diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2020-03-28 11:24:37 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2020-03-28 11:24:37 +0900 |
| commit | 6be127e18bdbea6031698baeb8632f917a8346eb (patch) | |
| tree | 4b7ceb082d76b0628df6496bc802172106721ce9 /src/server | |
| parent | wip (diff) | |
| download | sharkey-6be127e18bdbea6031698baeb8632f917a8346eb.tar.gz sharkey-6be127e18bdbea6031698baeb8632f917a8346eb.tar.bz2 sharkey-6be127e18bdbea6031698baeb8632f917a8346eb.zip | |
Implement MiAuth
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/api/authenticate.ts | 24 | ||||
| -rw-r--r-- | src/server/api/call.ts | 7 | ||||
| -rw-r--r-- | src/server/api/define.ts | 9 | ||||
| -rw-r--r-- | src/server/api/endpoints/app/show.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/drive/files/create.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/i.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/miauth/gen-token.ts | 54 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/create.ts | 3 | ||||
| -rw-r--r-- | src/server/api/index.ts | 24 | ||||
| -rw-r--r-- | src/server/api/stream/index.ts | 5 |
11 files changed, 115 insertions, 25 deletions
diff --git a/src/server/api/authenticate.ts b/src/server/api/authenticate.ts index 519ed77388..32ad3b4019 100644 --- a/src/server/api/authenticate.ts +++ b/src/server/api/authenticate.ts @@ -1,7 +1,11 @@ import isNativeToken from './common/is-native-token'; import { User } from '../../models/entities/user'; -import { App } from '../../models/entities/app'; import { Users, AccessTokens, Apps } from '../../models'; +import { ensure } from '../../prelude/ensure'; + +type App = { + permission: string[]; +}; export default async (token: string): Promise<[User | null | undefined, App | null | undefined]> => { if (token == null) { @@ -27,14 +31,26 @@ export default async (token: string): Promise<[User | null | undefined, App | nu throw new Error('invalid signature'); } - const app = await Apps - .findOne(accessToken.appId); + AccessTokens.update(accessToken.id, { + lastUsedAt: new Date(), + }); const user = await Users .findOne({ id: accessToken.userId // findOne(accessToken.userId) のように書かないのは後方互換性のため }); - return [user, app]; + if (accessToken.appId) { + const app = await Apps + .findOne(accessToken.appId).then(ensure); + + return [user, { + permission: app.permission + }]; + } else { + return [user, { + permission: accessToken.permission + }]; + } } }; diff --git a/src/server/api/call.ts b/src/server/api/call.ts index 37bcf7ce16..c75006ef31 100644 --- a/src/server/api/call.ts +++ b/src/server/api/call.ts @@ -4,7 +4,10 @@ import { User } from '../../models/entities/user'; import endpoints from './endpoints'; import { ApiError } from './error'; import { apiLogger } from './logger'; -import { App } from '../../models/entities/app'; + +type App = { + permission: string[]; +}; const accessDenied = { message: 'Access denied.', @@ -73,7 +76,7 @@ export default async (endpoint: string, user: User | null | undefined, app: App // API invoking const before = performance.now(); - return await ep.exec(data, user, app, file).catch((e: Error) => { + return await ep.exec(data, user, isSecure, file).catch((e: Error) => { if (e instanceof ApiError) { throw e; } else { diff --git a/src/server/api/define.ts b/src/server/api/define.ts index 1fd4543bd0..3c9e6863b7 100644 --- a/src/server/api/define.ts +++ b/src/server/api/define.ts @@ -2,7 +2,6 @@ import * as fs from 'fs'; import { ILocalUser } from '../../models/entities/user'; import { IEndpointMeta } from './endpoints'; import { ApiError } from './error'; -import { App } from '../../models/entities/app'; import { SchemaType } from '../../misc/schema'; // TODO: defaultが設定されている場合はその型も考慮する @@ -15,12 +14,12 @@ type Params<T extends IEndpointMeta> = { export type Response = Record<string, any> | void; type executor<T extends IEndpointMeta> = - (params: Params<T>, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, app: App, file?: any, cleanup?: Function) => + (params: Params<T>, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, isSecure: boolean, file?: any, cleanup?: Function) => Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>; export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>) - : (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, app: App, file?: any) => Promise<any> { - return (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, app: App, file?: any) => { + : (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, isSecure: boolean, file?: any) => Promise<any> { + return (params: any, user: T['requireCredential'] extends true ? ILocalUser : ILocalUser | null, isSecure: boolean, file?: any) => { function cleanup() { fs.unlink(file.path, () => {}); } @@ -37,7 +36,7 @@ export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>) return Promise.reject(pserr); } - return cb(ps, user, app, file, cleanup); + return cb(ps, user, isSecure, file, cleanup); }; } diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts index 2c8cdbe396..c1bbb2c53e 100644 --- a/src/server/api/endpoints/app/show.ts +++ b/src/server/api/endpoints/app/show.ts @@ -28,9 +28,7 @@ export const meta = { } }; -export default define(meta, async (ps, user, app) => { - const isSecure = user != null && app == null; - +export default define(meta, async (ps, user, isSecure) => { // Lookup app const ap = await Apps.findOne(ps.appId); diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts index 3c5c982534..5043fbb8e7 100644 --- a/src/server/api/endpoints/drive/files/create.ts +++ b/src/server/api/endpoints/drive/files/create.ts @@ -78,7 +78,7 @@ export const meta = { } }; -export default define(meta, async (ps, user, app, file, cleanup) => { +export default define(meta, async (ps, user, isSecure, file, cleanup) => { // Get 'name' parameter let name = ps.name || file.originalname; if (name !== undefined && name !== null) { diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts index d22de40c69..3909d54663 100644 --- a/src/server/api/endpoints/i.ts +++ b/src/server/api/endpoints/i.ts @@ -19,9 +19,7 @@ export const meta = { }, }; -export default define(meta, async (ps, user, app) => { - const isSecure = user != null && app == null; - +export default define(meta, async (ps, user, isSecure) => { return await Users.pack(user, user, { detail: true, includeHasUnreadNotes: true, diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index 5c4a9576e1..0a3ba824ae 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -178,9 +178,7 @@ export const meta = { } }; -export default define(meta, async (ps, user, app) => { - const isSecure = user != null && app == null; - +export default define(meta, async (ps, user, isSecure) => { const updates = {} as Partial<User>; const profileUpdates = {} as Partial<UserProfile>; diff --git a/src/server/api/endpoints/miauth/gen-token.ts b/src/server/api/endpoints/miauth/gen-token.ts new file mode 100644 index 0000000000..599ecf477e --- /dev/null +++ b/src/server/api/endpoints/miauth/gen-token.ts @@ -0,0 +1,54 @@ +import rndstr from 'rndstr'; +import $ from 'cafy'; +import define from '../../define'; +import { AccessTokens } from '../../../../models'; +import { genId } from '../../../../misc/gen-id'; + +export const meta = { + tags: ['auth'], + + requireCredential: true as const, + + secure: true, + + params: { + session: { + validator: $.str + }, + + name: { + validator: $.nullable.optional.str + }, + + description: { + validator: $.nullable.optional.str, + }, + + iconUrl: { + validator: $.nullable.optional.str, + }, + + permission: { + validator: $.arr($.str).unique(), + }, + }, +}; + +export default define(meta, async (ps, user) => { + // Generate access token + const accessToken = rndstr('a-zA-Z0-9', 32); + + // Insert access token doc + await AccessTokens.save({ + id: genId(), + createdAt: new Date(), + session: ps.session, + userId: user.id, + token: accessToken, + hash: accessToken, + name: ps.name, + description: ps.description, + iconUrl: ps.iconUrl, + permission: ps.permission, + }); +}); diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index e983ad6fd6..cccf138add 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -209,7 +209,7 @@ export const meta = { } }; -export default define(meta, async (ps, user, app) => { +export default define(meta, async (ps, user) => { let visibleUsers: User[] = []; if (ps.visibleUserIds) { visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id)))) @@ -281,7 +281,6 @@ export default define(meta, async (ps, user, app) => { reply, renote, cw: ps.cw, - app, viaMobile: ps.viaMobile, localOnly: ps.localOnly, visibility: ps.visibility, diff --git a/src/server/api/index.ts b/src/server/api/index.ts index 258e632bd8..49209ede43 100644 --- a/src/server/api/index.ts +++ b/src/server/api/index.ts @@ -15,7 +15,7 @@ import signin from './private/signin'; import discord from './service/discord'; import github from './service/github'; import twitter from './service/twitter'; -import { Instances } from '../../models'; +import { Instances, AccessTokens, Users } from '../../models'; // Init app const app = new Koa(); @@ -73,6 +73,28 @@ router.get('/v1/instance/peers', async ctx => { ctx.body = instances.map(instance => instance.host); }); +router.post('/miauth/:session/check', async ctx => { + const token = await AccessTokens.findOne({ + session: ctx.params.session + }); + + if (token && !token.fetched) { + AccessTokens.update(token.id, { + fetched: true + }); + + ctx.body = { + ok: true, + token: token.token, + user: await Users.pack(token.userId, null, { detail: true }) + }; + } else { + ctx.body = { + ok: false, + }; + } +}); + // Return 404 for unknown API router.all('*', async ctx => { ctx.status = 404; diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 463ae0a601..4b233b9a8b 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -7,10 +7,13 @@ import Channel from './channel'; import channels from './channels'; import { EventEmitter } from 'events'; import { User } from '../../../models/entities/user'; -import { App } from '../../../models/entities/app'; import { Users, Followings, Mutings } from '../../../models'; import { ApiError } from '../error'; +type App = { + permission: string[]; +}; + /** * Main stream connection */ |