feat(backend/ApiCallService): allow limited access for suspend accounts

This commit is contained in:
Kagami Sascha Rosylight 2023-08-13 15:30:19 +02:00
parent ab58b651f7
commit c28e0abb75
49 changed files with 109 additions and 55 deletions

View File

@ -276,17 +276,10 @@ export class ApiCallService implements OnApplicationShutdown {
id: '1384574d-a912-4b81-8601-c7b1c4085df1', id: '1384574d-a912-4b81-8601-c7b1c4085df1',
httpStatusCode: 401, httpStatusCode: 401,
}); });
} else if (user!.isSuspended) {
throw new ApiError({
message: 'Your account has been suspended.',
code: 'YOUR_ACCOUNT_SUSPENDED',
kind: 'permission',
id: 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370',
});
} }
} }
if (ep.meta.prohibitMoved) { if (ep.meta.prohibitDeactivated) {
if (user?.movedToUri) { if (user?.movedToUri) {
throw new ApiError({ throw new ApiError({
message: 'You have moved your account.', message: 'You have moved your account.',
@ -295,6 +288,14 @@ export class ApiCallService implements OnApplicationShutdown {
id: '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31', id: '56f20ec9-fd06-4fa5-841b-edd6d7d4fa31',
}); });
} }
if (user?.isSuspended) {
throw new ApiError({
message: 'Your account has been suspended.',
code: 'YOUR_ACCOUNT_SUSPENDED',
kind: 'permission',
id: 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370',
});
}
} }
if ((ep.meta.requireModerator || ep.meta.requireAdmin) && !user!.isRoot) { if ((ep.meta.requireModerator || ep.meta.requireAdmin) && !user!.isRoot) {

View File

@ -729,7 +729,7 @@ export interface IEndpointMeta {
* *
* false * false
*/ */
readonly prohibitMoved?: boolean; readonly prohibitDeactivated?: boolean;
/** /**
* *

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -16,7 +16,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:channels', kind: 'write:channels',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:channels', kind: 'write:channels',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:channels', kind: 'write:channels',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:channels', kind: 'write:channels',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:channels', kind: 'write:channels',

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -17,7 +17,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:clip-favorite', kind: 'write:clip-favorite',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:clip-favorite', kind: 'write:clip-favorite',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),

View File

@ -22,7 +22,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:drive', kind: 'write:drive',
} as const; } as const;

View File

@ -16,7 +16,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:flash', kind: 'write:flash',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:flash-likes', kind: 'write:flash-likes',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:flash-likes', kind: 'write:flash-likes',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:flash', kind: 'write:flash',

View File

@ -24,7 +24,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:following', kind: 'write:following',

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:gallery', kind: 'write:gallery',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:gallery-likes', kind: 'write:gallery-likes',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:gallery-likes', kind: 'write:gallery-likes',

View File

@ -16,7 +16,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:gallery', kind: 'write:gallery',

View File

@ -9,7 +9,7 @@ import { AchievementService, ACHIEVEMENT_TYPES } from '@/core/AchievementService
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
} as const; } as const;
export const paramDef = { export const paramDef = {

View File

@ -16,7 +16,7 @@ import { ApiError } from '../../error.js';
export const meta = { export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),

View File

@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = { export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),

View File

@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = { export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),
max: 1, max: 1,

View File

@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = { export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),

View File

@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = { export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),
max: 1, max: 1,

View File

@ -25,7 +25,7 @@ export const meta = {
secure: true, secure: true,
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1day'), duration: ms('1day'),
max: 5, max: 5,

View File

@ -13,7 +13,7 @@ export const meta = {
tags: ['account', 'notes'], tags: ['account', 'notes'],
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -16,7 +16,7 @@ export const meta = {
tags: ['account'], tags: ['account'],
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:mutes', kind: 'write:mutes',

View File

@ -23,7 +23,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
limit: { limit: {
duration: ms('1hour'), duration: ms('1hour'),

View File

@ -17,7 +17,7 @@ export const meta = {
tags: ['notes', 'favorites'], tags: ['notes', 'favorites'],
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:favorites', kind: 'write:favorites',

View File

@ -22,7 +22,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:votes', kind: 'write:votes',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:reactions', kind: 'write:reactions',

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:pages', kind: 'write:pages',

View File

@ -15,7 +15,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:page-likes', kind: 'write:page-likes',

View File

@ -14,7 +14,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:page-likes', kind: 'write:page-likes',

View File

@ -16,7 +16,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:pages', kind: 'write:pages',

View File

@ -17,7 +17,7 @@ export const meta = {
tags: ['account'], tags: ['account'],
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:mutes', kind: 'write:mutes',

View File

@ -17,7 +17,7 @@ import { UserListService } from '@/core/UserListService.js';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
res: { res: {
type: 'object', type: 'object',
optional: false, nullable: false, optional: false, nullable: false,

View File

@ -18,7 +18,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -17,7 +17,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -17,7 +17,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
prohibitMoved: true, prohibitDeactivated: true,
kind: 'write:account', kind: 'write:account',

View File

@ -0,0 +1,53 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
process.env.NODE_ENV = 'test';
import * as assert from 'assert';
import { loadConfig } from '@/config.js';
import { User, UsersRepository } from '@/models/index.js';
import { jobQueue } from '@/boot/common.js';
import { secureRndstr } from '@/misc/secure-rndstr.js';
import { uploadFile, signup, startServer, initTestDb, api, sleep, successfulApiCall } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js';
describe('Account Suspension', () => {
let app: INestApplicationContext;
let root: misskey.entities.MeSignup;
let alice: misskey.entities.MeSignup;
beforeAll(async () => {
app = await startServer();
root = await signup({ username: 'root' });
alice = await signup({ username: 'alice' });
await api('admin/suspend-user', { userId: alice.id }, root);
}, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
it('Cannot create notes', async () => {
const res = await api('notes/create', { text: 'foo' }, alice);
assert.strictEqual(res.status, 403);
assert.strictEqual(res.body.error.code, 'YOUR_ACCOUNT_SUSPENDED');
assert.strictEqual(res.body.error.id, 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370');
});
it('Can see notes', async () => {
const createRes = await api('notes/create', { text: 'bar' }, root);
assert.strictEqual(createRes.status, 200);
assert.strictEqual(createRes.body.createdNote.text, 'bar');
const showRes = await api('notes/show', { noteId: createRes.body.createdNote.id }, alice);
assert.strictEqual(showRes.status, 200);
assert.strictEqual(showRes.body.text, 'bar');
assert.strictEqual(showRes.body.id, createRes.body.createdNote.id);
});
});