Account API endpoint fixes
parent
f79348817f
commit
7ca9afad57
|
@ -22,7 +22,6 @@ type fileCache struct {
|
|||
dir string
|
||||
totalSizeCurrent int64
|
||||
totalSizeLimit int64
|
||||
fileSizeLimit int64
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
|
|
|
@ -50,14 +50,11 @@ import (
|
|||
- figure out what settings are "web" or "phone"
|
||||
UI:
|
||||
- Subscription dotmenu dropdown: Move to nav bar, or make same as profile dropdown
|
||||
- "Logout and delete local storage" option
|
||||
- Delete local storage when deleting account
|
||||
Pages:
|
||||
- Home
|
||||
- Password reset
|
||||
- Pricing
|
||||
- change email
|
||||
-
|
||||
Polishing:
|
||||
aria-label for everything
|
||||
Tests:
|
||||
|
@ -345,6 +342,8 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit
|
|||
return s.handleHealth(w, r, v)
|
||||
} else if r.Method == http.MethodGet && r.URL.Path == webConfigPath {
|
||||
return s.ensureWebEnabled(s.handleWebConfig)(w, r, v)
|
||||
} else if r.Method == http.MethodPost && r.URL.Path == accountTokenPath {
|
||||
return s.ensureAccountsEnabled(s.handleAccountTokenIssue)(w, r, v)
|
||||
} else if r.Method == http.MethodPost && r.URL.Path == accountPath {
|
||||
return s.ensureAccountsEnabled(s.handleAccountCreate)(w, r, v)
|
||||
} else if r.Method == http.MethodGet && r.URL.Path == accountPath {
|
||||
|
@ -353,8 +352,6 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit
|
|||
return s.ensureWithAccount(s.handleAccountDelete)(w, r, v)
|
||||
} else if r.Method == http.MethodPost && r.URL.Path == accountPasswordPath {
|
||||
return s.ensureWithAccount(s.handleAccountPasswordChange)(w, r, v)
|
||||
} else if r.Method == http.MethodPost && r.URL.Path == accountTokenPath {
|
||||
return s.ensureWithAccount(s.handleAccountTokenIssue)(w, r, v)
|
||||
} else if r.Method == http.MethodPatch && r.URL.Path == accountTokenPath {
|
||||
return s.ensureWithAccount(s.handleAccountTokenExtend)(w, r, v)
|
||||
} else if r.Method == http.MethodDelete && r.URL.Path == accountTokenPath {
|
||||
|
@ -1408,7 +1405,7 @@ func (s *Server) ensureWebEnabled(next handleFunc) handleFunc {
|
|||
|
||||
func (s *Server) ensureAccountsEnabled(next handleFunc) handleFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
if s.userManager != nil {
|
||||
if s.userManager == nil {
|
||||
return errHTTPNotFound
|
||||
}
|
||||
return next(w, r, v)
|
||||
|
@ -1417,7 +1414,7 @@ func (s *Server) ensureAccountsEnabled(next handleFunc) handleFunc {
|
|||
|
||||
func (s *Server) ensureWithAccount(next handleFunc) handleFunc {
|
||||
return s.ensureAccountsEnabled(func(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
if v.user != nil {
|
||||
if v.user == nil {
|
||||
return errHTTPNotFound
|
||||
}
|
||||
return next(w, r, v)
|
||||
|
|
|
@ -243,6 +243,7 @@ func (a *Manager) RemoveExpiredTokens() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ChangeSettings persists the user settings
|
||||
func (a *Manager) ChangeSettings(user *User) error {
|
||||
settings, err := json.Marshal(user.Prefs)
|
||||
if err != nil {
|
||||
|
@ -254,6 +255,8 @@ func (a *Manager) ChangeSettings(user *User) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// EnqueueStats adds the user to a queue which writes out user stats (messages, emails, ..) in
|
||||
// batches at a regular interval
|
||||
func (a *Manager) EnqueueStats(user *User) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
|
|
@ -244,6 +244,7 @@ func TestManager_Token_Valid(t *testing.T) {
|
|||
|
||||
// Create token for user
|
||||
token, err := a.CreateToken(u)
|
||||
require.Nil(t, err)
|
||||
require.NotEmpty(t, token.Value)
|
||||
require.True(t, time.Now().Add(71*time.Hour).Unix() < token.Expires.Unix())
|
||||
|
||||
|
|
|
@ -45,12 +45,12 @@ class AccountApi {
|
|||
return json.token;
|
||||
}
|
||||
|
||||
async logout(token) {
|
||||
async logout() {
|
||||
const url = accountTokenUrl(config.baseUrl);
|
||||
console.log(`[AccountApi] Logging out from ${url} using token ${token}`);
|
||||
console.log(`[AccountApi] Logging out from ${url} using token ${session.token()}`);
|
||||
const response = await fetch(url, {
|
||||
method: "DELETE",
|
||||
headers: withBearerAuth({}, token)
|
||||
headers: withBearerAuth({}, session.token())
|
||||
});
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
throw new UnauthorizedError();
|
||||
|
|
|
@ -57,7 +57,7 @@ const Stats = () => {
|
|||
const { t } = useTranslation();
|
||||
const { account } = useOutletContext();
|
||||
if (!account) {
|
||||
return <></>; // TODO loading
|
||||
return <></>;
|
||||
}
|
||||
const accountType = account.plan.code ?? "none";
|
||||
const normalize = (value, max) => (value / max * 100);
|
||||
|
@ -234,9 +234,9 @@ const DeleteAccount = () => {
|
|||
const handleDialogSubmit = async (newPassword) => {
|
||||
try {
|
||||
await accountApi.delete();
|
||||
await db.delete();
|
||||
setDialogOpen(false);
|
||||
console.debug(`[Account] Account deleted`);
|
||||
// TODO delete local storage
|
||||
session.resetAndRedirect(routes.app);
|
||||
} catch (e) {
|
||||
console.log(`[Account] Error deleting account`, e);
|
||||
|
|
|
@ -8,6 +8,7 @@ import * as React from "react";
|
|||
import {useEffect, useRef, useState} from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
import {formatShortDateTime, shuffle, topicDisplayName} from "../app/utils";
|
||||
import db from "../app/db";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import ClickAwayListener from '@mui/material/ClickAwayListener';
|
||||
import Grow from '@mui/material/Grow';
|
||||
|
@ -270,6 +271,7 @@ const ProfileIcon = (props) => {
|
|||
const handleLogout = async () => {
|
||||
try {
|
||||
await accountApi.logout();
|
||||
await db.delete();
|
||||
} finally {
|
||||
session.resetAndRedirect(routes.app);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue