良い感じに
This commit is contained in:
		
							parent
							
								
									1e4a86da8e
								
							
						
					
					
						commit
						1744316656
					
				|  | @ -1,12 +1,12 @@ | |||
| import * as Koa from 'koa'; | ||||
| 
 | ||||
| import Endpoint from './endpoint'; | ||||
| import { IEndpoint } from './endpoints'; | ||||
| import authenticate from './authenticate'; | ||||
| import call from './call'; | ||||
| import { IUser } from '../../models/user'; | ||||
| import { IApp } from '../../models/app'; | ||||
| 
 | ||||
| export default async (endpoint: Endpoint, ctx: Koa.Context) => { | ||||
| export default async (endpoint: IEndpoint, ctx: Koa.Context) => { | ||||
| 	const body = ctx.is('multipart/form-data') ? (ctx.req as any).body : ctx.request.body; | ||||
| 
 | ||||
| 	const reply = (x?: any, y?: any) => { | ||||
|  | @ -37,7 +37,7 @@ export default async (endpoint: Endpoint, ctx: Koa.Context) => { | |||
| 
 | ||||
| 	// API invoking
 | ||||
| 	try { | ||||
| 		res = await call(endpoint, user, app, body, (ctx.req as any).file); | ||||
| 		res = await call(endpoint.name, user, app, body, (ctx.req as any).file); | ||||
| 	} catch (e) { | ||||
| 		reply(400, e); | ||||
| 		return; | ||||
|  |  | |||
|  | @ -1,35 +1,12 @@ | |||
| import * as path from 'path'; | ||||
| import * as glob from 'glob'; | ||||
| 
 | ||||
| import Endpoint from './endpoint'; | ||||
| import limitter from './limitter'; | ||||
| import { IUser } from '../../models/user'; | ||||
| import { IApp } from '../../models/app'; | ||||
| import endpoints from './endpoints'; | ||||
| 
 | ||||
| const files = glob.sync('**/*.js', { | ||||
| 	cwd: path.resolve(__dirname + '/endpoints/') | ||||
| }); | ||||
| 
 | ||||
| const endpoints: Array<{ | ||||
| 	exec: any, | ||||
| 	meta: Endpoint | ||||
| }> = files.map(f => { | ||||
| 	const ep = require('./endpoints/' + f); | ||||
| 
 | ||||
| 	ep.meta = ep.meta || {}; | ||||
| 	ep.meta.name = f.replace('.js', ''); | ||||
| 
 | ||||
| 	return { | ||||
| 		exec: ep.default, | ||||
| 		meta: ep.meta | ||||
| 	}; | ||||
| }); | ||||
| 
 | ||||
| export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => { | ||||
| export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => { | ||||
| 	const isSecure = user != null && app == null; | ||||
| 
 | ||||
| 	const epName = typeof endpoint === 'string' ? endpoint : endpoint.name; | ||||
| 	const ep = endpoints.find(e => e.meta.name === epName); | ||||
| 	const ep = endpoints.find(e => e.name === endpoint); | ||||
| 
 | ||||
| 	if (ep.meta.secure && !isSecure) { | ||||
| 		return rej('ACCESS_DENIED'); | ||||
|  | @ -51,7 +28,7 @@ export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, | |||
| 
 | ||||
| 	if (ep.meta.requireCredential && ep.meta.limit) { | ||||
| 		try { | ||||
| 			await limitter(ep.meta, user); // Rate limit
 | ||||
| 			await limitter(ep, user); // Rate limit
 | ||||
| 		} catch (e) { | ||||
| 			// drop request if limit exceeded
 | ||||
| 			return rej('RATE_LIMIT_EXCEEDED'); | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| export default interface IEndpoint { | ||||
| 	/** | ||||
| 	 * エンドポイント名 | ||||
| 	 */ | ||||
| 	name: string; | ||||
| import * as path from 'path'; | ||||
| import * as glob from 'glob'; | ||||
| 
 | ||||
| export interface IEndpointMeta { | ||||
| 	/** | ||||
| 	 * このエンドポイントにリクエストするのにユーザー情報が必須か否か | ||||
| 	 * 省略した場合は false として解釈されます。 | ||||
|  | @ -58,3 +56,25 @@ export default interface IEndpoint { | |||
| 	 */ | ||||
| 	kind?: string; | ||||
| } | ||||
| 
 | ||||
| export interface IEndpoint { | ||||
| 	name: string; | ||||
| 	exec: any; | ||||
| 	meta: IEndpointMeta; | ||||
| } | ||||
| 
 | ||||
| const files = glob.sync('**/*.js', { | ||||
| 	cwd: path.resolve(__dirname + '/endpoints/') | ||||
| }); | ||||
| 
 | ||||
| const endpoints: IEndpoint[] = files.map(f => { | ||||
| 	const ep = require('./endpoints/' + f); | ||||
| 
 | ||||
| 	return { | ||||
| 		name: f.replace('.js', ''), | ||||
| 		exec: ep.default, | ||||
| 		meta: ep.meta || {} | ||||
| 	}; | ||||
| }); | ||||
| 
 | ||||
| export default endpoints; | ||||
|  | @ -1,8 +1,36 @@ | |||
| import * as fs from 'fs'; | ||||
| const ms = require('ms'); | ||||
| import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; | ||||
| import { validateFileName, pack } from '../../../../../models/drive-file'; | ||||
| import create from '../../../../../services/drive/add-file'; | ||||
| import { ILocalUser } from '../../../../../models/user'; | ||||
| import getParams from '../../../get-params'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	desc: { | ||||
| 		ja: 'ドライブにファイルをアップロードします。' | ||||
| 	}, | ||||
| 
 | ||||
| 	requireCredential: true, | ||||
| 
 | ||||
| 	limit: { | ||||
| 		duration: ms('1hour'), | ||||
| 		max: 100 | ||||
| 	}, | ||||
| 
 | ||||
| 	withFile: true, | ||||
| 
 | ||||
| 	kind: 'drive-write', | ||||
| 
 | ||||
| 	params: { | ||||
| 		folderId: $.type(ID).optional.nullable.note({ | ||||
| 			default: null, | ||||
| 			desc: { | ||||
| 				ja: 'フォルダID' | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Create a file | ||||
|  | @ -27,17 +55,19 @@ export default async (file: any, params: any, user: ILocalUser): Promise<any> => | |||
| 		name = null; | ||||
| 	} | ||||
| 
 | ||||
| 	// Get 'folderId' parameter
 | ||||
| 	const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId); | ||||
| 	if (folderIdErr) throw 'invalid folderId param'; | ||||
| 
 | ||||
| 	function cleanup() { | ||||
| 		fs.unlink(file.path, () => {}); | ||||
| 	} | ||||
| 
 | ||||
| 	const [ps, psErr] = getParams(meta, params); | ||||
| 	if (psErr) { | ||||
| 		cleanup(); | ||||
| 		throw psErr; | ||||
| 	} | ||||
| 
 | ||||
| 	try { | ||||
| 		// Create file
 | ||||
| 		const driveFile = await create(user, file.path, name, null, folderId); | ||||
| 		const driveFile = await create(user, file.path, name, null, ps.folderId); | ||||
| 
 | ||||
| 		cleanup(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { IApp } from '../../../../models/app'; | |||
| import getParams from '../../get-params'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	name: 'notes/create', | ||||
| 
 | ||||
| 	desc: { | ||||
| 		ja: '投稿します。' | ||||
| 	}, | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ const router = new Router(); | |||
| /** | ||||
|  * Register endpoint handlers | ||||
|  */ | ||||
| endpoints.forEach(endpoint => endpoint.withFile | ||||
| endpoints.forEach(endpoint => endpoint.meta.withFile | ||||
| 	? router.post(`/${endpoint.name}`, upload.single('file'), handler.bind(null, endpoint)) | ||||
| 	: router.post(`/${endpoint.name}`, handler.bind(null, endpoint)) | ||||
| ); | ||||
|  |  | |||
|  | @ -1,14 +1,14 @@ | |||
| import * as Limiter from 'ratelimiter'; | ||||
| import * as debug from 'debug'; | ||||
| import limiterDB from '../../db/redis'; | ||||
| import Endpoint from './endpoint'; | ||||
| import { IEndpoint } from './endpoints'; | ||||
| import getAcct from '../../misc/acct/render'; | ||||
| import { IUser } from '../../models/user'; | ||||
| 
 | ||||
| const log = debug('misskey:limitter'); | ||||
| 
 | ||||
| export default (endpoint: Endpoint, user: IUser) => new Promise((ok, reject) => { | ||||
| 	const limitation = endpoint.limit; | ||||
| export default (endpoint: IEndpoint, user: IUser) => new Promise((ok, reject) => { | ||||
| 	const limitation = endpoint.meta.limit; | ||||
| 
 | ||||
| 	const key = limitation.hasOwnProperty('key') | ||||
| 		? limitation.key | ||||
|  |  | |||
|  | @ -168,14 +168,15 @@ router.get('/assets/*', async ctx => { | |||
| 
 | ||||
| router.get('/*/api/endpoints/*', async ctx => { | ||||
| 	const lang = ctx.params[0]; | ||||
| 	const ep = require('../../../built/server/api/endpoints/' + ctx.params[1]).meta; | ||||
| 	const name = ctx.params[1]; | ||||
| 	const ep = require('../../../built/server/api/endpoints/' + name).meta || {}; | ||||
| 
 | ||||
| 	const vars = { | ||||
| 		title: ep.name, | ||||
| 		endpoint: ep.name, | ||||
| 		title: name, | ||||
| 		endpoint: name, | ||||
| 		url: { | ||||
| 			host: config.api_url, | ||||
| 			path: ep.name | ||||
| 			path: name | ||||
| 		}, | ||||
| 		desc: ep.desc, | ||||
| 		// @ts-ignore
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue