feat(policies): account removal policy
This commit is contained in:
parent
fdb49bc2e4
commit
0ec6a0fbfb
9 changed files with 45 additions and 10 deletions
|
@ -68,6 +68,7 @@ export type RolePolicies = {
|
|||
userEachUserListsLimit: number;
|
||||
rateLimitFactor: number;
|
||||
avatarDecorationLimit: number;
|
||||
canUseAccountRemoval: boolean;
|
||||
};
|
||||
|
||||
export const DEFAULT_POLICIES: RolePolicies = {
|
||||
|
@ -106,6 +107,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
|||
userEachUserListsLimit: 50,
|
||||
rateLimitFactor: 1,
|
||||
avatarDecorationLimit: 1,
|
||||
canUseAccountRemoval: true,
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
@ -389,6 +391,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
|||
canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
|
||||
canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),
|
||||
canDeleteContent: calc('canDeleteContent', vs => vs.some(v => v === true)),
|
||||
canUseAccountRemoval: calc('canUseAccountRemoval', vs => vs.some(v => v === true)),
|
||||
canPurgeAccount: calc('canPurgeAccount', vs => vs.some(v => v === true)),
|
||||
canUpdateAvatar: calc('canUpdateAvatar', vs => vs.some(v => v === true)),
|
||||
canUpdateBanner: calc('canUpdateBanner', vs => vs.some(v => v === true)),
|
||||
|
|
|
@ -308,6 +308,10 @@ export const packedRolePoliciesSchema = {
|
|||
type: 'integer',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
canUseAccountRemoval: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||
import type { UsersRepository, UserProfilesRepository } from '@/models/_.js';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { DeleteAccountService } from '@/core/DeleteAccountService.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { UserAuthService } from '@/core/UserAuthService.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
|
@ -18,17 +19,21 @@ export const meta = {
|
|||
secure: true,
|
||||
|
||||
errors: {
|
||||
incorrectPassword: {
|
||||
message: 'Incorrect password.',
|
||||
code: 'INCORRECT_PASSWORD',
|
||||
id: '44326b04-08ea-4525-b01c-98cc117bdd2a',
|
||||
removalDisabled: {
|
||||
message: 'Account removal is disabled by your role.',
|
||||
code: 'REMOVAL_DISABLED',
|
||||
id: '453d954b-3d8b-4df0-a261-b26ec6660ea3',
|
||||
},
|
||||
|
||||
authenticationFailed: {
|
||||
message: 'Authentication failed.',
|
||||
message: 'Your password or 2FA token is invalid.',
|
||||
code: 'AUTHENTICATION_FAILED',
|
||||
id: 'ea791cff-63e7-4b2a-92fc-646ab641794e',
|
||||
},
|
||||
alreadyRemoved: {
|
||||
message: 'Your account is already removed.',
|
||||
code: 'ACCOUNT_REMOVED',
|
||||
id: '59b8f0e6-6eb2-4dc1-a080-1de3108416d0',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
|
@ -52,18 +57,24 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
private userAuthService: UserAuthService,
|
||||
private deleteAccountService: DeleteAccountService,
|
||||
private roleService: RoleService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id });
|
||||
|
||||
const policies = await this.roleService.getUserPolicies(me.id);
|
||||
if (!policies.canUseAccountRemoval) {
|
||||
throw new ApiError(meta.errors.removalDisabled);
|
||||
}
|
||||
|
||||
const userDetailed = await this.usersRepository.findOneByOrFail({ id: me.id });
|
||||
if (userDetailed.isDeleted) {
|
||||
return;
|
||||
throw new ApiError(meta.errors.alreadyRemoved);
|
||||
}
|
||||
|
||||
const passwordMatched = await bcrypt.compare(ps.password, profile.password!);
|
||||
if (!passwordMatched) {
|
||||
throw new ApiError(meta.errors.incorrectPassword);
|
||||
throw new ApiError(meta.errors.authenticationFailed);
|
||||
}
|
||||
|
||||
if (profile.twoFactorEnabled) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue