diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index f4624abf3fcd..d28d60c0f083 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -382,7 +382,7 @@ import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; import * as ep___users_stats from './endpoints/users/stats.js'; -import * as ep___users_get_twofactor_enable from './endpoints/users/get-twofactor-enable.js'; +import * as ep___users_get_security_info from './endpoints/users/get-security-info.js'; import * as ep___users_achievements from './endpoints/users/achievements.js'; import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; import * as ep___fetchRss from './endpoints/fetch-rss.js'; @@ -777,7 +777,7 @@ const $users_searchByUsernameAndHost: Provider = { provide: 'ep:users/search-by- const $users_search: Provider = { provide: 'ep:users/search', useClass: ep___users_search.default }; const $users_show: Provider = { provide: 'ep:users/show', useClass: ep___users_show.default }; const $users_stats: Provider = { provide: 'ep:users/stats', useClass: ep___users_stats.default }; -const $users_twofactor_enable: Provider = { provide: 'ep:users/get-twofactor-enable', useClass: ep___users_get_twofactor_enable.default }; +const $users_twofactor_enable: Provider = { provide: 'ep:users/get-security-info', useClass: ep___users_get_security_info.default }; const $users_achievements: Provider = { provide: 'ep:users/achievements', useClass: ep___users_achievements.default }; const $users_updateMemo: Provider = { provide: 'ep:users/update-memo', useClass: ep___users_updateMemo.default }; const $fetchRss: Provider = { provide: 'ep:fetch-rss', useClass: ep___fetchRss.default }; diff --git a/packages/backend/src/server/api/SigninApiService.ts b/packages/backend/src/server/api/SigninApiService.ts index a1728026bebc..ec1ec567d6db 100644 --- a/packages/backend/src/server/api/SigninApiService.ts +++ b/packages/backend/src/server/api/SigninApiService.ts @@ -122,33 +122,25 @@ export class SigninApiService { return; } - let user: MiLocalUser | null = null; - let profile: MiUserProfile | null = null; // Fetch user - if (username.includes('@')) { - profile = await this.userProfilesRepository.findOneBy({ + const profile = await this.userProfilesRepository.findOne({ + relations: ['user'], + where: username.includes('@') ? { email: username, emailVerified: true, - }) as MiUserProfile; - - user = await this.usersRepository.findOneBy({ - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - id: profile?.userId, - }) as MiLocalUser; - } else { - user = await this.usersRepository.findOneBy({ - usernameLower: username.toLowerCase(), - host: IsNull(), - }) as MiLocalUser; - - if (user !== null) { - profile = await this.userProfilesRepository.findOneByOrFail({ - userId: user.id, - }) as MiUserProfile; + user: { + host: IsNull(), + } + } : { + user: { + usernameLower: username.toLowerCase(), + host: IsNull(), + } } - } + }); + const user = (profile?.user as MiLocalUser) ?? null; - if (user == null || profile == null) { + if (!user || !profile) { logger.error('No such user.'); return error(403, { id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c', diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index e09ea09efece..987228be66b1 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -381,7 +381,7 @@ import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js'; import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js'; import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; -import * as ep___users_get_twofactor_enable from './endpoints/users/get-twofactor-enable.js'; +import * as ep___users_get_security_info from './endpoints/users/get-security-info.js'; import * as ep___users_stats from './endpoints/users/stats.js'; import * as ep___users_achievements from './endpoints/users/achievements.js'; import * as ep___users_updateMemo from './endpoints/users/update-memo.js'; @@ -774,7 +774,7 @@ const eps = [ ['users/search-by-username-and-host', ep___users_searchByUsernameAndHost], ['users/search', ep___users_search], ['users/show', ep___users_show], - ['users/get-twofactor-enable', ep___users_get_twofactor_enable], + ['users/get-security-info', ep___users_get_security_info], ['users/stats', ep___users_stats], ['users/achievements', ep___users_achievements], ['users/update-memo', ep___users_updateMemo], diff --git a/packages/backend/src/server/api/endpoints/users/get-twofactor-enable.ts b/packages/backend/src/server/api/endpoints/users/get-security-info.ts similarity index 57% rename from packages/backend/src/server/api/endpoints/users/get-twofactor-enable.ts rename to packages/backend/src/server/api/endpoints/users/get-security-info.ts index dc7ce920cfbe..1762087ed0c6 100644 --- a/packages/backend/src/server/api/endpoints/users/get-twofactor-enable.ts +++ b/packages/backend/src/server/api/endpoints/users/get-security-info.ts @@ -1,17 +1,20 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - import { Inject, Injectable } from '@nestjs/common'; import type { UserProfilesRepository, UserSecurityKeysRepository } from '@/models/_.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; +import bcrypt from 'bcryptjs'; +import ms from 'ms'; export const meta = { tags: ['users'], requireCredential: false, + + limit: { + duration: ms('1hour'), + max: 30, + }, + res: { type: 'object', properties: { @@ -28,8 +31,9 @@ export const paramDef = { type: 'object', properties: { email: { type: 'string' }, + password: { type: 'string' }, }, - required: ['email'], + required: ['email', 'password'], } as const; @Injectable() @@ -42,22 +46,24 @@ export default class extends Endpoint { // eslint- private userSecurityKeysRepository: UserSecurityKeysRepository, ) { super(meta, paramDef, async (ps, me) => { - const userProfile = await this.userProfilesRepository.findOneBy({ - email: ps.email, - }); - - return userProfile ? { - twoFactorEnabled: userProfile.twoFactorEnabled, - usePasswordLessLogin: userProfile.usePasswordLessLogin, - securityKeys: userProfile.twoFactorEnabled - ? await this.userSecurityKeysRepository.countBy({ userId: userProfile.userId }).then(result => result >= 1) + const profile = await this.userProfilesRepository.findOneBy({ email: ps.email }); + + const passwordMatched = await bcrypt.compare(ps.password, profile?.password ?? ''); + if (!profile || !passwordMatched) { + return { + twoFactorEnabled: false, + usePasswordLessLogin: false, + securityKeys: false, + } + } + + return { + twoFactorEnabled: profile.twoFactorEnabled, + usePasswordLessLogin: profile.usePasswordLessLogin, + securityKeys: profile.twoFactorEnabled + ? await this.userSecurityKeysRepository.countBy({ userId: profile.userId }).then(result => result >= 1) : false, - } : { - twoFactorEnabled: false, - usePasswordLessLogin: false, - securityKeys: false, }; }); } } - diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index 386c0f2d64eb..e4f8b707b546 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -340,9 +340,9 @@ export async function openAccountMenu(opts: { } } -export function getAccountWithSigninDialog(emailMode = false): Promise<{ id: string, token: string } | null> { +export function getAccountWithSigninDialog(): Promise<{ id: string, token: string } | null> { return new Promise((resolve) => { - const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), { emailMode }, { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => { await addAccount(res.id, res.i); resolve({ id: res.id, token: res.i }); diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue index 593ee599ccf9..acae3d4691e4 100644 --- a/packages/frontend/src/components/MkSignin.vue +++ b/packages/frontend/src/components/MkSignin.vue @@ -6,32 +6,30 @@ SPDX-License-Identifier: AGPL-3.0-only