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`;
if (page) {
// Construct query
const query = {
followeeId: user._id
} as any;

View file

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

View file

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

View file

@ -5,18 +5,17 @@ import authenticate from './authenticate';
import call from './call';
import { IUser } from '../../models/user';
import { IApp } from '../../models/app';
import { ApiError } from './error';
export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
const body = ctx.is('multipart/form-data') ? (ctx.req as any).body : ctx.request.body;
const reply = (x?: any, y?: any) => {
if (x === undefined) {
const reply = (x?: any, y?: ApiError) => {
if (x == null) {
ctx.status = 204;
} else if (typeof x === 'number') {
ctx.status = x;
ctx.body = {
error: x === 500 ? 'INTERNAL_ERROR' : y
};
ctx.body = y;
} else {
ctx.body = x;
}
@ -29,7 +28,11 @@ export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
try {
[user, app] = await authenticate(body['i']);
} 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;
}
@ -39,7 +42,11 @@ export default async (endpoint: IEndpoint, ctx: Koa.BaseContext) => {
try {
res = await call(endpoint.name, user, app, body, (ctx.req as any).file);
} catch (e) {
if (e.kind == 'client') {
reply(400, e);
} else {
reply(500, e);
}
return;
}

View file

@ -2,6 +2,15 @@ import limiter from './limiter';
import { IUser } from '../../models/user';
import { IApp } from '../../models/app';
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) => {
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);
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) {
throw 'ACCESS_DENIED';
throw new ApiError(accessDenied);
}
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) {
throw 'YOUR_ACCOUNT_HAS_BEEN_SUSPENDED';
throw new ApiError(accessDenied, { reason: 'Your account has been suspended.' });
}
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) {
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)) {
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) {
@ -41,24 +62,31 @@ export default async (endpoint: string, user: IUser, app: IApp, data: any, file?
await limiter(ep, user); // Rate limit
} catch (e) {
// 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
try {
res = await ep.exec(data, user, app, file);
} catch (e) {
if (e && e.name == 'INVALID_PARAM') {
throw {
code: e.name,
param: e.param,
reason: e.message
};
} else {
if (e instanceof ApiError) {
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 Note from "../../../models/note";
import User, { isRemoteUser, isLocalUser } from "../../../models/user";
import Note from '../../../models/note';
import User, { isRemoteUser, isLocalUser } from '../../../models/user';
import { IdentifiableError } from '../../../misc/identifiable-error';
/**
* Get valied note for API processing
@ -12,7 +13,7 @@ export async function getValiedNote(noteId: mongo.ObjectID) {
});
if (note === null) {
throw 'note not found';
throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
}
return note;
@ -27,7 +28,7 @@ export async function getUser(userId: mongo.ObjectID) {
});
if (user == null) {
throw 'user not found';
throw new IdentifiableError('15348ddd-432d-49c2-8a5a-8069753becff', 'No such user.');
}
return user;

View file

@ -2,6 +2,7 @@ import * as fs from 'fs';
import { ILocalUser } from '../../models/user';
import { IApp } from '../../models/app';
import { IEndpointMeta } from './endpoints';
import { ApiError } from './error';
type Params<T extends IEndpointMeta> = {
[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];
};
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) => {
function cleanup() {
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);
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];
const x: any = {};
let err: Error = null;
let err: ApiError = null;
Object.entries(defs.params).some(([k, def]) => {
const [v, e] = def.validator.get(params[k]);
if (e) {
err = new Error(e.message);
err.name = 'INVALID_PARAM';
(err as any).param = k;
err = new ApiError({
message: 'Invalid param.',
code: 'INVALID_PARAM',
id: '3d81ceae-475f-4600-b2a8-2bc116157532',
}, {
param: k,
reason: e.message
});
return true;
} else {
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) => {
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
export default define(meta, async (ps) => {
const sort = {
_id: -1
};
@ -51,5 +47,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
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 }
};
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
export default define(meta, async (ps, me) => {
const q = {
'metadata.deletedAt': { $exists: false },
} as any;
@ -61,5 +61,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
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 define from '../../../define';
import DriveFile from '../../../../../models/drive-file';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: true,
@ -12,17 +13,25 @@ export const meta = {
validator: $.type(ID),
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({
_id: ps.fileId
});
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({
updatedAt: new Date(),
name: ps.name,
@ -35,7 +35,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
url: ps.url
});
res({
return {
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({
host: ps.host
});
res(emojis.map(e => ({
return emojis.map(e => ({
id: e._id,
name: e.name,
aliases: e.aliases,
host: e.host,
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({
_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 });
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({
_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 }, {
$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({
'_follower.host': ps.host
});
@ -29,5 +29,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
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 });
if (instance == null) {
return rej('instance not found');
throw new Error('instance not found');
}
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: {}
};
export default define(meta, (ps) => new Promise(async (res, rej) => {
export default define(meta, async (ps) => {
const code = rndstr({ length: 5, chars: '0-9' });
await RegistrationTicket.insert({
@ -21,7 +21,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
code: code
});
res({
return {
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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: {}
};
export default define(meta, (ps) => new Promise(async (res, rej) => {
export default define(meta, async (ps) => {
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({
_id: ps.reportId
});
if (report == null) {
return rej('report not found');
throw new Error('report not found');
}
await AbuseUserReport.remove({
_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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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);
@ -51,7 +51,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
}
});
res({
return {
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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 }
};
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
export default define(meta, async (ps, me) => {
const q = {
$and: []
} as any;
@ -99,5 +99,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
if (user.isAdmin) {
return rej('cannot silence admin');
throw new Error('cannot silence admin');
}
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
if (user.isAdmin) {
return rej('cannot suspend admin');
throw new Error('cannot suspend admin');
}
if (user.isModerator) {
return rej('cannot suspend moderator');
throw new Error('cannot suspend moderator');
}
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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;
if (ps.broadcasts) {
@ -506,5 +506,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
$set: set
}, { upsert: true });
res();
}));
return;
});

View file

@ -26,9 +26,10 @@ export const meta = {
}
};
export default define(meta, (ps) => new Promise((res, rej) => {
updatePersonById(ps.userId).then(() => res(), e => rej(e));
}));
export default define(meta, async (ps) => {
await updatePersonById(ps.userId);
return;
});
async function updatePersonById(userId: mongo.ObjectID) {
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({
_id: ps.userId
});
if (user == null) {
return rej('user not found');
throw new Error('user not found');
}
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,
};
export default define(meta, (ps) => new Promise(async (res, rej) => {
export default define(meta, async (ps) => {
const instance = await fetchMeta();
const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
@ -40,7 +40,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
//#endregion
if (data.length == 0) {
return res([]);
return [];
}
let tags: {
@ -66,5 +66,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
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 { createNote } from '../../../../remote/activitypub/models/note';
import Resolver from '../../../../remote/activitypub/resolver';
import { ApiError } from '../../error';
export const meta = {
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) => {
fetchAny(ps.uri)
.then(object => object != null ? res(object) : rej('object not found'))
.catch(e => rej(e));
}));
export default define(meta, async (ps) => {
const object = await fetchAny(ps.uri);
if (object) {
return object;
} else {
throw new ApiError(meta.errors.noSuchObject);
}
});
/***
* 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
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
});
// Response
res(await pack(app, null, {
return await pack(app, null, {
detail: true,
includeSecret: true
}));
}));
});
});

View file

@ -2,6 +2,7 @@ import $ from 'cafy';
import ID, { transform } from '../../../../misc/cafy-id';
import App, { pack } from '../../../../models/app';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
params: {
@ -9,22 +10,29 @@ export const meta = {
validator: $.type(ID),
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;
// Lookup app
const ap = await App.findOne({ _id: ps.appId });
if (ap === null) {
return rej('app not found');
throw new ApiError(meta.errors.noSuchApp);
}
// Send response
res(await pack(ap, user, {
return await pack(ap, user, {
detail: true,
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 AccessToken from '../../../../models/access-token';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
requireCredential: true,
@ -15,16 +16,24 @@ export const meta = {
token: {
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
const session = await AuthSess
.findOne({ token: ps.token });
if (session === null) {
return rej('session not found');
throw new ApiError(meta.errors.noSuchSession);
}
// Generate access token
@ -64,6 +73,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
}
});
// Response
res();
}));
return;
});

View file

@ -4,6 +4,7 @@ import App from '../../../../../models/app';
import AuthSess from '../../../../../models/auth-session';
import config from '../../../../../config';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: false,
@ -12,17 +13,25 @@ export const meta = {
appSecret: {
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
const app = await App.findOne({
secret: ps.appSecret
});
if (app == null) {
return rej('app not found');
throw new ApiError(meta.errors.noSuchApp);
}
// Generate token
@ -35,9 +44,8 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
token: token
});
// Response
res({
return {
token: doc.token,
url: `${config.auth_url}/${doc.token}`
});
}));
};
});

View file

@ -1,6 +1,7 @@
import $ from 'cafy';
import AuthSess, { pack } from '../../../../../models/auth-session';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: false,
@ -9,19 +10,26 @@ export const meta = {
token: {
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
const session = await AuthSess.findOne({
token: ps.token
});
if (session == null) {
return rej('session not found');
throw new ApiError(meta.errors.noSuchSession);
}
// Response
res(await pack(session, user));
}));
return await pack(session, user);
});

View file

@ -4,6 +4,7 @@ import AuthSess from '../../../../../models/auth-session';
import AccessToken from '../../../../../models/access-token';
import { pack } from '../../../../../models/user';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: false,
@ -16,17 +17,37 @@ export const meta = {
token: {
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
const app = await App.findOne({
secret: ps.appSecret
});
if (app == null) {
return rej('app not found');
throw new ApiError(meta.errors.noSuchApp);
}
// Fetch token
@ -37,11 +58,11 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
});
if (session === null) {
return rej('session not found');
throw new ApiError(meta.errors.noSuchSession);
}
if (session.userId == null) {
return rej('this session is not allowed yet');
throw new ApiError(meta.errors.pendingSession);
}
// Lookup access token
@ -61,11 +82,10 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
_id: session._id
});
// Response
res({
return {
accessToken: accessToken.token,
user: await pack(session.userId, null, {
detail: true
})
});
}));
};
});

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Blocking from '../../../../models/blocking';
import create from '../../../../services/blocking/create';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'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;
// 自分自身
if (user._id.equals(ps.userId)) {
return rej('blockee is yourself');
throw new ApiError(meta.errors.blockeeIsYourself);
}
// Get blockee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (blockee === null) {
return rej('user not found');
throw new ApiError(meta.errors.noSuchUser);
}
// Check if already blocking
@ -64,14 +85,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (exist !== null) {
return rej('already blocking');
throw new ApiError(meta.errors.alreadyBlocking);
}
// Create blocking
await create(blocker, blockee);
// Send response
res(await pack(blockee._id, user, {
return await pack(blockee._id, user, {
detail: true
}));
}));
});
});

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Blocking from '../../../../models/blocking';
import deleteBlocking from '../../../../services/blocking/delete';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'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;
// Check if the blockee is yourself
if (user._id.equals(ps.userId)) {
return rej('blockee is yourself');
throw new ApiError(meta.errors.blockeeIsYourself);
}
// Get blockee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (blockee === null) {
return rej('user not found');
throw new ApiError(meta.errors.noSuchUser);
}
// Check not blocking
@ -64,14 +85,13 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (exist === null) {
return rej('already not blocking');
throw new ApiError(meta.errors.notBlocking);
}
// Delete blocking
await deleteBlocking(blocker, blockee);
// Send response
res(await pack(blockee._id, user, {
return await pack(blockee._id, user, {
detail: true
}));
}));
});
});

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -41,12 +41,7 @@ export const meta = {
}
};
export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
export default define(meta, async (ps, user) => {
const sort = {
_id: -1
};
@ -78,5 +73,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
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 define from '../../../define';
import { packMany } from '../../../../../models/note';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -25,10 +26,18 @@ export const meta = {
'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
const file = await DriveFile
.findOne({
@ -38,10 +47,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
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
}));
}));
});
});

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({
md5: ps.md5,
'metadata.userId': user._id,
'metadata.deletedAt': { $exists: false }
});
if (file === null) {
res({ file: null });
} else {
res({ file: await pack(file, { self: true }) });
}
}));
return { file: file ? await pack(file, { self: true }) : null };
});

View file

@ -5,6 +5,7 @@ import { validateFileName, pack } from '../../../../../models/drive-file';
import create from '../../../../../services/drive/add-file';
import define from '../../../define';
import { apiLogger } from '../../../logger';
import { ApiError } from '../../../error';
export const meta = {
desc: {
@ -51,10 +52,18 @@ export const meta = {
'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
let name = file.originalname;
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') {
name = null;
} else if (!validateFileName(name)) {
return rej('invalid name');
throw new ApiError(meta.errors.invalidFileName);
}
} else {
name = null;
@ -73,15 +82,11 @@ export default define(meta, (ps, user, app, file, cleanup) => new Promise(async
try {
// Create file
const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
cleanup();
res(pack(driveFile, { self: true }));
return pack(driveFile, { self: true });
} catch (e) {
apiLogger.error(e);
throw new ApiError();
} finally {
cleanup();
rej(e);
}
}));
});

View file

@ -4,6 +4,7 @@ import DriveFile from '../../../../../models/drive-file';
import del from '../../../../../services/drive/delete-file';
import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -26,10 +27,24 @@ export const meta = {
'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
const file = await DriveFile
.findOne({
@ -37,11 +52,11 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
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)) {
return rej('access denied');
throw new ApiError(meta.errors.accessDenied);
}
// Delete
@ -50,5 +65,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Publish fileDeleted event
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
.find({
filename: ps.name,
@ -32,5 +32,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
'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 define from '../../../define';
import config from '../../../../../config';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -34,10 +35,30 @@ export const meta = {
'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;
if (ps.fileId) {
@ -69,22 +90,19 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
}
} else {
return rej('fileId or url required');
throw new ApiError(meta.errors.fileIdOrUrlRequired);
}
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
return rej('access denied');
throw new ApiError(meta.errors.accessDenied);
}
if (file === null) {
return rej('file-not-found');
throw new ApiError(meta.errors.noSuchFile);
}
// Serialize
const _file = await pack(file, {
return await pack(file, {
detail: 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 define from '../../../define';
import Note from '../../../../../models/note';
import { ApiError } from '../../../error';
export const meta = {
desc: {
@ -51,10 +52,30 @@ export const meta = {
'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
const file = await DriveFile
.findOne({
@ -62,11 +83,11 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
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)) {
return rej('access denied');
throw new ApiError(meta.errors.accessDenied);
}
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) {
return rej('folder-not-found');
throw new ApiError(meta.errors.noSuchFolder);
}
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 });
// Response
res(fileObj);
// Publish fileUpdated event
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) => {
res(pack(await uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force), { self: true }));
}));
export default define(meta, async (ps, user) => {
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) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
export default define(meta, async (ps, user) => {
const sort = {
_id: -1
};
@ -67,5 +62,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
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 { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -34,10 +35,18 @@ export const meta = {
'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
let parent = null;
if (ps.parentId) {
@ -49,7 +58,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
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
});
// Serialize
const folderObj = await pack(folder);
// Response
res(folderObj);
// Publish folderCreated event
publishDriveStream(user._id, 'folderCreated', folderObj);
}));
return folderObj;
});

View file

@ -4,6 +4,7 @@ import DriveFolder from '../../../../../models/drive-folder';
import define from '../../../define';
import { publishDriveStream } from '../../../../../services/stream';
import DriveFile from '../../../../../models/drive-file';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -26,10 +27,24 @@ export const meta = {
'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
const folder = await DriveFolder
.findOne({
@ -38,7 +53,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (folder === null) {
return rej('folder-not-found');
throw new ApiError(meta.errors.noSuchFolder);
}
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) {
return rej('has-child-contents');
throw new ApiError(meta.errors.hasChildFilesOrFolders);
}
await DriveFolder.remove({ _id: folder._id });
@ -55,5 +70,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Publish folderCreated event
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
.find({
name: ps.name,
@ -32,5 +32,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
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 DriveFolder, { pack } from '../../../../../models/drive-folder';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -24,10 +25,18 @@ export const meta = {
'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
const folder = await DriveFolder
.findOne({
@ -36,11 +45,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (folder === null) {
return rej('folder-not-found');
throw new ApiError(meta.errors.noSuchFolder);
}
// Serialize
res(await pack(folder, {
return await pack(folder, {
detail: true
}));
}));
});
});

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../misc/cafy-id';
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
import { publishDriveStream } from '../../../../../services/stream';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
stability: 'stable',
@ -42,10 +43,30 @@ export const meta = {
'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
const folder = await DriveFolder
.findOne({
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (folder === null) {
return rej('folder-not-found');
throw new ApiError(meta.errors.noSuchFolder);
}
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) {
return rej('parent-folder-not-found');
throw new ApiError(meta.errors.noSuchParentFolder);
}
// 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 (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);
// Response
res(folderObj);
// Publish folderUpdated event
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) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
export default define(meta, async (ps, user) => {
const sort = {
_id: -1
};
@ -66,5 +61,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
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;
if (ps.sort) {
@ -122,5 +122,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
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
.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 create from '../../../../services/following/create';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
stability: 'stable',
@ -32,15 +33,47 @@ export const meta = {
'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;
// 自分自身
if (user._id.equals(ps.userId)) {
return rej('followee is yourself');
throw new ApiError(meta.errors.followeeIsYourself);
}
// Get followee
@ -54,7 +87,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (followee === null) {
return rej('user not found');
throw new ApiError(meta.errors.noSuchUser);
}
// Check if already following
@ -64,16 +97,16 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (exist !== null) {
return rej('already following');
throw new ApiError(meta.errors.alreadyFollowing);
}
// Create following
try {
await create(follower, followee);
} 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
res(await pack(followee._id, user));
}));
return await pack(followee._id, user);
});

View file

@ -5,6 +5,7 @@ import User, { pack } from '../../../../models/user';
import Following from '../../../../models/following';
import deleteFollowing from '../../../../services/following/delete';
import define from '../../define';
import { ApiError } from '../../error';
export const meta = {
stability: 'stable',
@ -32,15 +33,35 @@ export const meta = {
'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;
// Check if the followee is yourself
if (user._id.equals(ps.userId)) {
return rej('followee is yourself');
throw new ApiError(meta.errors.followeeIsYourself);
}
// Get followee
@ -54,7 +75,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (followee === null) {
return rej('user not found');
throw new ApiError(meta.errors.noSuchUser);
}
// Check not following
@ -64,12 +85,10 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (exist === null) {
return rej('already not following');
throw new ApiError(meta.errors.notFollowing);
}
// Delete following
await deleteFollowing(follower, followee);
// Send response
res(await pack(followee._id, user));
}));
return 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 User from '../../../../../models/user';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
desc: {
@ -23,20 +24,28 @@ export const meta = {
'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
const follower = await User.findOne({
_id: ps.userId
});
if (follower === null) {
return rej('follower not found');
throw new ApiError(meta.errors.noSuchUser);
}
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 User, { pack } from '../../../../../models/user';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
desc: {
@ -23,24 +24,39 @@ export const meta = {
'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
const followee = await User.findOne({
_id: ps.userId
});
if (followee === null) {
return rej('followee not found');
throw new ApiError(meta.errors.noSuchUser);
}
try {
await cancelFollowRequest(followee, user);
} 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 define from '../../../define';
@ -14,11 +12,10 @@ export const meta = {
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({
followeeId: user._id
});
// Send response
res(await Promise.all(reqs.map(req => pack(req))));
}));
return 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 User from '../../../../../models/user';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
desc: {
@ -23,20 +24,28 @@ export const meta = {
'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
const follower = await User.findOne({
_id: ps.userId
});
if (follower === null) {
return rej('follower not found');
throw new ApiError(meta.errors.noSuchUser);
}
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) => {
// Check if both of sinceId and untilId is specified
if (ps.sinceId && ps.untilId) {
return rej('cannot set sinceId and untilId');
}
export default define(meta, async (ps, user) => {
const q: any = ps.my ? {
isStarted: true,
$or: [{
@ -65,8 +60,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
limit: ps.limit
});
// Reponse
res(Promise.all(games.map(async (g) => await pack(g, user, {
return await Promise.all(games.map((g) => pack(g, user, {
detail: false
}))));
}));
})));
});

View file

@ -3,6 +3,7 @@ import ID, { transform } from '../../../../../../misc/cafy-id';
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
import Reversi from '../../../../../../games/reversi/core';
import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = {
params: {
@ -10,14 +11,22 @@ export const meta = {
validator: $.type(ID),
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 });
if (game == null) {
return rej('game not found');
throw new ApiError(meta.errors.noSuchGame);
}
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);
res(Object.assign({
return Object.assign({
board: o.board,
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 { publishReversiGameStream } from '../../../../../../services/stream';
import define from '../../../../define';
import { ApiError } from '../../../../error';
export const meta = {
desc: {
@ -19,22 +20,42 @@ export const meta = {
'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 });
if (game == null) {
return rej('game not found');
throw new ApiError(meta.errors.noSuchGame);
}
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)) {
return rej('access denied');
throw new ApiError(meta.errors.accessDenied);
}
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)
});
res();
}));
return;
});

View file

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

View file

@ -6,6 +6,7 @@ import User from '../../../../../models/user';
import { publishMainStream, publishReversiStream } from '../../../../../services/stream';
import { eighteight } from '../../../../../games/reversi/maps';
import define from '../../../define';
import { ApiError } from '../../../error';
export const meta = {
requireCredential: true,
@ -19,13 +20,27 @@ export const meta = {
'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
if (ps.userId.equals(user._id)) {
return rej('invalid userId param');
throw new ApiError(meta.errors.isYourself);
}
// 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));
const other = await Matching.count({
@ -69,6 +81,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
if (other == 0) {
publishMainStream(user._id, 'reversiNoInvites');
}
return await packGame(game, user);
} else {
// Fetch child
const child = await User.findOne({
@ -80,7 +94,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
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
});
// Reponse
res();
const packed = await packMatching(matching, child);
// 招待
publishReversiStream(child._id, 'invited', packed);
publishMainStream(child._id, 'reversiInvited', packed);
return;
}
}));
});

View file

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

View file

@ -60,7 +60,7 @@ const sort: any = {
'-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;
if (ps.attachedToUserOnly) q.attachedUsersCount = { $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
.find({
tag: new RegExp('^' + escapeRegexp(ps.query.toLowerCase()))
@ -48,5 +48,5 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
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,
};
export default define(meta, () => new Promise(async (res, rej) => {
export default define(meta, async () => {
const instance = await fetchMeta();
const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
@ -49,7 +49,7 @@ export default define(meta, () => new Promise(async (res, rej) => {
//#endregion
if (data.length == 0) {
return res([]);
return [];
}
const tags: {
@ -141,5 +141,5 @@ export default define(meta, () => new Promise(async (res, rej) => {
usersCount: totalCounts[i].length
}));
res(stats);
}));
return stats;
});

View file

@ -54,7 +54,7 @@ const sort: any = {
'-updatedAt': { updatedAt: 1 },
};
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
export default define(meta, async (ps, me) => {
const q = {
tags: ps.tag,
$and: []
@ -79,5 +79,5 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
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;
// Serialize
res(await pack(user, user, {
return await pack(user, user, {
detail: true,
includeHasUnreadNotes: true,
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, '');
if (user.twoFactorTempSecret == null) {
return rej('二段階認証の設定が開始されていません');
throw new Error('二段階認証の設定が開始されていません');
}
const verified = (speakeasy as any).totp.verify({
@ -29,7 +29,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
});
if (!verified) {
return rej('not verified');
throw new Error('not verified');
}
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
const same = await bcrypt.compare(ps.password, user.password);
if (!same) {
return rej('incorrect password');
throw new Error('incorrect password');
}
// 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
QRCode.toDataURL(speakeasy.otpauthURL({
const dataUrl = await QRCode.toDataURL(speakeasy.otpauthURL({
secret: secret.base32,
encoding: 'base32',
label: user.username,
issuer: config.host
}), (err, data_url) => {
res({
qr: data_url,
}));
return {
qr: dataUrl,
secret: secret.base32,
label: user.username,
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
const same = await bcrypt.compare(ps.password, user.password);
if (!same) {
return rej('incorrect password');
throw new Error('incorrect password');
}
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
const tokens = await AccessToken
.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
}))));
}));
})));
});

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
const same = await bcrypt.compare(ps.currentPassword, user.password);
if (!same) {
return rej('incorrect password');
throw new Error('incorrect 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 }, {
$set: {
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
const same = await bcrypt.compare(ps.password, user.password);
if (!same) {
return rej('incorrect password');
throw new Error('incorrect password');
}
await User.update({ _id: user._id }, {
@ -49,5 +49,5 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
createDeleteNotesJob(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);
res();
}));
return;
});

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