/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '../../../error.js'; export const meta = { requireCredential: true, secure: true, errors: { noKey: { message: 'No security key.', code: 'NO_SECURITY_KEY', id: 'f9c54d7f-d4c2-4d3c-9a8g-a70daac86512', }, }, limit: { duration: ms('1hour'), max: 10, minInterval: ms('1sec'), }, } as const; export const paramDef = { type: 'object', properties: { value: { type: 'boolean' }, }, required: ['value'], } as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( @Inject(DI.userProfilesRepository) private userProfilesRepository: UserProfilesRepository, @Inject(DI.userSecurityKeysRepository) private userSecurityKeysRepository: UserSecurityKeysRepository, private userEntityService: UserEntityService, private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { if (ps.value === true) { // セキュリティキーがなければパスワードレスを有効にはできない const keyCount = await this.userSecurityKeysRepository.count({ where: { userId: me.id, }, select: { id: true, name: true, lastUsed: true, }, }); if (keyCount === 0) { await this.userProfilesRepository.update(me.id, { usePasswordLessLogin: false, }); throw new ApiError(meta.errors.noKey); } } await this.userProfilesRepository.update(me.id, { usePasswordLessLogin: ps.value, }); // Publish meUpdated event this.globalEventService.publishMainStream(me.id, 'meUpdated', await this.userEntityService.pack(me.id, me, { schema: 'MeDetailed', includeSecrets: true, })); }); } }