From 0e4a111f81cceed275d9bec2695f6e401fb654d8 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 12 Nov 2021 02:02:25 +0900 Subject: refactoring Resolve #7779 --- .../server/api/endpoints/auth/session/generate.ts | 70 ++++++++++++++++ .../src/server/api/endpoints/auth/session/show.ts | 58 +++++++++++++ .../server/api/endpoints/auth/session/userkey.ts | 98 ++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 packages/backend/src/server/api/endpoints/auth/session/generate.ts create mode 100644 packages/backend/src/server/api/endpoints/auth/session/show.ts create mode 100644 packages/backend/src/server/api/endpoints/auth/session/userkey.ts (limited to 'packages/backend/src/server/api/endpoints/auth/session') diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts new file mode 100644 index 0000000000..859cf52ed3 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -0,0 +1,70 @@ +import { v4 as uuid } from 'uuid'; +import $ from 'cafy'; +import config from '@/config/index'; +import define from '../../../define'; +import { ApiError } from '../../../error'; +import { Apps, AuthSessions } from '@/models/index'; +import { genId } from '@/misc/gen-id'; + +export const meta = { + tags: ['auth'], + + requireCredential: false as const, + + params: { + appSecret: { + validator: $.str, + } + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + token: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + url: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'url', + }, + } + }, + + errors: { + noSuchApp: { + message: 'No such app.', + code: 'NO_SUCH_APP', + id: '92f93e63-428e-4f2f-a5a4-39e1407fe998' + } + } +}; + +export default define(meta, async (ps) => { + // Lookup app + const app = await Apps.findOne({ + secret: ps.appSecret + }); + + if (app == null) { + throw new ApiError(meta.errors.noSuchApp); + } + + // Generate token + const token = uuid(); + + // Create session token document + const doc = await AuthSessions.save({ + id: genId(), + createdAt: new Date(), + appId: app.id, + token: token + }); + + return { + token: doc.token, + url: `${config.authUrl}/${doc.token}` + }; +}); diff --git a/packages/backend/src/server/api/endpoints/auth/session/show.ts b/packages/backend/src/server/api/endpoints/auth/session/show.ts new file mode 100644 index 0000000000..23f1a56a37 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/auth/session/show.ts @@ -0,0 +1,58 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { ApiError } from '../../../error'; +import { AuthSessions } from '@/models/index'; + +export const meta = { + tags: ['auth'], + + requireCredential: false as const, + + params: { + token: { + validator: $.str, + } + }, + + errors: { + noSuchSession: { + message: 'No such session.', + code: 'NO_SUCH_SESSION', + id: 'bd72c97d-eba7-4adb-a467-f171b8847250' + } + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id' + }, + app: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'App' + }, + token: { + type: 'string' as const, + optional: false as const, nullable: false as const + } + } + } +}; + +export default define(meta, async (ps, user) => { + // Lookup session + const session = await AuthSessions.findOne({ + token: ps.token + }); + + if (session == null) { + throw new ApiError(meta.errors.noSuchSession); + } + + return await AuthSessions.pack(session, user); +}); diff --git a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts new file mode 100644 index 0000000000..72201cb207 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts @@ -0,0 +1,98 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { ApiError } from '../../../error'; +import { Apps, AuthSessions, AccessTokens, Users } from '@/models/index'; + +export const meta = { + tags: ['auth'], + + requireCredential: false as const, + + params: { + appSecret: { + validator: $.str, + }, + + token: { + validator: $.str, + } + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + accessToken: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + + user: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'User', + }, + } + }, + + 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, async (ps) => { + // Lookup app + const app = await Apps.findOne({ + secret: ps.appSecret + }); + + if (app == null) { + throw new ApiError(meta.errors.noSuchApp); + } + + // Fetch token + const session = await AuthSessions.findOne({ + token: ps.token, + appId: app.id + }); + + if (session == null) { + throw new ApiError(meta.errors.noSuchSession); + } + + if (session.userId == null) { + throw new ApiError(meta.errors.pendingSession); + } + + // Lookup access token + const accessToken = await AccessTokens.findOneOrFail({ + appId: app.id, + userId: session.userId + }); + + // Delete session + AuthSessions.delete(session.id); + + return { + accessToken: accessToken.token, + user: await Users.pack(session.userId, null, { + detail: true + }) + }; +}); -- cgit v1.2.3-freya