diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c01aff076..0d4c5950dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ --> +## 13.x.x (unreleased) + +### General +- プレイにAPI Tokenを要求できる関数を追加 + ## 13.14.1 ### General diff --git a/locales/index.d.ts b/locales/index.d.ts index db7e3e95756..42433c5a47a 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1074,6 +1074,9 @@ export interface Locale { "additionalEmojiDictionary": string; "installed": string; "branding": string; + "additionalPermissionsForFlash": string; + "thisFlashRequiresTheFollowingPermissions": string; + "doYouWantToAllowThisPlayToAccessYourAccount": string; "enableServerMachineStats": string; "enableIdenticonGeneration": string; "turnOffToImprovePerformance": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b2fa9c337e2..c7faabf29fc 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1071,6 +1071,9 @@ goToMisskey: "Misskeyへ" additionalEmojiDictionary: "絵文字の追加辞書" installed: "インストール済み" branding: "ブランディング" +additionalPermissionsForFlash: "Playへの追加許可" +thisFlashRequiresTheFollowingPermissions: "このPlayは以下の権限を要求しています" +doYouWantToAllowThisPlayToAccessYourAccount: "このPlayによるアカウントへのアクセスを許可しますか?" enableServerMachineStats: "サーバーのマシン情報を公開する" enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にする" turnOffToImprovePerformance: "オフにするとパフォーマンスが向上します。" diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts index cd6b68e721d..0b841370a51 100644 --- a/packages/backend/src/core/CacheService.ts +++ b/packages/backend/src/core/CacheService.ts @@ -7,6 +7,7 @@ import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; import { StreamMessages } from '@/server/api/stream/types.js'; +import type { FlashToken } from '@/misc/flash-token.js'; import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() @@ -16,6 +17,7 @@ export class CacheService implements OnApplicationShutdown { public localUserByIdCache: MemoryKVCache; public uriPersonCache: MemoryKVCache; public userProfileCache: RedisKVCache; + public flashAccessTokensCache: RedisKVCache; public userMutingsCache: RedisKVCache>; public userBlockingCache: RedisKVCache>; public userBlockedCache: RedisKVCache>; // NOTE: 「被」Blockキャッシュ @@ -147,6 +149,13 @@ export class CacheService implements OnApplicationShutdown { fromRedisConverter: (value) => new Set(JSON.parse(value)), }); + this.flashAccessTokensCache = new RedisKVCache(this.redisClient, 'flashAccessTokens', { + lifetime: 1000 * 60 * 30, // 30m + memoryCacheLifetime: 1000 * 60, // 1m + fetcher: async (key) => null, + toRedisConverter: (value) => JSON.stringify(value), + fromRedisConverter: (value) => JSON.parse(value), + }); this.redisForSub.on('message', this.onMessage); } diff --git a/packages/backend/src/misc/flash-token.ts b/packages/backend/src/misc/flash-token.ts new file mode 100644 index 00000000000..2622f955dfc --- /dev/null +++ b/packages/backend/src/misc/flash-token.ts @@ -0,0 +1,6 @@ +import type { LocalUser } from '@/models/entities/User.js'; + +export type FlashToken = { + permissions: string[]; + user: LocalUser +}; diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index c4c02e7afeb..516f4b38f8b 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -20,6 +20,7 @@ import { AuthenticateService, AuthenticationError } from './AuthenticateService. import type { FastifyRequest, FastifyReply } from 'fastify'; import type { OnApplicationShutdown } from '@nestjs/common'; import type { IEndpointMeta, IEndpoint } from './endpoints.js'; +import type { FlashToken } from '@/misc/flash-token.js'; const pump = promisify(pipeline); @@ -104,8 +105,8 @@ export class ApiCallService implements OnApplicationShutdown { reply.code(400); return; } - this.authenticateService.authenticate(token).then(([user, app]) => { - this.call(endpoint, user, app, body, null, request).then((res) => { + this.authenticateService.authenticate(token).then(([user, app, flashToken]) => { + this.call(endpoint, user, app, flashToken, body, null, request).then((res) => { if (request.method === 'GET' && endpoint.meta.cacheSec && !token && !user) { reply.header('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`); } @@ -153,8 +154,8 @@ export class ApiCallService implements OnApplicationShutdown { reply.code(400); return; } - this.authenticateService.authenticate(token).then(([user, app]) => { - this.call(endpoint, user, app, fields, { + this.authenticateService.authenticate(token).then(([user, app, flashToken]) => { + this.call(endpoint, user, app, flashToken, fields, { name: multipartData.filename, path: path, }, request).then((res) => { @@ -222,6 +223,7 @@ export class ApiCallService implements OnApplicationShutdown { ep: IEndpoint & { exec: any }, user: LocalUser | null | undefined, token: AccessToken | null | undefined, + flashToken: FlashToken | null | undefined, data: any, file: { name: string; @@ -229,7 +231,7 @@ export class ApiCallService implements OnApplicationShutdown { } | null, request: FastifyRequest<{ Body: Record | undefined, Querystring: Record }>, ) { - const isSecure = user != null && token == null; + const isSecure = user != null && token == null && flashToken == null; if (ep.meta.secure && !isSecure) { throw new ApiError(accessDenied); @@ -336,6 +338,14 @@ export class ApiCallService implements OnApplicationShutdown { }); } + if (flashToken && ep.meta.kind && !flashToken.permissions.some(p => p === ep.meta.kind)) { + throw new ApiError({ + message: 'Your flash does not have the necessary permissions to use this endpoint.', + code: 'PERMISSION_DENIED', + id: '11924d17-113a-4ab0-954a-c567ee8a6ce5', + }); + } + // Cast non JSON input if ((ep.meta.requireFile || request.method === 'GET') && ep.params.properties) { for (const k of Object.keys(ep.params.properties)) { @@ -358,7 +368,7 @@ export class ApiCallService implements OnApplicationShutdown { } // API invoking - return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => { + return await ep.exec(data, user, token, flashToken, file, request.ip, request.headers).catch((err: Error) => { if (err instanceof ApiError || err instanceof AuthenticationError) { throw err; } else { diff --git a/packages/backend/src/server/api/AuthenticateService.ts b/packages/backend/src/server/api/AuthenticateService.ts index 8b0fff80d91..84bca387944 100644 --- a/packages/backend/src/server/api/AuthenticateService.ts +++ b/packages/backend/src/server/api/AuthenticateService.ts @@ -8,6 +8,7 @@ import type { App } from '@/models/entities/App.js'; import { CacheService } from '@/core/CacheService.js'; import isNativeToken from '@/misc/is-native-token.js'; import { bindThis } from '@/decorators.js'; +import type { FlashToken } from '@/misc/flash-token.js'; export class AuthenticationError extends Error { constructor(message: string) { @@ -36,9 +37,9 @@ export class AuthenticateService implements OnApplicationShutdown { } @bindThis - public async authenticate(token: string | null | undefined): Promise<[LocalUser | null, AccessToken | null]> { + public async authenticate(token: string | null | undefined): Promise<[LocalUser | null, AccessToken | null, FlashToken | null]> { if (token == null) { - return [null, null]; + return [null, null, null]; } if (isNativeToken(token)) { @@ -49,7 +50,7 @@ export class AuthenticateService implements OnApplicationShutdown { throw new AuthenticationError('user not found'); } - return [user, null]; + return [user, null, null]; } else { const accessToken = await this.accessTokensRepository.findOne({ where: [{ @@ -60,7 +61,12 @@ export class AuthenticateService implements OnApplicationShutdown { }); if (accessToken == null) { - throw new AuthenticationError('invalid signature'); + const flashToken = await this.cacheService.flashAccessTokensCache.get(token); + if (flashToken !== null && typeof flashToken !== 'undefined') { + return [flashToken.user, null, flashToken]; + } else { + throw new AuthenticationError('invalid signature'); + } } this.accessTokensRepository.update(accessToken.id, { @@ -79,9 +85,9 @@ export class AuthenticateService implements OnApplicationShutdown { return [user, { id: accessToken.id, permission: app.permission, - } as AccessToken]; + } as AccessToken, null]; } else { - return [user, accessToken]; + return [user, accessToken, null]; } } } diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 4e6bc46e677..33ed88f2424 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -289,6 +289,7 @@ import * as ep___pages_update from './endpoints/pages/update.js'; import * as ep___flash_create from './endpoints/flash/create.js'; import * as ep___flash_delete from './endpoints/flash/delete.js'; import * as ep___flash_featured from './endpoints/flash/featured.js'; +import * as ep___flash_genToken from './endpoints/flash/gen-token.js'; import * as ep___flash_like from './endpoints/flash/like.js'; import * as ep___flash_show from './endpoints/flash/show.js'; import * as ep___flash_unlike from './endpoints/flash/unlike.js'; @@ -634,6 +635,7 @@ const $pages_update: Provider = { provide: 'ep:pages/update', useClass: ep___pag const $flash_create: Provider = { provide: 'ep:flash/create', useClass: ep___flash_create.default }; const $flash_delete: Provider = { provide: 'ep:flash/delete', useClass: ep___flash_delete.default }; const $flash_featured: Provider = { provide: 'ep:flash/featured', useClass: ep___flash_featured.default }; +const $flash_genToken: Provider = { provide: 'ep:flash/gen-token', useClass: ep___flash_genToken.default }; const $flash_like: Provider = { provide: 'ep:flash/like', useClass: ep___flash_like.default }; const $flash_show: Provider = { provide: 'ep:flash/show', useClass: ep___flash_show.default }; const $flash_unlike: Provider = { provide: 'ep:flash/unlike', useClass: ep___flash_unlike.default }; @@ -983,6 +985,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $flash_create, $flash_delete, $flash_featured, + $flash_genToken, $flash_like, $flash_show, $flash_unlike, @@ -1326,6 +1329,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $flash_create, $flash_delete, $flash_featured, + $flash_genToken, $flash_like, $flash_show, $flash_unlike, diff --git a/packages/backend/src/server/api/endpoint-base.ts b/packages/backend/src/server/api/endpoint-base.ts index 364fa7a19b9..3a95a048422 100644 --- a/packages/backend/src/server/api/endpoint-base.ts +++ b/packages/backend/src/server/api/endpoint-base.ts @@ -3,6 +3,7 @@ import _Ajv from 'ajv'; import type { Schema, SchemaType } from '@/misc/json-schema.js'; import type { LocalUser } from '@/models/entities/User.js'; import type { AccessToken } from '@/models/entities/AccessToken.js'; +import type { FlashToken } from '@/misc/flash-token.js'; import { ApiError } from './error.js'; import type { IEndpointMeta } from './endpoints.js'; @@ -23,16 +24,16 @@ type File = { // TODO: paramsの型をT['params']のスキーマ定義から推論する type Executor = - (params: SchemaType, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => + (params: SchemaType, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, flashToken: FlashToken | null, file?: File, cleanup?: () => any, ip?: string | null, headers?: Record | null) => Promise>>; export abstract class Endpoint { - public exec: (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; + public exec: (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, flashToken: FlashToken | null, file?: File, ip?: string | null, headers?: Record | null) => Promise; constructor(meta: T, paramDef: Ps, cb: Executor) { const validate = ajv.compile(paramDef); - this.exec = (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, file?: File, ip?: string | null, headers?: Record | null) => { + this.exec = (params: any, user: T['requireCredential'] extends true ? LocalUser : LocalUser | null, token: AccessToken | null, flashToken: FlashToken | null, file?: File, ip?: string | null, headers?: Record | null) => { let cleanup: undefined | (() => void) = undefined; if (meta.requireFile) { @@ -63,7 +64,7 @@ export abstract class Endpoint { return Promise.reject(err); } - return cb(params as SchemaType, user, token, file, cleanup, ip, headers); + return cb(params as SchemaType, user, token, flashToken, file, cleanup, ip, headers); }; } } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 41c3a29eec0..bb48dd642a4 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -289,6 +289,7 @@ import * as ep___pages_update from './endpoints/pages/update.js'; import * as ep___flash_create from './endpoints/flash/create.js'; import * as ep___flash_delete from './endpoints/flash/delete.js'; import * as ep___flash_featured from './endpoints/flash/featured.js'; +import * as ep___flash_genToken from './endpoints/flash/gen-token.js'; import * as ep___flash_like from './endpoints/flash/like.js'; import * as ep___flash_show from './endpoints/flash/show.js'; import * as ep___flash_unlike from './endpoints/flash/unlike.js'; @@ -632,6 +633,7 @@ const eps = [ ['flash/create', ep___flash_create], ['flash/delete', ep___flash_delete], ['flash/featured', ep___flash_featured], + ['flash/gen-token', ep___flash_genToken], ['flash/like', ep___flash_like], ['flash/show', ep___flash_show], ['flash/unlike', ep___flash_unlike], diff --git a/packages/backend/src/server/api/endpoints/app/show.ts b/packages/backend/src/server/api/endpoints/app/show.ts index eaafa8dc1b0..52e9c02aba7 100644 --- a/packages/backend/src/server/api/endpoints/app/show.ts +++ b/packages/backend/src/server/api/endpoints/app/show.ts @@ -40,8 +40,8 @@ export default class extends Endpoint { private appEntityService: AppEntityService, ) { - super(meta, paramDef, async (ps, user, token) => { - const isSecure = user != null && token == null; + super(meta, paramDef, async (ps, user, token, flashToken) => { + const isSecure = user != null && token == null && flashToken == null; // Lookup app const ap = await this.appsRepository.findOneBy({ id: ps.appId }); diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index a1c1f9325ec..e128e80944a 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -78,7 +78,7 @@ export default class extends Endpoint { private metaService: MetaService, private driveService: DriveService, ) { - super(meta, paramDef, async (ps, me, _, file, cleanup, ip, headers) => { + super(meta, paramDef, async (ps, me, _1, _2, file, cleanup, ip, headers) => { // Get 'name' parameter let name = ps.name ?? file!.name ?? null; if (name != null) { diff --git a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts index c835587c4aa..4edc4cdc9fe 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts @@ -48,7 +48,7 @@ export default class extends Endpoint { private driveService: DriveService, private globalEventService: GlobalEventService, ) { - super(meta, paramDef, async (ps, user, _1, _2, _3, ip, headers) => { + super(meta, paramDef, async (ps, user, _1, _2, _3, _4, ip, headers) => { this.driveService.uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment, requestIp: ip, requestHeaders: headers }).then(file => { this.driveFileEntityService.pack(file, { self: true }).then(packedFile => { this.globalEventService.publishMainStream(user.id, 'urlUploadFinished', { diff --git a/packages/backend/src/server/api/endpoints/flash/gen-token.ts b/packages/backend/src/server/api/endpoints/flash/gen-token.ts new file mode 100644 index 00000000000..b0ef81ddc25 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/flash/gen-token.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@nestjs/common'; +import ms from 'ms'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { CacheService } from '@/core/CacheService.js'; + +export const meta = { + tags: ['flash'], + + requireCredential: true, + + prohibitMoved: true, + + secure: true, + + limit: { + duration: ms('1hour'), + max: 30, + }, + + res: { + type: 'object', + optional: false, nullable: false, + properties: { + token: { type: 'string' }, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + permissions: { type: 'array', items: { + type: 'string', + } }, + }, + required: ['permissions'], +} as const; + +@Injectable() // eslint-disable-next-line import/no-default-export +export default class extends Endpoint { + constructor ( + private cacheService: CacheService, + ) { + super(meta, paramDef, async (ps, me) => { + const token = secureRndstr(32); + await this.cacheService.flashAccessTokensCache.set(token, { + user: me, + permissions: ps.permissions, + }); + return { + token, + }; + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/i.ts b/packages/backend/src/server/api/endpoints/i.ts index 4d593542db6..cdc72e3368f 100644 --- a/packages/backend/src/server/api/endpoints/i.ts +++ b/packages/backend/src/server/api/endpoints/i.ts @@ -44,8 +44,8 @@ export default class extends Endpoint { private userEntityService: UserEntityService, ) { - super(meta, paramDef, async (ps, user, token) => { - const isSecure = token == null; + super(meta, paramDef, async (ps, user, token, flashToken) => { + const isSecure = token == null && flashToken == null; const now = new Date(); const today = `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()}`; diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 8f5e6177c28..5f4bc8cf3f9 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -194,9 +194,9 @@ export default class extends Endpoint { private roleService: RoleService, private cacheService: CacheService, ) { - super(meta, paramDef, async (ps, _user, token) => { + super(meta, paramDef, async (ps, _user, token, flashToken) => { const user = await this.usersRepository.findOneByOrFail({ id: _user.id }); - const isSecure = token == null; + const isSecure = token == null && flashToken == null; const updates = {} as Partial; const profileUpdates = {} as Partial; diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 8e25af64fec..9f6486048df 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -87,7 +87,7 @@ export default class extends Endpoint { private perUserPvChart: PerUserPvChart, private apiLoggerService: ApiLoggerService, ) { - super(meta, paramDef, async (ps, me, _1, _2, _3, ip) => { + super(meta, paramDef, async (ps, me, _1, _2, _3, _4, ip) => { let user; const isModerator = await this.roleService.isModerator(me); diff --git a/packages/frontend/src/components/MkFlashRequestTokenDialog.vue b/packages/frontend/src/components/MkFlashRequestTokenDialog.vue new file mode 100644 index 00000000000..9f65f211685 --- /dev/null +++ b/packages/frontend/src/components/MkFlashRequestTokenDialog.vue @@ -0,0 +1,58 @@ + + + diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts index f9d04f7950a..8d7b9c876e6 100644 --- a/packages/frontend/src/local-storage.ts +++ b/packages/frontend/src/local-storage.ts @@ -29,6 +29,7 @@ type Keys = `ui:folder:${string}` | `themes:${string}` | `aiscript:${string}` | + `aiscriptSecure:${string}` | 'lastEmojisFetchedAt' | // DEPRECATED, stored in indexeddb (13.9.0~) 'emojis' // DEPRECATED, stored in indexeddb (13.9.0~); diff --git a/packages/frontend/src/scripts/aiscript/api.ts b/packages/frontend/src/scripts/aiscript/api.ts index 5453fe827db..f394f14963c 100644 --- a/packages/frontend/src/scripts/aiscript/api.ts +++ b/packages/frontend/src/scripts/aiscript/api.ts @@ -1,4 +1,6 @@ import { utils, values } from '@syuilo/aiscript'; +import { defineAsyncComponent } from 'vue'; +import { permissions as MkPermissions } from 'misskey-js'; import * as os from '@/os'; import { $i } from '@/account'; import { miLocalStorage } from '@/local-storage'; @@ -6,6 +8,10 @@ import { customEmojis } from '@/custom-emojis'; export function createAiScriptEnv(opts) { let apiRequests = 0; + const table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + const randomString = Array.from(crypto.getRandomValues(new Uint32Array(32))) + .map(v => table[v % table.length]) + .join(''); return { USER_ID: $i ? values.STR($i.id) : values.NULL, USER_NAME: $i ? values.STR($i.name) : values.NULL, @@ -36,7 +42,7 @@ export function createAiScriptEnv(opts) { } apiRequests++; if (apiRequests > 16) return values.NULL; - const res = await os.api(ep.value, utils.valToJs(param), token ? token.value : (opts.token ?? null)); + const res = await os.api(ep.value, utils.valToJs(param), token ? token.value : miLocalStorage.getItem(`aiscriptSecure:${opts.storageKey}:${randomString}:accessToken`) ?? (opts.token ?? null)); return utils.jsToVal(res); }), 'Mk:save': values.FN_NATIVE(([key, value]) => { @@ -48,5 +54,32 @@ export function createAiScriptEnv(opts) { utils.assertString(key); return utils.jsToVal(JSON.parse(miLocalStorage.getItem(`aiscript:${opts.storageKey}:${key.value}`))); }), + 'Mk:requestToken': values.FN_NATIVE(async ([value]) => { + utils.assertArray(value); + const permissions = (utils.valToJs(value) as unknown[]).map(val => { + if (typeof val !== 'string') { + throw new Error(`Invalid type. expected string but got ${typeof val}`); + } + return val; + }).filter(val => MkPermissions.includes(val)); + return await new Promise(async (resolve: any) => { + await os.popup(defineAsyncComponent(() => import('@/components/MkFlashRequestTokenDialog.vue')), { + permissions, + }, { + accept: () => { + os.api('flash/gen-token', { + permissions, + }).then(res => { + miLocalStorage.setItem(`aiscriptSecure:${opts.storageKey}:${randomString}:accessToken`, res!.token); + resolve(values.TRUE); + }); + }, + cancel: () => resolve(values.FALSE), + closed: () => { + resolve(values.FALSE); + }, + }, 'closed'); + }); + }), }; } diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 65d6e2e0b1f..fc7aea5459d 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1562,6 +1562,10 @@ export type Endpoints = { req: TODO; res: TODO; }; + 'flash/gen-token': { + req: TODO; + res: TODO; + }; 'invite/create': { req: NoParams; res: Invite; @@ -2810,7 +2814,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u // // src/api.types.ts:16:32 - (ae-forgotten-export) The symbol "TODO" needs to be exported by the entry point index.d.ts // src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts -// src/api.types.ts:629:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts +// src/api.types.ts:632:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts index 343977f4be3..3ef52eac822 100644 --- a/packages/misskey-js/src/api.types.ts +++ b/packages/misskey-js/src/api.types.ts @@ -443,6 +443,9 @@ export type Endpoints = { 'i/2fa/remove-key': { req: TODO; res: TODO; }; 'i/2fa/unregister': { req: TODO; res: TODO; }; + // flash + 'flash/gen-token': { req: TODO; res: TODO; }; + // invite 'invite/create': { req: NoParams; res: Invite; }; 'invite/delete': { req: { inviteId: Invite['id']; }; res: null; };