Improve error handling of API (#4345)

* wip

* wip

* wip

* Update attached_notes.ts

* wip

* Refactor

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update call.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* ✌️

* Fix
This commit is contained in:
syuilo 2019-02-22 11:46:58 +09:00 committed by GitHub
parent fc52e95ad0
commit 2756f553c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
181 changed files with 2010 additions and 1322 deletions

View file

@ -0,0 +1,13 @@
/**
* ID付きエラー
*/
export class IdentifiableError extends Error {
public message: string;
public id: string;
constructor(id: string, message?: string) {
super(message);
this.message = message;
this.id = id;
}
}

View file

@ -48,7 +48,6 @@ export default async (ctx: Router.IRouterContext) => {
const partOf = `${config.url}/users/${userId}/followers`; const partOf = `${config.url}/users/${userId}/followers`;
if (page) { if (page) {
// Construct query
const query = { const query = {
followeeId: user._id followeeId: user._id
} as any; } as any;

View file

@ -48,7 +48,6 @@ export default async (ctx: Router.IRouterContext) => {
const partOf = `${config.url}/users/${userId}/following`; const partOf = `${config.url}/users/${userId}/following`;
if (page) { if (page) {
// Construct query
const query = { const query = {
followerId: user._id followerId: user._id
} as any; } as any;

View file

@ -78,7 +78,6 @@ export default async (ctx: Router.IRouterContext) => {
} }
//#endregion //#endregion
// Issue query
const notes = await Note const notes = await Note
.find(query, { .find(query, {
limit: limit, limit: limit,

View file

@ -5,18 +5,17 @@ import authenticate from './authenticate';
import call from './call'; import call from './call';
import { IUser } from '../../models/user'; import { IUser } from '../../models/user';
import { IApp } from '../../models/app'; import { IApp } from '../../models/app';
import { ApiError } from './error';
export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => { export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
const body = ctx.is('multipart/form-data') ? (ctx.req as any).body : ctx.request.body; const body = ctx.is('multipart/form-data') ? (ctx.req as any).body : ctx.request.body;
const reply = (x?: any, y?: any) => { const reply = (x?: any, y?: ApiError) => {
if (x === undefined) { if (x == null) {
ctx.status = 204; ctx.status = 204;
} else if (typeof x === 'number') { } else if (typeof x === 'number') {
ctx.status = x; ctx.status = x;
ctx.body = { ctx.body = y;
error: x === 500 ? 'INTERNAL_ERROR' : y
};
} else { } else {
ctx.body = x; ctx.body = x;
} }
@ -29,7 +28,11 @@ export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
try { try {
[user, app] = await authenticate(body['i']); [user, app] = await authenticate(body['i']);
} catch (e) { } catch (e) {
reply(403, 'AUTHENTICATION_FAILED'); reply(403, new ApiError({
message: 'Authentication failed. Please ensure your token is correct.',
code: 'AUTHENTICATION_FAILED',
id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14'
}));
return; return;
} }
@ -39,7 +42,11 @@ export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
try { try {
res = await call(endpoint.name, user, app, body, (ctx.req as any).file); res = await call(endpoint.name, user, app, body, (ctx.req as any).file);
} catch (e) { } catch (e) {
if (e.kind == 'client') {
reply(400, e); reply(400, e);
} else {
reply(500, e);
}
return; return;
} }

View file

@ -2,6 +2,15 @@ import limiter from './limiter';
import { IUser } from '../../models/user'; import { IUser } from '../../models/user';
import { IApp } from '../../models/app'; import { IApp } from '../../models/app';
import endpoints from './endpoints'; import endpoints from './endpoints';
import { ApiError } from './error';
import { apiLogger } from './logger';
import { Response } from './define';
const accessDenied = {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '56f35758-7dd5-468b-8439-5d6fb8ec9b8e'
};
export default async (endpoint: string, user: IUser, app: IApp, data: any, file?: any) => { export default async (endpoint: string, user: IUser, app: IApp, data: any, file?: any) => {
const isSecure = user != null && app == null; const isSecure = user != null && app == null;
@ -9,31 +18,43 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
const ep = endpoints.find(e => e.name === endpoint); const ep = endpoints.find(e => e.name === endpoint);
if (ep == null) { if (ep == null) {
throw 'ENDPOINT_NOT_FOUND'; throw new ApiError({
message: 'No such endpoint.',
code: 'NO_SUCH_ENDPOINT',
id: 'f8080b67-5f9c-4eb7-8c18-7f1eeae8f709',
});
} }
if (ep.meta.secure && !isSecure) { if (ep.meta.secure && !isSecure) {
throw 'ACCESS_DENIED'; throw new ApiError(accessDenied);
} }
if (ep.meta.requireCredential && user == null) { if (ep.meta.requireCredential && user == null) {
throw 'CREDENTIAL_REQUIRED'; throw new ApiError({
message: 'Credential required.',
code: 'CREDENTIAL_REQUIRED',
id: '1384574d-a912-4b81-8601-c7b1c4085df1',
});
} }
if (ep.meta.requireCredential && user.isSuspended) { if (ep.meta.requireCredential && user.isSuspended) {
throw 'YOUR_ACCOUNT_HAS_BEEN_SUSPENDED'; throw new ApiError(accessDenied, { reason: 'Your account has been suspended.' });
} }
if (ep.meta.requireAdmin && !user.isAdmin) { if (ep.meta.requireAdmin && !user.isAdmin) {
throw 'YOU_ARE_NOT_ADMIN'; throw new ApiError(accessDenied, { reason: 'You are not the admin.' });
} }
if (ep.meta.requireModerator && !user.isAdmin && !user.isModerator) { if (ep.meta.requireModerator && !user.isAdmin && !user.isModerator) {
throw 'YOU_ARE_NOT_MODERATOR'; throw new ApiError(accessDenied, { reason: 'You are not a moderator.' });
} }
if (app && ep.meta.kind && !app.permission.some(p => p === ep.meta.kind)) { if (app && ep.meta.kind && !app.permission.some(p => p === ep.meta.kind)) {
throw 'PERMISSION_DENIED'; throw new ApiError({
message: 'Your app does not have the necessary permissions to use this endpoint.',
code: 'PERMISSION_DENIED',
id: '1370e5b7-d4eb-4566-bb1d-7748ee6a1838',
});
} }
if (ep.meta.requireCredential && ep.meta.limit) { if (ep.meta.requireCredential && ep.meta.limit) {
@ -41,24 +62,31 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
await limiter(ep, user); // Rate limit await limiter(ep, user); // Rate limit
} catch (e) { } catch (e) {
// drop request if limit exceeded // drop request if limit exceeded
throw 'RATE_LIMIT_EXCEEDED'; throw new ApiError({
message: 'Rate limit exceeded. Please try again later.',
code: 'RATE_LIMIT_EXCEEDED',
id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef',
});
} }
} }
let res; let res: Response;
// API invoking // API invoking
try { try {
res = await ep.exec(data, user, app, file); res = await ep.exec(data, user, app, file);
} catch (e) { } catch (e) {
if (e && e.name == 'INVALID_PARAM') { if (e instanceof ApiError) {
throw {
code: e.name,
param: e.param,
reason: e.message
};
} else {
throw e; throw e;
} else {
apiLogger.error(e);
throw new ApiError(null, {
e: {
message: e.message,
code: e.code,
stack: e.stack
}
});
} }
} }

View file

@ -1,6 +1,7 @@
import * as mongo from 'mongodb'; import * as mongo from 'mongodb';
import Note from "../../../models/note"; import Note from '../../../models/note';
import User, { isRemoteUser, isLocalUser } from "../../../models/user"; import User, { isRemoteUser, isLocalUser } from '../../../models/user';
import { IdentifiableError } from '../../../misc/identifiable-error';
/** /**
* Get valied note for API processing * Get valied note for API processing
@ -12,7 +13,7 @@ export async function getValiedNote(noteId: mongo.ObjectID) {
}); });
if (note === null) { if (note === null) {
throw 'note not found'; throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
} }
return note; return note;
@ -27,7 +28,7 @@ export async function getUser(userId: mongo.ObjectID) {
}); });
if (user == null) { if (user == null) {
throw 'user not found'; throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.');
} }
return user; return user;

View file

@ -2,6 +2,7 @@ import * as fs from 'fs';
import { ILocalUser } from '../../models/user'; import { ILocalUser } from '../../models/user';
import { IApp } from '../../models/app'; import { IApp } from '../../models/app';
import { IEndpointMeta } from './endpoints'; import { IEndpointMeta } from './endpoints';
import { ApiError } from './error';
type Params<T extends IEndpointMeta> = { type Params<T extends IEndpointMeta> = {
[P in keyof T['params']]: T['params'][P]['transform'] extends Function [P in keyof T['params']]: T['params'][P]['transform'] extends Function
@ -9,13 +10,19 @@ type Params<T extends IEndpointMeta> = {
: ReturnType<T['params'][P]['validator']['get']>[0]; : ReturnType<T['params'][P]['validator']['get']>[0];
}; };
export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T>, user: ILocalUser, app: IApp, file?: any, cleanup?: Function) => Promise<any>): (params: any, user: ILocalUser, app: IApp, file?: any) => Promise<any> { export type Response = Record<string, any> | void;
export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T>, user: ILocalUser, app: IApp, file?: any, cleanup?: Function) => Promise<Response>): (params: any, user: ILocalUser, app: IApp, file?: any) => Promise<any> {
return (params: any, user: ILocalUser, app: IApp, file?: any) => { return (params: any, user: ILocalUser, app: IApp, file?: any) => {
function cleanup() { function cleanup() {
fs.unlink(file.path, () => {}); fs.unlink(file.path, () => {});
} }
if (meta.requireFile && file == null) return Promise.reject('file required'); if (meta.requireFile && file == null) return Promise.reject(new ApiError({
message: 'File required.',
code: 'FILE_REQUIRED',
id: '4267801e-70d1-416a-b011-4ee502885d8b',
}));
const [ps, pserr] = getParams(meta, params); const [ps, pserr] = getParams(meta, params);
if (pserr) { if (pserr) {
@ -27,17 +34,22 @@ export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T
}; };
} }
function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, Error] { function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, ApiError] {
if (defs.params == null) return [params, null]; if (defs.params == null) return [params, null];
const x: any = {}; const x: any = {};
let err: Error = null; let err: ApiError = null;
Object.entries(defs.params).some(([k, def]) => { Object.entries(defs.params).some(([k, def]) => {
const [v, e] = def.validator.get(params[k]); const [v, e] = def.validator.get(params[k]);
if (e) { if (e) {
err = new Error(e.message); err = new ApiError({
err.name = 'INVALID_PARAM'; message: 'Invalid param.',
(err as any).param = k; code: 'INVALID_PARAM',
id: '3d81ceae-475f-4600-b2a8-2bc116157532',
}, {
param: k,
reason: e.message
});
return true; return true;
} else { } else {
if (v === undefined && def.hasOwnProperty('default')) { if (v === undefined && def.hasOwnProperty('default')) {

View file

@ -25,11 +25,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const sort = { const sort = {
_id: -1 _id: -1
}; };
@ -51,5 +47,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
sort: sort sort: sort
}); });
res(await packMany(reports)); return await packMany(reports);
})); });

View file

@ -46,7 +46,7 @@ const sort: any = { // < https://github.com/Microsoft/TypeScript/issues/1863
[fallback]: { _id: -1 } [fallback]: { _id: -1 }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const q = { const q = {
'metadata.deletedAt': { $exists: false }, 'metadata.deletedAt': { $exists: false },
} as any; } as any;
@ -61,5 +61,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
skip: ps.offset skip: ps.offset
}); });
res(await packMany(files, { detail: true, withUser: true, self: true })); return await packMany(files, { detail: true, withUser: true, self: true });
})); });

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import ID, { transform } from '../../../../../misc/cafy-id'; import ID, { transform } from '../../../../../misc/cafy-id';
import define from '../../../define'; import define from '../../../define';
import DriveFile from '../../../../../models/drive-file'; import DriveFile from '../../../../../models/drive-file';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -12,17 +13,25 @@ export const meta = {
validator: $.type(ID), validator: $.type(ID),
transform: transform, transform: transform,
}, },
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'caf3ca38-c6e5-472e-a30c-b05377dcc240'
}
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const file = await DriveFile.findOne({ const file = await DriveFile.findOne({
_id: ps.fileId _id: ps.fileId
}); });
if (file == null) { if (file == null) {
return rej('file not found'); throw new ApiError(meta.errors.noSuchFile);
} }
res(file); return file;
})); });

View file

@ -26,7 +26,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const emoji = await Emoji.insert({ const emoji = await Emoji.insert({
updatedAt: new Date(), updatedAt: new Date(),
name: ps.name, name: ps.name,
@ -35,7 +35,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
url: ps.url url: ps.url
}); });
res({ return {
id: emoji._id id: emoji._id
}); };
})); });

View file

@ -18,16 +18,16 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const emojis = await Emoji.find({ const emojis = await Emoji.find({
host: ps.host host: ps.host
}); });
res(emojis.map(e => ({ return emojis.map(e => ({
id: e._id, id: e._id,
name: e.name, name: e.name,
aliases: e.aliases, aliases: e.aliases,
host: e.host, host: e.host,
url: e.url url: e.url
}))); }));
})); });

View file

@ -18,14 +18,14 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const emoji = await Emoji.findOne({ const emoji = await Emoji.findOne({
_id: ps.id _id: ps.id
}); });
if (emoji == null) return rej('emoji not found'); if (emoji == null) throw new Error('emoji not found');
await Emoji.remove({ _id: emoji._id }); await Emoji.remove({ _id: emoji._id });
res(); return;
})); });

View file

@ -30,12 +30,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const emoji = await Emoji.findOne({ const emoji = await Emoji.findOne({
_id: ps.id _id: ps.id
}); });
if (emoji == null) return rej('emoji not found'); if (emoji == null) throw new Error('emoji not found');
await Emoji.update({ _id: emoji._id }, { await Emoji.update({ _id: emoji._id }, {
$set: { $set: {
@ -46,5 +46,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -15,7 +15,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const followings = await Following.find({ const followings = await Following.find({
'_follower.host': ps.host '_follower.host': ps.host
}); });
@ -29,5 +29,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
deleteFollowing(pair[0], pair[1]); deleteFollowing(pair[0], pair[1]);
} }
res(); return;
})); });

View file

@ -21,11 +21,11 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const instance = await Instance.findOne({ host: ps.host }); const instance = await Instance.findOne({ host: ps.host });
if (instance == null) { if (instance == null) {
return rej('instance not found'); throw new Error('instance not found');
} }
Instance.update({ host: ps.host }, { Instance.update({ host: ps.host }, {
@ -35,5 +35,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -13,7 +13,7 @@ export const meta = {
params: {} params: {}
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const code = rndstr({ length: 5, chars: '0-9' }); const code = rndstr({ length: 5, chars: '0-9' });
await RegistrationTicket.insert({ await RegistrationTicket.insert({
@ -21,7 +21,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
code: code code: code
}); });
res({ return {
code: code code: code
}); };
})); });

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.update({ await User.update({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.update({ await User.update({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -8,8 +8,8 @@ export const meta = {
params: {} params: {}
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
destroy(); destroy();
res(); return;
})); });

View file

@ -15,18 +15,18 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const report = await AbuseUserReport.findOne({ const report = await AbuseUserReport.findOne({
_id: ps.reportId _id: ps.reportId
}); });
if (report == null) { if (report == null) {
return rej('report not found'); throw new Error('report not found');
} }
await AbuseUserReport.remove({ await AbuseUserReport.remove({
_id: report._id _id: report._id
}); });
res(); return;
})); });

View file

@ -25,17 +25,17 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
if (user.isAdmin) { if (user.isAdmin) {
return rej('cannot reset password of admin'); throw new Error('cannot reset password of admin');
} }
const passwd = rndstr('a-zA-Z0-9', 8); const passwd = rndstr('a-zA-Z0-9', 8);
@ -51,7 +51,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res({ return {
password: passwd password: passwd
}); };
})); });

View file

@ -23,18 +23,18 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
if (me.isModerator && user.isAdmin) { if (me.isModerator && user.isAdmin) {
return rej('cannot show info of admin'); throw new Error('cannot show info of admin');
} }
res(user); return user;
})); });

View file

@ -63,7 +63,7 @@ const sort: any = { // < https://github.com/Microsoft/TypeScript/issues/1863
[fallback]: { _id: -1 } [fallback]: { _id: -1 }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const q = { const q = {
$and: [] $and: []
} as any; } as any;
@ -99,5 +99,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
skip: ps.offset skip: ps.offset
}); });
res(await Promise.all(users.map(user => pack(user, me, { detail: true })))); return await Promise.all(users.map(user => pack(user, me, { detail: true })));
})); });

View file

@ -24,17 +24,17 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
if (user.isAdmin) { if (user.isAdmin) {
return rej('cannot silence admin'); throw new Error('cannot silence admin');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -45,5 +45,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -24,21 +24,21 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
if (user.isAdmin) { if (user.isAdmin) {
return rej('cannot suspend admin'); throw new Error('cannot suspend admin');
} }
if (user.isModerator) { if (user.isModerator) {
return rej('cannot suspend moderator'); throw new Error('cannot suspend moderator');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -49,5 +49,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -323,7 +323,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const set = {} as any; const set = {} as any;
if (ps.broadcasts) { if (ps.broadcasts) {
@ -506,5 +506,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
$set: set $set: set
}, { upsert: true }); }, { upsert: true });
res(); return;
})); });

View file

@ -26,9 +26,10 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise((res, rej) => { export default define(meta, async (ps) => {
updatePersonById(ps.userId).then(() => res(), e => rej(e)); await updatePersonById(ps.userId);
})); return;
});
async function updatePersonById(userId: mongo.ObjectID) { async function updatePersonById(userId: mongo.ObjectID) {
const user = await getRemoteUser(userId); const user = await getRemoteUser(userId);

View file

@ -24,13 +24,13 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const user = await User.findOne({ const user = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (user == null) { if (user == null) {
return rej('user not found'); throw new Error('user not found');
} }
await User.findOneAndUpdate({ await User.findOneAndUpdate({
@ -41,5 +41,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -6,7 +6,7 @@ export const meta = {
requireCredential: false, requireCredential: false,
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const instance = await fetchMeta(); const instance = await fetchMeta();
const hidedTags = instance.hidedTags.map(t => t.toLowerCase()); const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
@ -40,7 +40,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
//#endregion //#endregion
if (data.length == 0) { if (data.length == 0) {
return res([]); return [];
} }
let tags: { let tags: {
@ -66,5 +66,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
tags = tags.slice(0, 30); tags = tags.slice(0, 30);
res(tags); return tags;
})); });

View file

@ -7,6 +7,7 @@ import { createPerson } from '../../../../remote/activitypub/models/person';
import Note, { pack as packNote, INote } from '../../../../models/note'; import Note, { pack as packNote, INote } from '../../../../models/note';
import { createNote } from '../../../../remote/activitypub/models/note'; import { createNote } from '../../../../remote/activitypub/models/note';
import Resolver from '../../../../remote/activitypub/resolver'; import Resolver from '../../../../remote/activitypub/resolver';
import { ApiError } from '../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -23,13 +24,24 @@ export const meta = {
} }
}, },
}, },
errors: {
noSuchObject: {
message: 'No such object.',
code: 'NO_SUCH_OBJECT',
id: 'dc94d745-1262-4e63-a17d-fecaa57efc82'
}
}
}; };
export default define(meta, (ps) => new Promise((res, rej) => { export default define(meta, async (ps) => {
fetchAny(ps.uri) const object = await fetchAny(ps.uri);
.then(object => object != null ? res(object) : rej('object not found')) if (object) {
.catch(e => rej(e)); return object;
})); } else {
throw new ApiError(meta.errors.noSuchObject);
}
});
/*** /***
* URIからUserかNoteを解決する * URIからUserかNoteを解決する

View file

@ -27,7 +27,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Generate secret // Generate secret
const secret = rndstr('a-zA-Z0-9', 32); const secret = rndstr('a-zA-Z0-9', 32);
@ -42,9 +42,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
secret: secret secret: secret
}); });
// Response return await pack(app, null, {
res(await pack(app, null, {
detail: true, detail: true,
includeSecret: true includeSecret: true
})); });
})); });

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import ID, { transform } from '../../../../misc/cafy-id'; import ID, { transform } from '../../../../misc/cafy-id';
import App, { pack } from '../../../../models/app'; import App, { pack } from '../../../../models/app';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
params: { params: {
@ -9,22 +10,29 @@ export const meta = {
validator: $.type(ID), validator: $.type(ID),
transform: transform transform: transform
}, },
},
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: 'dce83913-2dc6-4093-8a7b-71dbb11718a3'
}
} }
}; };
export default define(meta, (ps, user, app) => new Promise(async (res, rej) => { export default define(meta, async (ps, user, app) => {
const isSecure = user != null && app == null; const isSecure = user != null && app == null;
// Lookup app // Lookup app
const ap = await App.findOne({ _id: ps.appId }); const ap = await App.findOne({ _id: ps.appId });
if (ap === null) { if (ap === null) {
return rej('app not found'); throw new ApiError(meta.errors.noSuchApp);
} }
// Send response return await pack(ap, user, {
res(await pack(ap, user, {
detail: true, detail: true,
includeSecret: isSecure && ap.userId.equals(user._id) includeSecret: isSecure && ap.userId.equals(user._id)
})); });
})); });

View file

@ -5,6 +5,7 @@ import App from '../../../../models/app';
import AuthSess from '../../../../models/auth-session'; import AuthSess from '../../../../models/auth-session';
import AccessToken from '../../../../models/access-token'; import AccessToken from '../../../../models/access-token';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -15,16 +16,24 @@ export const meta = {
token: { token: {
validator: $.str validator: $.str
} }
},
errors: {
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: '9c72d8de-391a-43c1-9d06-08d29efde8df'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch token // Fetch token
const session = await AuthSess const session = await AuthSess
.findOne({ token: ps.token }); .findOne({ token: ps.token });
if (session === null) { if (session === null) {
return rej('session not found'); throw new ApiError(meta.errors.noSuchSession);
} }
// Generate access token // Generate access token
@ -64,6 +73,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
// Response return;
res(); });
}));

View file

@ -4,6 +4,7 @@ import App from '../../../../../models/app';
import AuthSess from '../../../../../models/auth-session'; import AuthSess from '../../../../../models/auth-session';
import config from '../../../../../config'; import config from '../../../../../config';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
requireCredential: false, requireCredential: false,
@ -12,17 +13,25 @@ export const meta = {
appSecret: { appSecret: {
validator: $.str validator: $.str
} }
},
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: '92f93e63-428e-4f2f-a5a4-39e1407fe998'
}
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
// Lookup app // Lookup app
const app = await App.findOne({ const app = await App.findOne({
secret: ps.appSecret secret: ps.appSecret
}); });
if (app == null) { if (app == null) {
return rej('app not found'); throw new ApiError(meta.errors.noSuchApp);
} }
// Generate token // Generate token
@ -35,9 +44,8 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
token: token token: token
}); });
// Response return {
res({
token: doc.token, token: doc.token,
url: `${config.auth_url}/${doc.token}` url: `${config.auth_url}/${doc.token}`
}); };
})); });

View file

@ -1,6 +1,7 @@
import $ from 'cafy'; import $ from 'cafy';
import AuthSess, { pack } from '../../../../../models/auth-session'; import AuthSess, { pack } from '../../../../../models/auth-session';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
requireCredential: false, requireCredential: false,
@ -9,19 +10,26 @@ export const meta = {
token: { token: {
validator: $.str validator: $.str
} }
},
errors: {
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: 'bd72c97d-eba7-4adb-a467-f171b8847250'
}
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Lookup session // Lookup session
const session = await AuthSess.findOne({ const session = await AuthSess.findOne({
token: ps.token token: ps.token
}); });
if (session == null) { if (session == null) {
return rej('session not found'); throw new ApiError(meta.errors.noSuchSession);
} }
// Response return await pack(session, user);
res(await pack(session, user)); });
}));

View file

@ -4,6 +4,7 @@ import AuthSess from '../../../../../models/auth-session';
import AccessToken from '../../../../../models/access-token'; import AccessToken from '../../../../../models/access-token';
import { pack } from '../../../../../models/user'; import { pack } from '../../../../../models/user';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
requireCredential: false, requireCredential: false,
@ -16,17 +17,37 @@ export const meta = {
token: { token: {
validator: $.str validator: $.str
} }
},
errors: {
noSuchApp: {
message: 'No such app.',
code: 'NO_SUCH_APP',
id: 'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d'
},
noSuchSession: {
message: 'No such session.',
code: 'NO_SUCH_SESSION',
id: '5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3'
},
pendingSession: {
message: 'This session is not completed yet.',
code: 'PENDING_SESSION',
id: '8c8a4145-02cc-4cca-8e66-29ba60445a8e'
}
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
// Lookup app // Lookup app
const app = await App.findOne({ const app = await App.findOne({
secret: ps.appSecret secret: ps.appSecret
}); });
if (app == null) { if (app == null) {
return rej('app not found'); throw new ApiError(meta.errors.noSuchApp);
} }
// Fetch token // Fetch token
@ -37,11 +58,11 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
}); });
if (session === null) { if (session === null) {
return rej('session not found'); throw new ApiError(meta.errors.noSuchSession);
} }
if (session.userId == null) { if (session.userId == null) {
return rej('this session is not allowed yet'); throw new ApiError(meta.errors.pendingSession);
} }
// Lookup access token // Lookup access token
@ -61,11 +82,10 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
_id: session._id _id: session._id
}); });
// Response return {
res({
accessToken: accessToken.token, accessToken: accessToken.token,
user: await pack(session.userId, null, { user: await pack(session.userId, null, {
detail: true detail: true
}) })
}); };
})); });

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Blocking from '../../../../models/blocking'; import Blocking from '../../../../models/blocking';
import create from '../../../../services/blocking/create'; import create from '../../../../services/blocking/create';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '7cc4f851-e2f1-4621-9633-ec9e1d00c01e'
},
blockeeIsYourself: {
message: 'Blockee is yourself.',
code: 'BLOCKEE_IS_YOURSELF',
id: '88b19138-f28d-42c0-8499-6a31bbd0fdc6'
},
alreadyBlocking: {
message: 'You are already blocking that user.',
code: 'ALREADY_BLOCKING',
id: '787fed64-acb9-464a-82eb-afbd745b9614'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const blocker = user; const blocker = user;
// 自分自身 // 自分自身
if (user._id.equals(ps.userId)) { if (user._id.equals(ps.userId)) {
return rej('blockee is yourself'); throw new ApiError(meta.errors.blockeeIsYourself);
} }
// Get blockee // Get blockee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (blockee === null) { if (blockee === null) {
return rej('user not found'); throw new ApiError(meta.errors.noSuchUser);
} }
// Check if already blocking // Check if already blocking
@ -64,14 +85,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (exist !== null) { if (exist !== null) {
return rej('already blocking'); throw new ApiError(meta.errors.alreadyBlocking);
} }
// Create blocking // Create blocking
await create(blocker, blockee); await create(blocker, blockee);
// Send response return await pack(blockee._id, user, {
res(await pack(blockee._id, user, {
detail: true detail: true
})); });
})); });

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Blocking from '../../../../models/blocking'; import Blocking from '../../../../models/blocking';
import deleteBlocking from '../../../../services/blocking/delete'; import deleteBlocking from '../../../../services/blocking/delete';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '8621d8bf-c358-4303-a066-5ea78610eb3f'
},
blockeeIsYourself: {
message: 'Blockee is yourself.',
code: 'BLOCKEE_IS_YOURSELF',
id: '06f6fac6-524b-473c-a354-e97a40ae6eac'
},
notBlocking: {
message: 'You are not blocking that user.',
code: 'NOT_BLOCKING',
id: '291b2efa-60c6-45c0-9f6a-045c8f9b02cd'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const blocker = user; const blocker = user;
// Check if the blockee is yourself // Check if the blockee is yourself
if (user._id.equals(ps.userId)) { if (user._id.equals(ps.userId)) {
return rej('blockee is yourself'); throw new ApiError(meta.errors.blockeeIsYourself);
} }
// Get blockee // Get blockee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (blockee === null) { if (blockee === null) {
return rej('user not found'); throw new ApiError(meta.errors.noSuchUser);
} }
// Check not blocking // Check not blocking
@ -64,14 +85,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (exist === null) { if (exist === null) {
return rej('already not blocking'); throw new ApiError(meta.errors.notBlocking);
} }
// Delete blocking // Delete blocking
await deleteBlocking(blocker, blockee); await deleteBlocking(blocker, blockee);
// Send response return await pack(blockee._id, user, {
res(await pack(blockee._id, user, {
detail: true detail: true
})); });
})); });

View file

@ -31,12 +31,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const query = { const query = {
blockerId: me._id blockerId: me._id
} as any; } as any;
@ -62,5 +57,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
sort: sort sort: sort
}); });
res(await packMany(blockings, me)); return await packMany(blockings, me);
})); });

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await activeUsersChart.getChart(ps.span as any, ps.limit); return await activeUsersChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await driveChart.getChart(ps.span as any, ps.limit); return await driveChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await federationChart.getChart(ps.span as any, ps.limit); return await federationChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -34,8 +34,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await hashtagChart.getChart(ps.span as any, ps.limit, ps.tag); return await hashtagChart.getChart(ps.span as any, ps.limit, ps.tag);
});
res(stats);
}));

View file

@ -35,8 +35,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await instanceChart.getChart(ps.span as any, ps.limit, ps.host); return await instanceChart.getChart(ps.span as any, ps.limit, ps.host);
});
res(stats);
}));

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await networkChart.getChart(ps.span as any, ps.limit); return await networkChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await notesChart.getChart(ps.span as any, ps.limit); return await notesChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -37,8 +37,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await perUserDriveChart.getChart(ps.span as any, ps.limit, ps.userId); return await perUserDriveChart.getChart(ps.span as any, ps.limit, ps.userId);
});
res(stats);
}));

View file

@ -37,8 +37,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId); return await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
});
res(stats);
}));

View file

@ -37,8 +37,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await perUserNotesChart.getChart(ps.span as any, ps.limit, ps.userId); return await perUserNotesChart.getChart(ps.span as any, ps.limit, ps.userId);
});
res(stats);
}));

View file

@ -37,8 +37,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await perUserReactionsChart.getChart(ps.span as any, ps.limit, ps.userId); return await perUserReactionsChart.getChart(ps.span as any, ps.limit, ps.userId);
});
res(stats);
}));

View file

@ -27,8 +27,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const stats = await usersChart.getChart(ps.span as any, ps.limit); return await usersChart.getChart(ps.span as any, ps.limit);
});
res(stats);
}));

View file

@ -13,12 +13,11 @@ export const meta = {
kind: 'drive-read' kind: 'drive-read'
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const instance = await fetchMeta(); const instance = await fetchMeta();
// Calculate drive usage // Calculate drive usage
const usage = await DriveFile const usage = await DriveFile.aggregate([{
.aggregate([{
$match: { $match: {
'metadata.userId': user._id, 'metadata.userId': user._id,
'metadata.deletedAt': { $exists: false } 'metadata.deletedAt': { $exists: false }
@ -40,8 +39,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
return 0; return 0;
}); });
res({ return {
capacity: 1024 * 1024 * instance.localDriveCapacityMb, capacity: 1024 * 1024 * instance.localDriveCapacityMb,
usage: usage usage: usage
}); };
})); });

View file

@ -41,12 +41,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const sort = { const sort = {
_id: -1 _id: -1
}; };
@ -78,5 +73,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
sort: sort sort: sort
}); });
res(await packMany(files, { detail: false, self: true })); return await packMany(files, { detail: false, self: true });
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFile from '../../../../../models/drive-file'; import DriveFile from '../../../../../models/drive-file';
import define from '../../../define'; import define from '../../../define';
import { packMany } from '../../../../../models/note'; import { packMany } from '../../../../../models/note';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -25,10 +26,18 @@ export const meta = {
'en-US': 'Target file ID' 'en-US': 'Target file ID'
} }
} }
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'c118ece3-2e4b-4296-99d1-51756e32d232',
}
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch file // Fetch file
const file = await DriveFile const file = await DriveFile
.findOne({ .findOne({
@ -38,10 +47,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (file === null) { if (file === null) {
return rej('file-not-found'); throw new ApiError(meta.errors.noSuchFile);
} }
res(await packMany(file.metadata.attachedNoteIds || [], user, { return await packMany(file.metadata.attachedNoteIds || [], user, {
detail: true detail: true
})); });
})); });

View file

@ -22,16 +22,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const file = await DriveFile.findOne({ const file = await DriveFile.findOne({
md5: ps.md5, md5: ps.md5,
'metadata.userId': user._id, 'metadata.userId': user._id,
'metadata.deletedAt': { $exists: false } 'metadata.deletedAt': { $exists: false }
}); });
if (file === null) { return { file: file ? await pack(file, { self: true }) : null };
res({ file: null }); });
} else {
res({ file: await pack(file, { self: true }) });
}
}));

View file

@ -5,6 +5,7 @@ import { validateFileName, pack } from '../../../../../models/drive-file';
import create from '../../../../../services/drive/add-file'; import create from '../../../../../services/drive/add-file';
import define from '../../../define'; import define from '../../../define';
import { apiLogger } from '../../../logger'; import { apiLogger } from '../../../logger';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -51,10 +52,18 @@ export const meta = {
'ja-JP': 'true にすると、同じハッシュを持つファイルが既にアップロードされていても強制的にファイルを作成します。', 'ja-JP': 'true にすると、同じハッシュを持つファイルが既にアップロードされていても強制的にファイルを作成します。',
} }
} }
},
errors: {
invalidFileName: {
message: 'Invalid file name.',
code: 'INVALID_FILE_NAME',
id: 'f449b209-0c60-4e51-84d5-29486263bfd4'
}
} }
}; };
export default define(meta, (ps, user, app, file, cleanup) => new Promise(async (res, rej) => { export default define(meta, async (ps, user, app, file, cleanup) => {
// Get 'name' parameter // Get 'name' parameter
let name = file.originalname; let name = file.originalname;
if (name !== undefined && name !== null) { if (name !== undefined && name !== null) {
@ -64,7 +73,7 @@ export default define(meta, (ps, user, app, file, cleanup) => new Promise(async
} else if (name === 'blob') { } else if (name === 'blob') {
name = null; name = null;
} else if (!validateFileName(name)) { } else if (!validateFileName(name)) {
return rej('invalid name'); throw new ApiError(meta.errors.invalidFileName);
} }
} else { } else {
name = null; name = null;
@ -73,15 +82,11 @@ export default define(meta, (ps, user, app, file, cleanup) => new Promise(async
try { try {
// Create file // Create file
const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive); const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
return pack(driveFile, { self: true });
cleanup();
res(pack(driveFile, { self: true }));
} catch (e) { } catch (e) {
apiLogger.error(e); apiLogger.error(e);
throw new ApiError();
} finally {
cleanup(); cleanup();
rej(e);
} }
})); });

View file

@ -4,6 +4,7 @@ import DriveFile from '../../../../../models/drive-file';
import del from '../../../../../services/drive/delete-file'; import del from '../../../../../services/drive/delete-file';
import { publishDriveStream } from '../../../../../services/stream'; import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -26,10 +27,24 @@ export const meta = {
'en-US': 'Target file ID' 'en-US': 'Target file ID'
} }
} }
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '908939ec-e52b-4458-b395-1025195cea58'
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '5eb8d909-2540-4970-90b8-dd6f86088121'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch file // Fetch file
const file = await DriveFile const file = await DriveFile
.findOne({ .findOne({
@ -37,11 +52,11 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (file === null) { if (file === null) {
return rej('file-not-found'); throw new ApiError(meta.errors.noSuchFile);
} }
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) { if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
return rej('access denied'); throw new ApiError(meta.errors.accessDenied);
} }
// Delete // Delete
@ -50,5 +65,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Publish fileDeleted event // Publish fileDeleted event
publishDriveStream(user._id, 'fileDeleted', file._id); publishDriveStream(user._id, 'fileDeleted', file._id);
res(); return;
})); });

View file

@ -24,7 +24,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const files = await DriveFile const files = await DriveFile
.find({ .find({
filename: ps.name, filename: ps.name,
@ -32,5 +32,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
'metadata.folderId': ps.folderId 'metadata.folderId': ps.folderId
}); });
res(await Promise.all(files.map(file => pack(file, { self: true })))); return await Promise.all(files.map(file => pack(file, { self: true })));
})); });

View file

@ -4,6 +4,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFile, { pack, IDriveFile } from '../../../../../models/drive-file'; import DriveFile, { pack, IDriveFile } from '../../../../../models/drive-file';
import define from '../../../define'; import define from '../../../define';
import config from '../../../../../config'; import config from '../../../../../config';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -34,10 +35,30 @@ export const meta = {
'en-US': 'Target file URL' 'en-US': 'Target file URL'
} }
} }
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: '067bc436-2718-4795-b0fb-ecbe43949e31'
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '25b73c73-68b1-41d0-bad1-381cfdf6579f'
},
fileIdOrUrlRequired: {
message: 'fileId or url required.',
code: 'INVALID_PARAM',
id: '89674805-722c-440c-8d88-5641830dc3e4'
}
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
let file: IDriveFile; let file: IDriveFile;
if (ps.fileId) { if (ps.fileId) {
@ -69,22 +90,19 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
} }
} else { } else {
return rej('fileId or url required'); throw new ApiError(meta.errors.fileIdOrUrlRequired);
} }
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) { if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
return rej('access denied'); throw new ApiError(meta.errors.accessDenied);
} }
if (file === null) { if (file === null) {
return rej('file-not-found'); throw new ApiError(meta.errors.noSuchFile);
} }
// Serialize return await pack(file, {
const _file = await pack(file, {
detail: true, detail: true,
self: true self: true
}); });
});
res(_file);
}));

View file

@ -5,6 +5,7 @@ import DriveFile, { validateFileName, pack } from '../../../../../models/drive-f
import { publishDriveStream } from '../../../../../services/stream'; import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define'; import define from '../../../define';
import Note from '../../../../../models/note'; import Note from '../../../../../models/note';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -51,10 +52,30 @@ export const meta = {
'en-US': 'Whether this media is NSFW' 'en-US': 'Whether this media is NSFW'
} }
} }
},
errors: {
noSuchFile: {
message: 'No such file.',
code: 'NO_SUCH_FILE',
id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d'
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '01a53b27-82fc-445b-a0c1-b558465a8ed2'
},
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'ea8fb7a5-af77-4a08-b608-c0218176cd73'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch file // Fetch file
const file = await DriveFile const file = await DriveFile
.findOne({ .findOne({
@ -62,11 +83,11 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (file === null) { if (file === null) {
return rej('file-not-found'); throw new ApiError(meta.errors.noSuchFile);
} }
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) { if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
return rej('access denied'); throw new ApiError(meta.errors.accessDenied);
} }
if (ps.name) file.filename = ps.name; if (ps.name) file.filename = ps.name;
@ -85,7 +106,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (folder === null) { if (folder === null) {
return rej('folder-not-found'); throw new ApiError(meta.errors.noSuchFolder);
} }
file.metadata.folderId = folder._id; file.metadata.folderId = folder._id;
@ -114,12 +135,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
// Serialize
const fileObj = await pack(file, { self: true }); const fileObj = await pack(file, { self: true });
// Response
res(fileObj);
// Publish fileUpdated event // Publish fileUpdated event
publishDriveStream(user._id, 'fileUpdated', fileObj); publishDriveStream(user._id, 'fileUpdated', fileObj);
}));
return fileObj;
});

View file

@ -50,6 +50,6 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
res(pack(await uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force), { self: true })); return await pack(await uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force), { self: true });
})); });

View file

@ -37,12 +37,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const sort = { const sort = {
_id: -1 _id: -1
}; };
@ -67,5 +62,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
sort: sort sort: sort
}); });
res(await Promise.all(folders.map(folder => pack(folder)))); return await Promise.all(folders.map(folder => pack(folder)));
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
import { publishDriveStream } from '../../../../../services/stream'; import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -34,10 +35,18 @@ export const meta = {
'en-US': 'Parent folder ID' 'en-US': 'Parent folder ID'
} }
} }
},
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: '53326628-a00d-40a6-a3cd-8975105c0f95'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// If the parent folder is specified // If the parent folder is specified
let parent = null; let parent = null;
if (ps.parentId) { if (ps.parentId) {
@ -49,7 +58,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (parent === null) { if (parent === null) {
return rej('parent-not-found'); throw new ApiError(meta.errors.noSuchFolder);
} }
} }
@ -61,12 +70,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
userId: user._id userId: user._id
}); });
// Serialize
const folderObj = await pack(folder); const folderObj = await pack(folder);
// Response
res(folderObj);
// Publish folderCreated event // Publish folderCreated event
publishDriveStream(user._id, 'folderCreated', folderObj); publishDriveStream(user._id, 'folderCreated', folderObj);
}));
return folderObj;
});

View file

@ -4,6 +4,7 @@ import DriveFolder from '../../../../../models/drive-folder';
import define from '../../../define'; import define from '../../../define';
import { publishDriveStream } from '../../../../../services/stream'; import { publishDriveStream } from '../../../../../services/stream';
import DriveFile from '../../../../../models/drive-file'; import DriveFile from '../../../../../models/drive-file';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -26,10 +27,24 @@ export const meta = {
'en-US': 'Target folder ID' 'en-US': 'Target folder ID'
} }
} }
},
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: '1069098f-c281-440f-b085-f9932edbe091'
},
hasChildFilesOrFolders: {
message: 'This folder has child files or folders.',
code: 'HAS_CHILD_FILES_OR_FOLDERS',
id: 'b0fc8a17-963c-405d-bfbc-859a487295e1'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Get folder // Get folder
const folder = await DriveFolder const folder = await DriveFolder
.findOne({ .findOne({
@ -38,7 +53,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (folder === null) { if (folder === null) {
return rej('folder-not-found'); throw new ApiError(meta.errors.noSuchFolder);
} }
const [childFoldersCount, childFilesCount] = await Promise.all([ const [childFoldersCount, childFilesCount] = await Promise.all([
@ -47,7 +62,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
]); ]);
if (childFoldersCount !== 0 || childFilesCount !== 0) { if (childFoldersCount !== 0 || childFilesCount !== 0) {
return rej('has-child-contents'); throw new ApiError(meta.errors.hasChildFilesOrFolders);
} }
await DriveFolder.remove({ _id: folder._id }); await DriveFolder.remove({ _id: folder._id });
@ -55,5 +70,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Publish folderCreated event // Publish folderCreated event
publishDriveStream(user._id, 'folderDeleted', folder._id); publishDriveStream(user._id, 'folderDeleted', folder._id);
res(); return;
})); });

View file

@ -24,7 +24,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const folders = await DriveFolder const folders = await DriveFolder
.find({ .find({
name: ps.name, name: ps.name,
@ -32,5 +32,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
parentId: ps.parentId parentId: ps.parentId
}); });
res(await Promise.all(folders.map(folder => pack(folder)))); return await Promise.all(folders.map(folder => pack(folder)));
})); });

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import ID, { transform } from '../../../../../misc/cafy-id'; import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFolder, { pack } from '../../../../../models/drive-folder'; import DriveFolder, { pack } from '../../../../../models/drive-folder';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -24,10 +25,18 @@ export const meta = {
'en-US': 'Target folder ID' 'en-US': 'Target folder ID'
} }
} }
},
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'd74ab9eb-bb09-4bba-bf24-fb58f761e1e9'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Get folder // Get folder
const folder = await DriveFolder const folder = await DriveFolder
.findOne({ .findOne({
@ -36,11 +45,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (folder === null) { if (folder === null) {
return rej('folder-not-found'); throw new ApiError(meta.errors.noSuchFolder);
} }
// Serialize return await pack(folder, {
res(await pack(folder, {
detail: true detail: true
})); });
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder'; import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
import { publishDriveStream } from '../../../../../services/stream'; import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -42,10 +43,30 @@ export const meta = {
'en-US': 'Parent folder ID' 'en-US': 'Parent folder ID'
} }
} }
},
errors: {
noSuchFolder: {
message: 'No such folder.',
code: 'NO_SUCH_FOLDER',
id: 'f7974dac-2c0d-4a27-926e-23583b28e98e'
},
noSuchParentFolder: {
message: 'No such parent folder.',
code: 'NO_SUCH_PARENT_FOLDER',
id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1'
},
recursiveNesting: {
message: 'It can not be structured like nesting folders recursively.',
code: 'NO_SUCH_PARENT_FOLDER',
id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch folder // Fetch folder
const folder = await DriveFolder const folder = await DriveFolder
.findOne({ .findOne({
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (folder === null) { if (folder === null) {
return rej('folder-not-found'); throw new ApiError(meta.errors.noSuchFolder);
} }
if (ps.name) folder.name = ps.name; if (ps.name) folder.name = ps.name;
@ -71,7 +92,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (parent === null) { if (parent === null) {
return rej('parent-folder-not-found'); throw new ApiError(meta.errors.noSuchParentFolder);
} }
// Check if the circular reference will occur // Check if the circular reference will occur
@ -95,7 +116,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
if (parent.parentId !== null) { if (parent.parentId !== null) {
if (await checkCircle(parent.parentId)) { if (await checkCircle(parent.parentId)) {
return rej('detected-circular-definition'); throw new ApiError(meta.errors.recursiveNesting);
} }
} }
@ -111,12 +132,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
// Serialize
const folderObj = await pack(folder); const folderObj = await pack(folder);
// Response
res(folderObj);
// Publish folderUpdated event // Publish folderUpdated event
publishDriveStream(user._id, 'folderUpdated', folderObj); publishDriveStream(user._id, 'folderUpdated', folderObj);
}));
return folderObj;
});

View file

@ -30,12 +30,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const sort = { const sort = {
_id: -1 _id: -1
}; };
@ -66,5 +61,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
sort: sort sort: sort
}); });
res(await packMany(files, { self: true })); return await packMany(files, { self: true });
})); });

View file

@ -34,7 +34,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
let sort; let sort;
if (ps.sort) { if (ps.sort) {
@ -122,5 +122,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
skip: ps.offset skip: ps.offset
}); });
res(instances); return instances;
})); });

View file

@ -12,9 +12,9 @@ export const meta = {
} }
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const instance = await Instance const instance = await Instance
.findOne({ host: ps.host }); .findOne({ host: ps.host });
res(instance); return instance;
})); });

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Following from '../../../../models/following'; import Following from '../../../../models/following';
import create from '../../../../services/following/create'; import create from '../../../../services/following/create';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -32,15 +33,47 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5'
},
followeeIsYourself: {
message: 'Followee is yourself.',
code: 'FOLLOWEE_IS_YOURSELF',
id: '26fbe7bb-a331-4857-af17-205b426669a9'
},
alreadyFollowing: {
message: 'You are already following that user.',
code: 'ALREADY_FOLLOWING',
id: '35387507-38c7-4cb9-9197-300b93783fa0'
},
blocking: {
message: 'You are blocking that user.',
code: 'BLOCKING',
id: '4e2206ec-aa4f-4960-b865-6c23ac38e2d9'
},
blocked: {
message: 'You are blocked by that user.',
code: 'BLOCKED',
id: 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const follower = user; const follower = user;
// 自分自身 // 自分自身
if (user._id.equals(ps.userId)) { if (user._id.equals(ps.userId)) {
return rej('followee is yourself'); throw new ApiError(meta.errors.followeeIsYourself);
} }
// Get followee // Get followee
@ -54,7 +87,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (followee === null) { if (followee === null) {
return rej('user not found'); throw new ApiError(meta.errors.noSuchUser);
} }
// Check if already following // Check if already following
@ -64,16 +97,16 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (exist !== null) { if (exist !== null) {
return rej('already following'); throw new ApiError(meta.errors.alreadyFollowing);
} }
// Create following
try { try {
await create(follower, followee); await create(follower, followee);
} catch (e) { } catch (e) {
return rej(e && e.message ? e.message : e); if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking);
if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError(meta.errors.blocked);
throw e;
} }
// Send response return await pack(followee._id, user);
res(await pack(followee._id, user)); });
}));

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Following from '../../../../models/following'; import Following from '../../../../models/following';
import deleteFollowing from '../../../../services/following/delete'; import deleteFollowing from '../../../../services/following/delete';
import define from '../../define'; import define from '../../define';
import { ApiError } from '../../error';
export const meta = { export const meta = {
stability: 'stable', stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8'
},
followeeIsYourself: {
message: 'Followee is yourself.',
code: 'FOLLOWEE_IS_YOURSELF',
id: 'd9e400b9-36b0-4808-b1d8-79e707f1296c'
},
notFollowing: {
message: 'You are not following that user.',
code: 'NOT_FOLLOWING',
id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const follower = user; const follower = user;
// Check if the followee is yourself // Check if the followee is yourself
if (user._id.equals(ps.userId)) { if (user._id.equals(ps.userId)) {
return rej('followee is yourself'); throw new ApiError(meta.errors.followeeIsYourself);
} }
// Get followee // Get followee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (followee === null) { if (followee === null) {
return rej('user not found'); throw new ApiError(meta.errors.noSuchUser);
} }
// Check not following // Check not following
@ -64,12 +85,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (exist === null) { if (exist === null) {
return rej('already not following'); throw new ApiError(meta.errors.notFollowing);
} }
// Delete following
await deleteFollowing(follower, followee); await deleteFollowing(follower, followee);
// Send response return await pack(followee._id, user);
res(await pack(followee._id, user)); });
}));

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import acceptFollowRequest from '../../../../../services/following/requests/accept'; import acceptFollowRequest from '../../../../../services/following/requests/accept';
import User from '../../../../../models/user'; import User from '../../../../../models/user';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -23,20 +24,28 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '66ce1645-d66c-46bb-8b79-96739af885bd'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch follower // Fetch follower
const follower = await User.findOne({ const follower = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (follower === null) { if (follower === null) {
return rej('follower not found'); throw new ApiError(meta.errors.noSuchUser);
} }
await acceptFollowRequest(user, follower); await acceptFollowRequest(user, follower);
res(); return;
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import cancelFollowRequest from '../../../../../services/following/requests/cancel'; import cancelFollowRequest from '../../../../../services/following/requests/cancel';
import User, { pack } from '../../../../../models/user'; import User, { pack } from '../../../../../models/user';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -23,24 +24,39 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab'
},
followRequestNotFound: {
message: 'Follow request not found.',
code: 'FOLLOW_REQUEST_NOT_FOUND',
id: '089b125b-d338-482a-9a09-e2622ac9f8d4'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch followee // Fetch followee
const followee = await User.findOne({ const followee = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (followee === null) { if (followee === null) {
return rej('followee not found'); throw new ApiError(meta.errors.noSuchUser);
} }
try { try {
await cancelFollowRequest(followee, user); await cancelFollowRequest(followee, user);
} catch (e) { } catch (e) {
return rej(e); if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(meta.errors.followRequestNotFound);
throw e;
} }
res(await pack(followee._id, user)); return await pack(followee._id, user);
})); });

View file

@ -1,5 +1,3 @@
// import $ from 'cafy';
// import ID, { transform } from '../../../../../cafy-id';
import FollowRequest, { pack } from '../../../../../models/follow-request'; import FollowRequest, { pack } from '../../../../../models/follow-request';
import define from '../../../define'; import define from '../../../define';
@ -14,11 +12,10 @@ export const meta = {
kind: 'following-read' kind: 'following-read'
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const reqs = await FollowRequest.find({ const reqs = await FollowRequest.find({
followeeId: user._id followeeId: user._id
}); });
// Send response return await Promise.all(reqs.map(req => pack(req)));
res(await Promise.all(reqs.map(req => pack(req)))); });
}));

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import rejectFollowRequest from '../../../../../services/following/requests/reject'; import rejectFollowRequest from '../../../../../services/following/requests/reject';
import User from '../../../../../models/user'; import User from '../../../../../models/user';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -23,20 +24,28 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
} }
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Fetch follower // Fetch follower
const follower = await User.findOne({ const follower = await User.findOne({
_id: ps.userId _id: ps.userId
}); });
if (follower === null) { if (follower === null) {
return rej('follower not found'); throw new ApiError(meta.errors.noSuchUser);
} }
await rejectFollowRequest(user, follower); await rejectFollowRequest(user, follower);
res(); return;
})); });

View file

@ -27,12 +27,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
const q: any = ps.my ? { const q: any = ps.my ? {
isStarted: true, isStarted: true,
$or: [{ $or: [{
@ -65,8 +60,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
limit: ps.limit limit: ps.limit
}); });
// Reponse return await Promise.all(games.map((g) => pack(g, user, {
res(Promise.all(games.map(async (g) => await pack(g, user, {
detail: false detail: false
})))); })));
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../../misc/cafy-id';
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game'; import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
import Reversi from '../../../../../../games/reversi/core'; import Reversi from '../../../../../../games/reversi/core';
import define from '../../../../define'; import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = { export const meta = {
params: { params: {
@ -10,14 +11,22 @@ export const meta = {
validator: $.type(ID), validator: $.type(ID),
transform: transform, transform: transform,
}, },
},
errors: {
noSuchGame: {
message: 'No such game.',
code: 'NO_SUCH_GAME',
id: 'f13a03db-fae1-46c9-87f3-43c8165419e1'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const game = await ReversiGame.findOne({ _id: ps.gameId }); const game = await ReversiGame.findOne({ _id: ps.gameId });
if (game == null) { if (game == null) {
return rej('game not found'); throw new ApiError(meta.errors.noSuchGame);
} }
const o = new Reversi(game.settings.map, { const o = new Reversi(game.settings.map, {
@ -31,8 +40,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
const packed = await pack(game, user); const packed = await pack(game, user);
res(Object.assign({ return Object.assign({
board: o.board, board: o.board,
turn: o.turn turn: o.turn
}, packed)); }, packed);
})); });

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../../misc/cafy-id';
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game'; import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
import { publishReversiGameStream } from '../../../../../../services/stream'; import { publishReversiGameStream } from '../../../../../../services/stream';
import define from '../../../../define'; import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = { export const meta = {
desc: { desc: {
@ -19,22 +20,42 @@ export const meta = {
'ja-JP': '投了したい対局' 'ja-JP': '投了したい対局'
} }
} }
},
errors: {
noSuchGame: {
message: 'No such game.',
code: 'NO_SUCH_GAME',
id: 'ace0b11f-e0a6-4076-a30d-e8284c81b2df'
},
alreadyEnded: {
message: 'That game has already ended.',
code: 'ALREADY_ENDED',
id: '6c2ad4a6-cbf1-4a5b-b187-b772826cfc6d'
},
accessDenied: {
message: 'Access denied.',
code: 'ACCESS_DENIED',
id: '6e04164b-a992-4c93-8489-2123069973e1'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const game = await ReversiGame.findOne({ _id: ps.gameId }); const game = await ReversiGame.findOne({ _id: ps.gameId });
if (game == null) { if (game == null) {
return rej('game not found'); throw new ApiError(meta.errors.noSuchGame);
} }
if (game.isEnded) { if (game.isEnded) {
return rej('this game is already ended'); throw new ApiError(meta.errors.alreadyEnded);
} }
if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) { if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) {
return rej('access denied'); throw new ApiError(meta.errors.accessDenied);
} }
const winnerId = game.user1Id.equals(user._id) ? game.user2Id : game.user1Id; const winnerId = game.user1Id.equals(user._id) ? game.user2Id : game.user1Id;
@ -54,5 +75,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
game: await pack(game._id, user) game: await pack(game._id, user)
}); });
res(); return;
})); });

View file

@ -5,7 +5,7 @@ export const meta = {
requireCredential: true requireCredential: true
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Find session // Find session
const invitations = await Matching.find({ const invitations = await Matching.find({
childId: user._id childId: user._id
@ -15,6 +15,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
// Reponse return await Promise.all(invitations.map((i) => packMatching(i, user)));
res(Promise.all(invitations.map(async (i) => await packMatching(i, user)))); });
}));

View file

@ -6,6 +6,7 @@ import User from '../../../../../models/user';
import { publishMainStream, publishReversiStream } from '../../../../../services/stream'; import { publishMainStream, publishReversiStream } from '../../../../../services/stream';
import { eighteight } from '../../../../../games/reversi/maps'; import { eighteight } from '../../../../../games/reversi/maps';
import define from '../../../define'; import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = { export const meta = {
requireCredential: true, requireCredential: true,
@ -19,13 +20,27 @@ export const meta = {
'en-US': 'Target user ID' 'en-US': 'Target user ID'
} }
}, },
},
errors: {
noSuchUser: {
message: 'No such user.',
code: 'NO_SUCH_USER',
id: '0b4f0559-b484-4e31-9581-3f73cee89b28'
},
isYourself: {
message: 'Target user is yourself.',
code: 'TARGET_IS_YOURSELF',
id: '96fd7bd6-d2bc-426c-a865-d055dcd2828e'
},
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Myself // Myself
if (ps.userId.equals(user._id)) { if (ps.userId.equals(user._id)) {
return rej('invalid userId param'); throw new ApiError(meta.errors.isYourself);
} }
// Find session // Find session
@ -57,9 +72,6 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
// Reponse
res(await packGame(game, user));
publishReversiStream(exist.parentId, 'matched', await packGame(game, exist.parentId)); publishReversiStream(exist.parentId, 'matched', await packGame(game, exist.parentId));
const other = await Matching.count({ const other = await Matching.count({
@ -69,6 +81,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
if (other == 0) { if (other == 0) {
publishMainStream(user._id, 'reversiNoInvites'); publishMainStream(user._id, 'reversiNoInvites');
} }
return await packGame(game, user);
} else { } else {
// Fetch child // Fetch child
const child = await User.findOne({ const child = await User.findOne({
@ -80,7 +94,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (child === null) { if (child === null) {
return rej('user not found'); throw new ApiError(meta.errors.noSuchUser);
} }
// 以前のセッションはすべて削除しておく // 以前のセッションはすべて削除しておく
@ -95,14 +109,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
childId: child._id childId: child._id
}); });
// Reponse
res();
const packed = await packMatching(matching, child); const packed = await packMatching(matching, child);
// 招待
publishReversiStream(child._id, 'invited', packed); publishReversiStream(child._id, 'invited', packed);
publishMainStream(child._id, 'reversiInvited', packed); publishMainStream(child._id, 'reversiInvited', packed);
return;
} }
})); });

View file

@ -5,10 +5,10 @@ export const meta = {
requireCredential: true requireCredential: true
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
await Matching.remove({ await Matching.remove({
parentId: user._id parentId: user._id
}); });
res(); return;
})); });

View file

@ -60,7 +60,7 @@ const sort: any = {
'-attachedRemoteUsers': { attachedRemoteUsersCount: 1 }, '-attachedRemoteUsers': { attachedRemoteUsersCount: 1 },
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const q = {} as any; const q = {} as any;
if (ps.attachedToUserOnly) q.attachedUsersCount = { $ne: 0 }; if (ps.attachedToUserOnly) q.attachedUsersCount = { $ne: 0 };
if (ps.attachedToLocalUserOnly) q.attachedLocalUsersCount = { $ne: 0 }; if (ps.attachedToLocalUserOnly) q.attachedLocalUsersCount = { $ne: 0 };
@ -80,5 +80,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
} }
}); });
res(tags); return tags;
})); });

View file

@ -36,7 +36,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps) => new Promise(async (res, rej) => { export default define(meta, async (ps) => {
const hashtags = await Hashtag const hashtags = await Hashtag
.find({ .find({
tag: new RegExp('^' + escapeRegexp(ps.query.toLowerCase())) tag: new RegExp('^' + escapeRegexp(ps.query.toLowerCase()))
@ -48,5 +48,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
skip: ps.offset skip: ps.offset
}); });
res(hashtags.map(tag => tag.tag)); return hashtags.map(tag => tag.tag);
})); });

View file

@ -19,7 +19,7 @@ export const meta = {
requireCredential: false, requireCredential: false,
}; };
export default define(meta, () => new Promise(async (res, rej) => { export default define(meta, async () => {
const instance = await fetchMeta(); const instance = await fetchMeta();
const hidedTags = instance.hidedTags.map(t => t.toLowerCase()); const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
@ -49,7 +49,7 @@ export default define(meta, () => new Promise(async (res, rej) => {
//#endregion //#endregion
if (data.length == 0) { if (data.length == 0) {
return res([]); return [];
} }
const tags: { const tags: {
@ -141,5 +141,5 @@ export default define(meta, () => new Promise(async (res, rej) => {
usersCount: totalCounts[i].length usersCount: totalCounts[i].length
})); }));
res(stats); return stats;
})); });

View file

@ -54,7 +54,7 @@ const sort: any = {
'-updatedAt': { updatedAt: 1 }, '-updatedAt': { updatedAt: 1 },
}; };
export default define(meta, (ps, me) => new Promise(async (res, rej) => { export default define(meta, async (ps, me) => {
const q = { const q = {
tags: ps.tag, tags: ps.tag,
$and: [] $and: []
@ -79,5 +79,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
sort: sort[ps.sort], sort: sort[ps.sort],
}); });
res(await Promise.all(users.map(user => pack(user, me, { detail: true })))); return await Promise.all(users.map(user => pack(user, me, { detail: true })));
})); });

View file

@ -18,13 +18,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user, app) => new Promise(async (res, rej) => { export default define(meta, async (ps, user, app) => {
const isSecure = user != null && app == null; const isSecure = user != null && app == null;
// Serialize return await pack(user, user, {
res(await pack(user, user, {
detail: true, detail: true,
includeHasUnreadNotes: true, includeHasUnreadNotes: true,
includeSecrets: isSecure includeSecrets: isSecure
})); });
})); });

View file

@ -15,11 +15,11 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
const _token = ps.token.replace(/\s/g, ''); const _token = ps.token.replace(/\s/g, '');
if (user.twoFactorTempSecret == null) { if (user.twoFactorTempSecret == null) {
return rej('二段階認証の設定が開始されていません'); throw new Error('二段階認証の設定が開始されていません');
} }
const verified = (speakeasy as any).totp.verify({ const verified = (speakeasy as any).totp.verify({
@ -29,7 +29,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
if (!verified) { if (!verified) {
return rej('not verified'); throw new Error('not verified');
} }
await User.update(user._id, { await User.update(user._id, {
@ -39,5 +39,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -18,12 +18,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, user.password); const same = await bcrypt.compare(ps.password, user.password);
if (!same) { if (!same) {
return rej('incorrect password'); throw new Error('incorrect password');
} }
// Generate user's secret key // Generate user's secret key
@ -38,17 +38,17 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}); });
// Get the data URL of the authenticator URL // Get the data URL of the authenticator URL
QRCode.toDataURL(speakeasy.otpauthURL({ const dataUrl = await QRCode.toDataURL(speakeasy.otpauthURL({
secret: secret.base32, secret: secret.base32,
encoding: 'base32', encoding: 'base32',
label: user.username, label: user.username,
issuer: config.host issuer: config.host
}), (err, data_url) => { }));
res({
qr: data_url, return {
qr: dataUrl,
secret: secret.base32, secret: secret.base32,
label: user.username, label: user.username,
issuer: config.host issuer: config.host
}); };
}); });
}));

View file

@ -15,12 +15,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, user.password); const same = await bcrypt.compare(ps.password, user.password);
if (!same) { if (!same) {
return rej('incorrect password'); throw new Error('incorrect password');
} }
await User.update(user._id, { await User.update(user._id, {
@ -30,5 +30,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -26,7 +26,7 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Get tokens // Get tokens
const tokens = await AccessToken const tokens = await AccessToken
.find({ .find({
@ -39,7 +39,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
res(await Promise.all(tokens.map(token => pack(token.appId, user, { return await Promise.all(tokens.map(token => pack(token.appId, user, {
detail: true detail: true
})))); })));
})); });

View file

@ -19,12 +19,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Compare password // Compare password
const same = await bcrypt.compare(ps.currentPassword, user.password); const same = await bcrypt.compare(ps.currentPassword, user.password);
if (!same) { if (!same) {
return rej('incorrect password'); throw new Error('incorrect password');
} }
// Generate hash of password // Generate hash of password
@ -37,5 +37,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
} }
}); });
res(); return;
})); });

View file

@ -10,12 +10,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
await User.update({ _id: user._id }, { await User.update({ _id: user._id }, {
$set: { $set: {
pendingReceivedFollowRequestsCount: 0 pendingReceivedFollowRequestsCount: 0
} }
}); });
res(); return;
})); });

View file

@ -18,12 +18,12 @@ export const meta = {
} }
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
// Compare password // Compare password
const same = await bcrypt.compare(ps.password, user.password); const same = await bcrypt.compare(ps.password, user.password);
if (!same) { if (!same) {
return rej('incorrect password'); throw new Error('incorrect password');
} }
await User.update({ _id: user._id }, { await User.update({ _id: user._id }, {
@ -49,5 +49,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
createDeleteNotesJob(user); createDeleteNotesJob(user);
createDeleteDriveFilesJob(user); createDeleteDriveFilesJob(user);
res(); return;
})); });

View file

@ -11,8 +11,8 @@ export const meta = {
}, },
}; };
export default define(meta, (ps, user) => new Promise(async (res, rej) => { export default define(meta, async (ps, user) => {
createExportBlockingJob(user); createExportBlockingJob(user);
res(); return;
})); });

Some files were not shown because too many files have changed in this diff Show more