refactor: use ajv instead of cafy (#8324)

* wip

* wip

* Update abuse-user-reports.ts

* Update files.ts

* Update list-remote.ts

* Update list.ts

* Update show-users.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update update.ts

* Update search.ts

* Update reactions.ts

* Update search.ts

* wip

* wip

* wip

* wip

* Update update.ts

* Update relation.ts

* Update available.ts

* wip

* wip

* wip

* Update packages/backend/src/server/api/define.ts

Co-authored-by: Johann150 <johann.galle@protonmail.com>

* Update define.ts

* Update define.ts

* typo

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update update.ts

* wip

* Update signup.ts

* Update call.ts

* minimum for limit

* type

* remove needless annotation

* wip

* Update signup.ts

* wip

* wip

* fix

* Update create.ts

Co-authored-by: Johann150 <johann.galle@protonmail.com>
This commit is contained in:
syuilo
2022-02-19 14:05:32 +09:00
committed by GitHub
parent 59785ea04c
commit 510de87607
320 changed files with 4395 additions and 5939 deletions

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as speakeasy from 'speakeasy';
import define from '../../../define';
import { UserProfiles } from '@/models/index';
@@ -7,16 +6,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
token: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
token: { type: 'string' },
},
required: ['token'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const token = ps.token.replace(/\s/g, '');
const profile = await UserProfiles.findOneOrFail(user.id);

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import { promisify } from 'util';
import * as cbor from 'cbor';
@@ -14,35 +13,28 @@ import { procedures, hash } from '../../../2fa';
import { publishMainStream } from '@/services/stream';
const cborDecodeFirst = promisify(cbor.decodeFirst) as any;
const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8'));
export const meta = {
requireCredential: true,
secure: true,
params: {
clientDataJSON: {
validator: $.str,
},
attestationObject: {
validator: $.str,
},
password: {
validator: $.str,
},
challengeId: {
validator: $.str,
},
name: {
validator: $.str,
},
},
} as const;
const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8'));
const paramDef = {
type: 'object',
properties: {
clientDataJSON: { type: 'string' },
attestationObject: { type: 'string' },
password: { type: 'string' },
challengeId: { type: 'string' },
name: { type: 'string' },
},
required: ['clientDataJSON', 'attestationObject', 'password', 'challengeId', 'name'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { UserProfiles } from '@/models/index';
@@ -6,16 +5,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
value: {
validator: $.boolean,
},
const paramDef = {
type: 'object',
properties: {
value: { type: 'boolean' },
},
required: ['value'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
await UserProfiles.update(user.id, {
usePasswordLessLogin: ps.value,
});

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import define from '../../../define';
import { UserProfiles, AttestationChallenges } from '@/models/index';
@@ -13,16 +12,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import * as speakeasy from 'speakeasy';
import * as QRCode from 'qrcode';
@@ -10,16 +9,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import define from '../../../define';
import { UserProfiles, UserSecurityKeys, Users } from '@/models/index';
@@ -8,19 +7,19 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
credentialId: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
credentialId: { type: 'string' },
},
required: ['password', 'credentialId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import define from '../../../define';
import { UserProfiles } from '@/models/index';
@@ -7,16 +6,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../define';
import { AccessTokens } from '@/models/index';
@@ -6,21 +5,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
sort: {
validator: $.optional.str.or([
'+createdAt',
'-createdAt',
'+lastUsedAt',
'-lastUsedAt',
]),
},
const paramDef = {
type: 'object',
properties: {
sort: { type: 'string', enum: ['+createdAt', '-createdAt', '+lastUsedAt', '-lastUsedAt'] },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = AccessTokens.createQueryBuilder('token')
.where('token.userId = :userId', { userId: user.id });

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../define';
import { AccessTokens, Apps } from '@/models/index';
@@ -6,33 +5,26 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
offset: {
validator: $.optional.num.min(0),
default: 0,
},
sort: {
validator: $.optional.str.or('desc|asc'),
default: 'desc',
},
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
offset: { type: 'integer', default: 0 },
sort: { type: 'string', enum: ['desc', 'asc'], default: "desc" },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
// Get tokens
const tokens = await AccessTokens.find({
where: {
userId: user.id,
},
take: ps.limit!,
take: ps.limit,
skip: ps.offset,
order: {
id: ps.sort == 'asc' ? 1 : -1,

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import define from '../../define';
import { UserProfiles } from '@/models/index';
@@ -7,20 +6,19 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
currentPassword: {
validator: $.str,
},
newPassword: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
currentPassword: { type: 'string' },
newPassword: { type: 'string', minLength: 1 },
},
required: ['currentPassword', 'newPassword'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import define from '../../define';
import { UserProfiles, Users } from '@/models/index';
@@ -10,16 +9,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
const userDetailed = await Users.findOneOrFail(user.id);
if (userDetailed.isDeleted) {

View File

@@ -11,7 +11,13 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
createExportBlockingJob(user);
});

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../define';
import { createExportFollowingJob } from '@/queue/index';
import ms from 'ms';
@@ -10,19 +9,18 @@ export const meta = {
duration: ms('1hour'),
max: 1,
},
params: {
excludeMuting: {
validator: $.optional.bool,
default: false,
},
excludeInactive: {
validator: $.optional.bool,
default: false,
},
} as const;
const paramDef = {
type: 'object',
properties: {
excludeMuting: { type: 'boolean', default: false },
excludeInactive: { type: 'boolean', default: false },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
createExportFollowingJob(user, ps.excludeMuting, ps.excludeInactive);
});

View File

@@ -11,7 +11,13 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
createExportMuteJob(user);
});

View File

@@ -11,7 +11,13 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
createExportNotesJob(user);
});

View File

@@ -11,7 +11,13 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
createExportUserListsJob(user);
});

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { NoteFavorites } from '@/models/index';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:favorites',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'array',
optional: false, nullable: false,
@@ -37,14 +20,24 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(NoteFavorites.createQueryBuilder('favorite'), ps.sinceId, ps.untilId)
.andWhere(`favorite.userId = :meId`, { meId: user.id })
.leftJoinAndSelect('favorite.note', 'note');
const favorites = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await NoteFavorites.packMany(favorites, user);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../../define';
import { GalleryLikes } from '@/models/index';
import { makePaginationQuery } from '../../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:gallery-likes',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'object',
optional: false, nullable: false,
@@ -44,14 +27,24 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(GalleryLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
.andWhere(`like.userId = :meId`, { meId: user.id })
.leftJoinAndSelect('like.post', 'post');
const likes = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await GalleryLikes.packMany(likes, user);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../../define';
import { GalleryPosts } from '@/models/index';
import { makePaginationQuery } from '../../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:gallery',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'array',
optional: false, nullable: false,
@@ -37,13 +20,23 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
.andWhere(`post.userId = :meId`, { meId: user.id });
const posts = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await GalleryPosts.packMany(posts, user);

View File

@@ -8,9 +8,6 @@ export const meta = {
kind: 'read:account',
params: {
},
res: {
type: 'object',
optional: false, nullable: false,
@@ -23,8 +20,14 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
return {
count: await MutedNotes.count({
userId: user.id,

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { createImportBlockingJob } from '@/queue/index';
import ms from 'ms';
@@ -15,12 +13,6 @@ export const meta = {
max: 1,
},
params: {
fileId: {
validator: $.type(ID),
},
},
errors: {
noSuchFile: {
message: 'No such file.',
@@ -48,8 +40,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOne(ps.fileId);
if (file == null) throw new ApiError(meta.errors.noSuchFile);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { createImportFollowingJob } from '@/queue/index';
import ms from 'ms';
@@ -14,12 +12,6 @@ export const meta = {
max: 1,
},
params: {
fileId: {
validator: $.type(ID),
},
},
errors: {
noSuchFile: {
message: 'No such file.',
@@ -47,8 +39,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOne(ps.fileId);
if (file == null) throw new ApiError(meta.errors.noSuchFile);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { createImportMutingJob } from '@/queue/index';
import ms from 'ms';
@@ -15,12 +13,6 @@ export const meta = {
max: 1,
},
params: {
fileId: {
validator: $.type(ID),
},
},
errors: {
noSuchFile: {
message: 'No such file.',
@@ -48,8 +40,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOne(ps.fileId);
if (file == null) throw new ApiError(meta.errors.noSuchFile);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { createImportUserListsJob } from '@/queue/index';
import ms from 'ms';
@@ -14,12 +12,6 @@ export const meta = {
max: 1,
},
params: {
fileId: {
validator: $.type(ID),
},
},
errors: {
noSuchFile: {
message: 'No such file.',
@@ -47,8 +39,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
fileId: { type: 'string', format: 'misskey:id' },
},
required: ['fileId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const file = await DriveFiles.findOne(ps.fileId);
if (file == null) throw new ApiError(meta.errors.noSuchFile);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import { readNotification } from '../../common/read-notification';
import define from '../../define';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -16,44 +14,6 @@ export const meta = {
kind: 'read:notifications',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
following: {
validator: $.optional.bool,
default: false,
},
unreadOnly: {
validator: $.optional.bool,
default: false,
},
markAsRead: {
validator: $.optional.bool,
default: true,
},
includeTypes: {
validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])),
},
excludeTypes: {
validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])),
},
},
res: {
type: 'array',
optional: false, nullable: false,
@@ -65,8 +25,27 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
following: { type: 'boolean', default: false },
unreadOnly: { type: 'boolean', default: false },
markAsRead: { type: 'boolean', default: true },
includeTypes: { type: 'array', items: {
type: 'string', enum: notificationTypes,
} },
excludeTypes: { type: 'array', items: {
type: 'string', enum: notificationTypes,
} },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
// includeTypes が空の場合はクエリしない
if (ps.includeTypes && ps.includeTypes.length === 0) {
return [];
@@ -125,7 +104,7 @@ export default define(meta, async (ps, user) => {
query.andWhere(`notification.isRead = false`);
}
const notifications = await query.take(ps.limit!).getMany();
const notifications = await query.take(ps.limit).getMany();
// Mark all as read
if (notifications.length > 0 && ps.markAsRead) {

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { PageLikes } from '@/models/index';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:page-likes',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'object',
optional: false, nullable: false,
@@ -44,14 +27,24 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(PageLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
.andWhere(`like.userId = :meId`, { meId: user.id })
.leftJoinAndSelect('like.page', 'page');
const likes = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await PageLikes.packMany(likes, user);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { Pages } from '@/models/index';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:pages',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'array',
optional: false, nullable: false,
@@ -37,13 +20,23 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
.andWhere(`page.userId = :meId`, { meId: user.id });
const pages = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await Pages.packMany(pages);

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import { addPinned } from '@/services/i/pin';
import define from '../../define';
import { ApiError } from '../../error';
@@ -12,12 +10,6 @@ export const meta = {
kind: 'write:account',
params: {
noteId: {
validator: $.type(ID),
},
},
errors: {
noSuchNote: {
message: 'No such note.',
@@ -45,8 +37,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
noteId: { type: 'string', format: 'misskey:id' },
},
required: ['noteId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
await addPinned(user, ps.noteId).catch(e => {
if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote);
if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError(meta.errors.pinLimitExceeded);

View File

@@ -8,13 +8,16 @@ export const meta = {
requireCredential: true,
kind: 'write:account',
} as const;
params: {
},
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
// Update documents
await MessagingMessages.update({
recipientId: user.id,

View File

@@ -8,13 +8,16 @@ export const meta = {
requireCredential: true,
kind: 'write:account',
} as const;
params: {
},
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
// Remove documents
await NoteUnreads.delete({
userId: user.id,

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { ApiError } from '../../error';
import { genId } from '@/misc/gen-id';
@@ -13,12 +11,6 @@ export const meta = {
kind: 'write:account',
params: {
announcementId: {
validator: $.type(ID),
},
},
errors: {
noSuchAnnouncement: {
message: 'No such announcement.',
@@ -28,8 +20,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
announcementId: { type: 'string', format: 'misskey:id' },
},
required: ['announcementId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
// Check if announcement exists
const announcement = await Announcements.findOne(ps.announcementId);

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import * as bcrypt from 'bcryptjs';
import { publishMainStream, publishUserEvent } from '@/services/stream';
import generateUserToken from '../../common/generate-native-user-token';
@@ -9,16 +8,18 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
password: {
validator: $.str,
},
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
@@ -6,17 +5,20 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
const paramDef = {
type: 'object',
properties: {
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
import { ApiError } from '../../../error';
@@ -8,17 +7,6 @@ export const meta = {
secure: true,
params: {
key: {
validator: $.str,
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
@@ -28,8 +16,19 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
key: { type: 'string' },
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: ['key'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
import { ApiError } from '../../../error';
@@ -8,17 +7,6 @@ export const meta = {
secure: true,
params: {
key: {
validator: $.str,
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
@@ -28,8 +16,19 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
key: { type: 'string' },
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: ['key'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
@@ -6,17 +5,20 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
const paramDef = {
type: 'object',
properties: {
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
@@ -6,17 +5,20 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
const paramDef = {
type: 'object',
properties: {
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.select('item.key')
.where('item.domain IS NULL')

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
import { ApiError } from '../../../error';
@@ -8,17 +7,6 @@ export const meta = {
secure: true,
params: {
key: {
validator: $.str,
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
},
errors: {
noSuchKey: {
message: 'No such key.',
@@ -28,8 +16,19 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
key: { type: 'string' },
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: ['key'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -5,13 +5,16 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
},
const paramDef = {
type: 'object',
properties: {},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.select('item.scope')
.where('item.domain IS NULL')

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import { publishMainStream } from '@/services/stream';
import define from '../../../define';
import { RegistryItems } from '@/models/index';
@@ -8,25 +7,22 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
key: {
validator: $.str.min(1),
},
value: {
validator: $.nullable.any,
},
scope: {
validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)),
default: [],
},
const paramDef = {
type: 'object',
properties: {
key: { type: 'string', minLength: 1 },
value: {},
scope: { type: 'array', default: [], items: {
type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1),
} },
},
required: ['key', 'value'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = RegistryItems.createQueryBuilder('item')
.where('item.domain IS NULL')
.andWhere('item.userId = :userId', { userId: user.id })

View File

@@ -1,23 +1,23 @@
import $ from 'cafy';
import define from '../../define';
import { AccessTokens } from '@/models/index';
import { ID } from '@/misc/cafy-id';
import { publishUserEvent } from '@/services/stream';
export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
tokenId: {
validator: $.type(ID),
},
const paramDef = {
type: 'object',
properties: {
tokenId: { type: 'string', format: 'misskey:id' },
},
required: ['tokenId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const token = await AccessTokens.findOne(ps.tokenId);
if (token) {

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { Signins } from '@/models/index';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -8,29 +6,24 @@ export const meta = {
requireCredential: true,
secure: true,
} as const;
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId)
.andWhere(`signin.userId = :meId`, { meId: user.id });
const history = await query.take(ps.limit!).getMany();
const history = await query.take(ps.limit).getMany();
return await Promise.all(history.map(record => Signins.pack(record)));
});

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import { removePinned } from '@/services/i/pin';
import define from '../../define';
import { ApiError } from '../../error';
@@ -12,12 +10,6 @@ export const meta = {
kind: 'write:account',
params: {
noteId: {
validator: $.type(ID),
},
},
errors: {
noSuchNote: {
message: 'No such note.',
@@ -33,8 +25,16 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
noteId: { type: 'string', format: 'misskey:id' },
},
required: ['noteId'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
await removePinned(user, ps.noteId).catch(e => {
if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote);
throw e;

View File

@@ -1,4 +1,3 @@
import $ from 'cafy';
import { publishMainStream } from '@/services/stream';
import define from '../../define';
import rndstr from 'rndstr';
@@ -20,16 +19,6 @@ export const meta = {
max: 3,
},
params: {
password: {
validator: $.str,
},
email: {
validator: $.optional.nullable.str,
},
},
errors: {
incorrectPassword: {
message: 'Incorrect password.',
@@ -45,8 +34,17 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
password: { type: 'string' },
email: { type: 'string', nullable: true },
},
required: ['password'],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const profile = await UserProfiles.findOneOrFail(user.id);
// Compare password

View File

@@ -1,7 +1,5 @@
const RE2 = require('re2');
import $ from 'cafy';
import * as mfm from 'mfm-js';
import { ID } from '@/misc/cafy-id';
import { publishMainStream, publishUserEvent } from '@/services/stream';
import acceptAllFollowRequests from '@/services/following/requests/accept-all';
import { publishToFollowers } from '@/services/i/update';
@@ -24,116 +22,6 @@ export const meta = {
kind: 'write:account',
params: {
name: {
validator: $.optional.nullable.use(Users.validateName),
},
description: {
validator: $.optional.nullable.use(Users.validateDescription),
},
lang: {
validator: $.optional.nullable.str.or(Object.keys(langmap)),
},
location: {
validator: $.optional.nullable.use(Users.validateLocation),
},
birthday: {
validator: $.optional.nullable.use(Users.validateBirthday),
},
avatarId: {
validator: $.optional.nullable.type(ID),
},
bannerId: {
validator: $.optional.nullable.type(ID),
},
fields: {
validator: $.optional.arr($.object()).range(1, 4),
},
isLocked: {
validator: $.optional.bool,
},
isExplorable: {
validator: $.optional.bool,
},
hideOnlineStatus: {
validator: $.optional.bool,
},
publicReactions: {
validator: $.optional.bool,
},
ffVisibility: {
validator: $.optional.str,
},
carefulBot: {
validator: $.optional.bool,
},
autoAcceptFollowed: {
validator: $.optional.bool,
},
noCrawle: {
validator: $.optional.bool,
},
isBot: {
validator: $.optional.bool,
},
isCat: {
validator: $.optional.bool,
},
showTimelineReplies: {
validator: $.optional.bool,
},
injectFeaturedNote: {
validator: $.optional.bool,
},
receiveAnnouncementEmail: {
validator: $.optional.bool,
},
alwaysMarkNsfw: {
validator: $.optional.bool,
},
pinnedPageId: {
validator: $.optional.nullable.type(ID),
},
mutedWords: {
validator: $.optional.arr($.either($.arr($.str.min(1)).min(1), $.str)),
},
mutedInstances: {
validator: $.optional.arr($.str),
},
mutingNotificationTypes: {
validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])),
},
emailNotificationTypes: {
validator: $.optional.arr($.str),
},
},
errors: {
noSuchAvatar: {
message: 'No such avatar file.',
@@ -179,8 +67,60 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
name: { ...Users.nameSchema, nullable: true },
description: { ...Users.descriptionSchema, nullable: true },
location: { ...Users.locationSchema, nullable: true },
birthday: { ...Users.birthdaySchema, nullable: true },
lang: { type: 'string', enum: Object.keys(langmap), nullable: true },
avatarId: { type: 'string', format: 'misskey:id', nullable: true },
bannerId: { type: 'string', format: 'misskey:id', nullable: true },
fields: { type: 'array',
minItems: 0,
maxItems: 8,
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' },
},
required: ['name', 'value'],
},
},
isLocked: { type: 'boolean' },
isExplorable: { type: 'boolean' },
hideOnlineStatus: { type: 'boolean' },
publicReactions: { type: 'boolean' },
carefulBot: { type: 'boolean' },
autoAcceptFollowed: { type: 'boolean' },
noCrawle: { type: 'boolean' },
isBot: { type: 'boolean' },
isCat: { type: 'boolean' },
showTimelineReplies: { type: 'boolean' },
injectFeaturedNote: { type: 'boolean' },
receiveAnnouncementEmail: { type: 'boolean' },
alwaysMarkNsfw: { type: 'boolean' },
ffVisibility: { type: 'string', enum: ['public', 'followers', 'private'] },
pinnedPageId: { type: 'array', items: {
type: 'string', format: 'misskey:id',
} },
mutedWords: { type: 'array' },
mutedInstances: { type: 'array', items: {
type: 'string',
} },
mutingNotificationTypes: { type: 'array', items: {
type: 'string', enum: notificationTypes,
} },
emailNotificationTypes: { type: 'array', items: {
type: 'string',
} },
},
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, _user, token) => {
export default define(meta, paramDef, async (ps, _user, token) => {
const user = await Users.findOneOrFail(_user.id);
const isSecure = token == null;

View File

@@ -1,5 +1,3 @@
import $ from 'cafy';
import { ID } from '@/misc/cafy-id';
import define from '../../define';
import { UserGroupInvitations } from '@/models/index';
import { makePaginationQuery } from '../../common/make-pagination-query';
@@ -11,21 +9,6 @@ export const meta = {
kind: 'read:user-groups',
params: {
limit: {
validator: $.optional.num.range(1, 100),
default: 10,
},
sinceId: {
validator: $.optional.type(ID),
},
untilId: {
validator: $.optional.type(ID),
},
},
res: {
type: 'array',
optional: false, nullable: false,
@@ -48,14 +31,24 @@ export const meta = {
},
} as const;
const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, user) => {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(UserGroupInvitations.createQueryBuilder('invitation'), ps.sinceId, ps.untilId)
.andWhere(`invitation.userId = :meId`, { meId: user.id })
.leftJoinAndSelect('invitation.userGroup', 'user_group');
const invitations = await query
.take(ps.limit!)
.take(ps.limit)
.getMany();
return await UserGroupInvitations.packMany(invitations);