forked from FoundKeyGang/FoundKey
server: improve error messages
Refactor Error's to ApiError's. Changelog: Changed
This commit is contained in:
parent
09bc3cf95a
commit
c2372315f7
26 changed files with 151 additions and 62 deletions
|
@ -1,5 +1,6 @@
|
|||
import { IsNull } from 'typeorm';
|
||||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
import { signup } from '../../../common/signup.js';
|
||||
|
||||
|
@ -17,6 +18,8 @@ export const meta = {
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -31,10 +34,17 @@ export const paramDef = {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, _me) => {
|
||||
const me = _me ? await Users.findOneByOrFail({ id: _me.id }) : null;
|
||||
const noUsers = (await Users.countBy({
|
||||
host: IsNull(),
|
||||
})) === 0;
|
||||
if (!noUsers && !me?.isAdmin) throw new Error('access denied');
|
||||
if (me == null) {
|
||||
// check if this is the initial setup
|
||||
const noUsers = (await Users.countBy({
|
||||
host: IsNull(),
|
||||
})) === 0;
|
||||
if (!noUsers) {
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
} else if (!me.isAdmin) {
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
const { account, secret } = await signup({
|
||||
username: ps.username,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { doPostSuspend } from '@/services/suspend-user.js';
|
||||
import { publishUserEvent } from '@/services/stream.js';
|
||||
import { createDeleteAccountJob } from '@/queue/index.js';
|
||||
|
@ -9,6 +10,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN', 'IS_MODERATOR'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -24,15 +27,11 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
if (user.isAdmin) {
|
||||
throw new Error('cannot suspend admin');
|
||||
}
|
||||
|
||||
if (user.isModerator) {
|
||||
throw new Error('cannot suspend moderator');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
} else if (user.isAdmin) {
|
||||
throw new ApiError('IS_ADMIN');
|
||||
} else if(user.isModerator) {
|
||||
throw new ApiError('IS_MODERATOR');
|
||||
}
|
||||
|
||||
if (Users.isLocalUser(user)) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Instances } from '@/models/index.js';
|
||||
import { toPuny } from '@/misc/convert-host.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
|
@ -8,6 +9,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_OBJECT'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,7 +26,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const instance = await Instances.findOneBy({ host: toPuny(ps.host) });
|
||||
|
||||
if (instance == null) {
|
||||
throw new Error('instance not found');
|
||||
throw new ApiError('NO_SUCH_OBJECT');
|
||||
}
|
||||
|
||||
fetchInstanceMetadata(instance, true);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Instances } from '@/models/index.js';
|
||||
import { toPuny } from '@/misc/convert-host.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -7,6 +8,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_OBJECT'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,7 +26,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const instance = await Instances.findOneBy({ host: toPuny(ps.host) });
|
||||
|
||||
if (instance == null) {
|
||||
throw new Error('instance not found');
|
||||
throw new ApiError('NO_SUCH_OBJECT');
|
||||
}
|
||||
|
||||
Instances.update({ host: toPuny(ps.host) }, {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { publishInternalEvent } from '@/services/stream.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
|
||||
description: 'Grants a user moderator privileges. Administrators cannot be granted moderator privileges.',
|
||||
|
||||
requireCredential: true,
|
||||
requireAdmin: true,
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -22,11 +27,11 @@ export default define(meta, paramDef, async (ps) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
if (user.isAdmin) {
|
||||
throw new Error('cannot mark as moderator if admin user');
|
||||
throw new ApiError('IS_ADMIN');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { publishInternalEvent } from '@/services/stream.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
|
@ -7,6 +8,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireAdmin: true,
|
||||
|
||||
errors: ['NO_SUCH_USER'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -22,7 +25,7 @@ export default define(meta, paramDef, async (ps) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -51,7 +51,7 @@ export const paramDef = {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
try {
|
||||
if (new URL(ps.inbox).protocol !== 'https:') throw new Error('https only');
|
||||
if (new URL(ps.inbox).protocol !== 'https:') throw new ApiError('INVALID_URL', 'https only');
|
||||
} catch (e) {
|
||||
throw new ApiError('INVALID_URL', e);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { secureRndstr } from '@/misc/secure-rndstr.js';
|
||||
import { Users, UserProfiles } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -21,6 +22,8 @@ export const meta = {
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -36,11 +39,11 @@ export default define(meta, paramDef, async (ps) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
if (user.isAdmin) {
|
||||
throw new Error('cannot reset password of admin');
|
||||
throw new ApiError('IS_ADMIN');
|
||||
}
|
||||
|
||||
const passwd = secureRndstr(8, true);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Signins, UserProfiles, Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -11,6 +12,8 @@ export const meta = {
|
|||
type: 'object',
|
||||
nullable: false, optional: false,
|
||||
},
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -29,12 +32,12 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
]);
|
||||
|
||||
if (user == null || profile == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
const _me = await Users.findOneByOrFail({ id: me.id });
|
||||
if ((_me.isModerator && !_me.isAdmin) && user.isAdmin) {
|
||||
throw new Error('cannot show info of admin');
|
||||
throw new ApiError('IS_ADMIN');
|
||||
}
|
||||
|
||||
if (!_me.isAdmin) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { insertModerationLog } from '@/services/insert-moderation-log.js';
|
||||
import { publishInternalEvent } from '@/services/stream.js';
|
||||
import define from '../../define.js';
|
||||
|
@ -8,6 +9,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,11 +26,11 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
if (user.isAdmin) {
|
||||
throw new Error('cannot silence admin');
|
||||
throw new ApiError('IS_ADMIN');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import deleteFollowing from '@/services/following/delete.js';
|
||||
import { Users, Followings, Notifications } from '@/models/index.js';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { insertModerationLog } from '@/services/insert-moderation-log.js';
|
||||
import { doPostSuspend } from '@/services/suspend-user.js';
|
||||
import { publishUserEvent } from '@/services/stream.js';
|
||||
|
@ -11,6 +12,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_USER', 'IS_ADMIN', 'IS_MODERATOR'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -26,15 +29,11 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
if (user.isAdmin) {
|
||||
throw new Error('cannot suspend admin');
|
||||
}
|
||||
|
||||
if (user.isModerator) {
|
||||
throw new Error('cannot suspend moderator');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
} else if (user.isAdmin) {
|
||||
throw new ApiError('IS_ADMIN');
|
||||
} else if (user.isModerator) {
|
||||
throw new ApiError('IS_MODERATOR');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { insertModerationLog } from '@/services/insert-moderation-log.js';
|
||||
import { publishInternalEvent } from '@/services/stream.js';
|
||||
import define from '../../define.js';
|
||||
|
@ -8,6 +9,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_USER'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,7 +26,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Users } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { insertModerationLog } from '@/services/insert-moderation-log.js';
|
||||
import { doPostUnsuspend } from '@/services/unsuspend-user.js';
|
||||
import define from '../../define.js';
|
||||
|
@ -8,6 +9,8 @@ export const meta = {
|
|||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
errors: ['NO_SUCH_USER'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,7 +26,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
const user = await Users.findOneBy({ id: ps.userId });
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
throw new ApiError('NO_SUCH_USER');
|
||||
}
|
||||
|
||||
await Users.update(user.id, {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { genId } from '@/misc/gen-id.js';
|
|||
import { GalleryPost } from '@/models/entities/gallery-post.js';
|
||||
import { DriveFile } from '@/models/entities/drive-file.js';
|
||||
import { HOUR } from '@/const.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -46,8 +47,14 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}),
|
||||
))).filter((file): file is DriveFile => file != null);
|
||||
|
||||
if (files.length === 0) {
|
||||
throw new Error();
|
||||
if (files.length !== ps.fileIds.length) {
|
||||
throw new ApiError(
|
||||
'INVALID_PARAM',
|
||||
{
|
||||
param: '#/properties/fileIds/items',
|
||||
reason: 'contains invalid file IDs',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const post = await GalleryPosts.insert(new GalleryPost({
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { DriveFiles, GalleryPosts } from '@/models/index.js';
|
||||
import { DriveFile } from '@/models/entities/drive-file.js';
|
||||
import { HOUR } from '@/const.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -20,6 +21,8 @@ export const meta = {
|
|||
optional: false, nullable: false,
|
||||
ref: 'GalleryPost',
|
||||
},
|
||||
|
||||
errors: ['INVALID_PARAM'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -45,8 +48,14 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
}),
|
||||
))).filter((file): file is DriveFile => file != null);
|
||||
|
||||
if (files.length === 0) {
|
||||
throw new Error();
|
||||
if (files.length !== ps.fileIds.length) {
|
||||
throw new ApiError(
|
||||
'INVALID_PARAM',
|
||||
{
|
||||
param: '#/properties/fileIds/items',
|
||||
reason: 'contains invalid file IDs',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
await GalleryPosts.update({
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import * as speakeasy from 'speakeasy';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
import define from '../../../define.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['INTERNAL_ERROR', 'ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -23,7 +26,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
|
||||
|
||||
if (profile.twoFactorTempSecret == null) {
|
||||
throw new Error('二段階認証の設定が開始されていません');
|
||||
throw new ApiError('INTERNAL_ERROR', 'Two-step verification has not been initiated.');
|
||||
}
|
||||
|
||||
const verified = (speakeasy as any).totp.verify({
|
||||
|
@ -33,7 +36,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
if (!verified) {
|
||||
throw new Error('not verified');
|
||||
throw new ApiError('ACCESS_DENIED', 'TOTP missmatch');
|
||||
}
|
||||
|
||||
await UserProfiles.update(user.id, {
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
Users,
|
||||
} from '@/models/index.js';
|
||||
import config from '@/config/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { publishMainStream } from '@/services/stream.js';
|
||||
import define from '../../../define.js';
|
||||
import { procedures, hash } from '../../../2fa.js';
|
||||
|
@ -20,6 +21,8 @@ export const meta = {
|
|||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED', 'INTERNAL_ERROR', 'NO_SUCH_OBJECT'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -42,20 +45,20 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
if (!profile.twoFactorEnabled) {
|
||||
throw new Error('2fa not enabled');
|
||||
throw new ApiError('INTERNAL_ERROR', '2fa not enabled');
|
||||
}
|
||||
|
||||
const clientData = JSON.parse(ps.clientDataJSON);
|
||||
|
||||
if (clientData.type !== 'webauthn.create') {
|
||||
throw new Error('not a creation attestation');
|
||||
throw new ApiError('INTERNAL_ERROR', 'not a creation attestation');
|
||||
}
|
||||
if (clientData.origin !== config.scheme + '://' + config.host) {
|
||||
throw new Error('origin mismatch');
|
||||
throw new ApiError('INTERNAL_ERROR', 'origin mismatch');
|
||||
}
|
||||
|
||||
const clientDataJSONHash = hash(Buffer.from(ps.clientDataJSON, 'utf-8'));
|
||||
|
@ -64,14 +67,14 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
|
||||
const rpIdHash = attestation.authData.slice(0, 32);
|
||||
if (!rpIdHashReal.equals(rpIdHash)) {
|
||||
throw new Error('rpIdHash mismatch');
|
||||
throw new ApiError('INTERNAL_ERROR', 'rpIdHash mismatch');
|
||||
}
|
||||
|
||||
const flags = attestation.authData[32];
|
||||
|
||||
// eslint:disable-next-line:no-bitwise
|
||||
if (!(flags & 1)) {
|
||||
throw new Error('user not present');
|
||||
throw new ApiError('INTERNAL_ERROR', 'user not present');
|
||||
}
|
||||
|
||||
const authData = Buffer.from(attestation.authData);
|
||||
|
@ -80,11 +83,11 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const publicKeyData = authData.slice(55 + credentialIdLength);
|
||||
const publicKey: Map<number, any> = await cborDecodeFirst(publicKeyData);
|
||||
if (publicKey.get(3) !== -7) {
|
||||
throw new Error('alg mismatch');
|
||||
throw new ApiError('INTERNAL_ERROR', 'algorithm mismatch');
|
||||
}
|
||||
|
||||
if (!(procedures as any)[attestation.fmt]) {
|
||||
throw new Error('unsupported fmt');
|
||||
throw new ApiError('INTERNAL_ERROR', 'unsupported fmt');
|
||||
}
|
||||
|
||||
const verificationData = (procedures as any)[attestation.fmt].verify({
|
||||
|
@ -95,7 +98,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
publicKey,
|
||||
rpIdHash,
|
||||
});
|
||||
if (!verificationData.valid) throw new Error('signature invalid');
|
||||
if (!verificationData.valid) throw new ApiError('INTERNAL_ERROR', 'signature invalid');
|
||||
|
||||
const attestationChallenge = await AttestationChallenges.findOneBy({
|
||||
userId: user.id,
|
||||
|
@ -105,7 +108,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
});
|
||||
|
||||
if (!attestationChallenge) {
|
||||
throw new Error('non-existent challenge');
|
||||
throw new ApiError('NO_SUCH_OBJECT', 'Attestation challenge not found.');
|
||||
}
|
||||
|
||||
await AttestationChallenges.delete({
|
||||
|
@ -118,7 +121,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
new Date().getTime() - attestationChallenge.createdAt.getTime() >=
|
||||
5 * MINUTE
|
||||
) {
|
||||
throw new Error('expired challenge');
|
||||
throw new ApiError('NO_SUCH_OBJECT', 'Attestation challenge expired.');
|
||||
}
|
||||
|
||||
const credentialIdString = credentialId.toString('hex');
|
||||
|
|
|
@ -3,6 +3,7 @@ import * as crypto from 'node:crypto';
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { UserProfiles, AttestationChallenges } from '@/models/index.js';
|
||||
import { genId } from '@/misc/gen-id.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
import { hash } from '../../../2fa.js';
|
||||
|
||||
|
@ -12,6 +13,8 @@ export const meta = {
|
|||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED', 'INTERNAL_ERROR'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -30,11 +33,11 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
if (!profile.twoFactorEnabled) {
|
||||
throw new Error('2fa not enabled');
|
||||
throw new ApiError('INTERNAL_ERROR', '2fa not enabled');
|
||||
}
|
||||
|
||||
// 32 byte challenge
|
||||
|
|
|
@ -3,12 +3,15 @@ import * as speakeasy from 'speakeasy';
|
|||
import * as QRCode from 'qrcode';
|
||||
import config from '@/config/index.js';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -27,7 +30,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
// Generate user's secret key
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { UserProfiles, UserSecurityKeys, Users } from '@/models/index.js';
|
||||
import { publishMainStream } from '@/services/stream.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -26,7 +29,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
// Make sure we only delete the user's own creds
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -24,7 +27,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
await UserProfiles.update(user.id, {
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -25,7 +28,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.currentPassword, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
// Generate hash of password
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import bcrypt from 'bcryptjs';
|
||||
import { UserProfiles, Users } from '@/models/index.js';
|
||||
import { deleteAccount } from '@/services/delete-account.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -29,7 +32,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
await deleteAccount(user);
|
||||
|
|
|
@ -2,12 +2,15 @@ import bcrypt from 'bcryptjs';
|
|||
import { publishInternalEvent, publishMainStream, publishUserEvent } from '@/services/stream.js';
|
||||
import { Users, UserProfiles } from '@/models/index.js';
|
||||
import generateUserToken from '../../common/generate-native-user-token.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../../define.js';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
secure: true,
|
||||
|
||||
errors: ['ACCESS_DENIED'],
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
@ -29,7 +32,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
||||
if (!same) {
|
||||
throw new Error('incorrect password');
|
||||
throw new ApiError('ACCESS_DENIED');
|
||||
}
|
||||
|
||||
const newToken = generateUserToken();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { resetDb } from '@/db/postgre.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import define from '../define.js';
|
||||
|
||||
export const meta = {
|
||||
|
@ -17,7 +18,7 @@ export const paramDef = {
|
|||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
if (process.env.NODE_ENV !== 'test') throw new Error('NODE_ENV is not a test');
|
||||
if (process.env.NODE_ENV !== 'test') throw new ApiError('ACCESS_DENIED');
|
||||
|
||||
await resetDb();
|
||||
|
||||
|
|
|
@ -187,6 +187,14 @@ export const errors: Record<string, { message: string, httpStatusCode: number }>
|
|||
message: 'Invalid username.',
|
||||
httpStatusCode: 400,
|
||||
},
|
||||
IS_ADMIN: {
|
||||
message: 'This action cannot be done to an administrator account.',
|
||||
httpStatusCode: 400,
|
||||
},
|
||||
IS_MODERATOR: {
|
||||
message: 'This action cannot be done to a moderator account.',
|
||||
httpStatusCode: 400,
|
||||
},
|
||||
LESS_RESTRICTIVE_VISIBILITY: {
|
||||
message: 'The visibility cannot be less restrictive than the parent note.',
|
||||
httpStatusCode: 400,
|
||||
|
|
Loading…
Reference in a new issue