core&ui: add error & fix error notification (#464)

This commit is contained in:
panda authored and GitHub committed 2022-11-26 20:30:18 +08:00
1 parent a2ea3812df
commit 534a634028
14 files changed
+123 -76

No files matched your search

+14 -14
View File
@@ -2,8 +2,8 @@ import moment from 'moment-timezone';
import notp from 'notp';
import b32 from 'thirty-two';
import {
BlacklistedError, ForbiddenError, InvalidTokenError, LoginError,
SystemError, UserAlreadyExistError, UserFacingError,
BlacklistedError, BuiltinLoginError, ForbiddenError, InvalidTokenError,
SystemError, TFAOperationError, UserAlreadyExistError, UserFacingError,
UserNotFoundError, ValidationError, VerifyPasswordError,
} from '../error';
import { Udoc, User } from '../interface';
@@ -53,8 +53,8 @@ registerResolver(
registerResolver(
'TFAContext', 'enable(secret: String!, code: String!)', 'Boolean!',
async (arg, ctx) => {
if (ctx.user._tfa) throw new Error('2FA is already enabled');
if (!verifyToken(arg.secret, arg.code)) throw new Error('Invalid 2FA code');
if (ctx.user._tfa) throw new TFAOperationError('enabled');
if (!verifyToken(arg.secret, arg.code)) throw new InvalidTokenError('2FA');
await user.setById(ctx.user._id, { tfa: arg.secret });
// TODO: return backup codes
return true;
@@ -64,8 +64,8 @@ registerResolver(
registerResolver(
'TFAContext', 'disable(code: String!)', 'Boolean!',
async (arg, ctx) => {
if (!ctx.user._tfa) throw new Error('2FA is already disabled');
if (!verifyToken(ctx.user._tfa, arg.code)) throw new Error('Invalid 2FA code');
if (!ctx.user._tfa) throw new TFAOperationError('disabled');
if (!verifyToken(ctx.user._tfa, arg.code)) throw new InvalidTokenError('2FA');
await user.setById(ctx.user._id, undefined, { tfa: '' });
return true;
},
@@ -106,7 +106,7 @@ class UserLoginHandler extends Handler {
noCheckPermView = true;
async get() {
if (!system.get('server.login')) throw new LoginError('Builtin login disabled.');
if (!system.get('server.login')) throw new BuiltinLoginError();
this.response.template = 'user_login.html';
}
@@ -116,7 +116,7 @@ class UserLoginHandler extends Handler {
@param('redirect', Types.String, true)
@param('tfa', Types.String, true)
async post(domainId: string, uname: string, password: string, rememberme = false, redirect = '', tfa = '') {
if (!system.get('server.login')) throw new LoginError('Builtin login disabled.');
if (!system.get('server.login')) throw new BuiltinLoginError();
let udoc = await user.getByEmail(domainId, uname);
if (!udoc) udoc = await user.getByUname(domainId, uname);
if (!udoc) throw new UserNotFoundError(uname);
@@ -125,7 +125,7 @@ class UserLoginHandler extends Handler {
this.limitRate(`user_login_${uname}`, 60, 5, false),
oplog.log(this, 'user.login', { redirect }),
]);
if (udoc._tfa && !verifyToken(udoc._tfa, tfa)) throw new InvalidTokenError('2FA token invalid.');
if (udoc._tfa && !verifyToken(udoc._tfa, tfa)) throw new InvalidTokenError('2FA');
udoc.checkPassword(password);
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
if (!udoc.hasPriv(PRIV.PRIV_USER_PROFILE)) throw new BlacklistedError(uname);
@@ -156,7 +156,7 @@ class UserSudoHandler extends Handler {
oplog.log(this, 'user.sudo', {}),
]);
if (tfa) {
if (!this.user._tfa || !verifyToken(this.user._tfa, tfa)) throw new InvalidTokenError('2FA token invalid.');
if (!this.user._tfa || !verifyToken(this.user._tfa, tfa)) throw new InvalidTokenError('2FA');
} else {
this.user.checkPassword(password);
}
@@ -241,7 +241,7 @@ class UserRegisterWithCodeHandler extends Handler {
async get(domainId: string, code: string) {
this.response.template = 'user_register_with_code.html';
const tdoc = await token.get(code, token.TYPE_REGISTRATION);
if (!tdoc) throw new InvalidTokenError(token.TYPE_REGISTRATION, code);
if (!tdoc) throw new InvalidTokenError(token.TYPE_TEXTS[token.TYPE_REGISTRATION], code);
this.response.body = tdoc;
}
@@ -254,7 +254,7 @@ class UserRegisterWithCodeHandler extends Handler {
uname: string, code: string,
) {
const tdoc = await token.get(code, token.TYPE_REGISTRATION);
if (!tdoc || (!tdoc.mail && !tdoc.phone)) throw new InvalidTokenError(token.TYPE_REGISTRATION, code);
if (!tdoc || (!tdoc.mail && !tdoc.phone)) throw new InvalidTokenError(token.TYPE_TEXTS[token.TYPE_REGISTRATION], code);
if (password !== verify) throw new VerifyPasswordError();
if (tdoc.phone) tdoc.mail = `${tdoc.phone}@hydro.local`;
const uid = await user.create(tdoc.mail, uname, password, undefined, this.request.ip);
@@ -305,7 +305,7 @@ class UserLostPassWithCodeHandler extends Handler {
async get({ domainId, code }) {
const tdoc = await token.get(code, token.TYPE_LOSTPASS);
if (!tdoc) throw new InvalidTokenError(token.TYPE_LOSTPASS, code);
if (!tdoc) throw new InvalidTokenError(token.TYPE_TEXTS[token.TYPE_LOSTPASS], code);
const udoc = await user.getById(domainId, tdoc.uid);
this.response.body = { uname: udoc.uname };
this.response.template = 'user_lostpass_with_code.html';
@@ -316,7 +316,7 @@ class UserLostPassWithCodeHandler extends Handler {
@param('verifyPassword', Types.String)
async post(domainId: string, code: string, password: string, verifyPassword: string) {
const tdoc = await token.get(code, token.TYPE_LOSTPASS);
if (!tdoc) throw new InvalidTokenError(token.TYPE_LOSTPASS, code);
if (!tdoc) throw new InvalidTokenError(token.TYPE_TEXTS[token.TYPE_LOSTPASS], code);
if (password !== verifyPassword) throw new VerifyPasswordError();
await user.setPassword(tdoc.uid, password);
await token.del(code, token.TYPE_LOSTPASS);