import { Controller, Get, Post, Body, CurrentUser, Flow } from "@iceshrimp/koa-openapi"; import type { ILocalUser } from "@/models/entities/user.js"; import { UserHandler } from "@/server/api/web/handlers/user.js"; import type { AuthRequest, AuthResponse } from "@/server/api/web/entities/auth.js"; import type { Session } from "@/models/entities/session.js"; import { RatelimitRouteMiddleware } from "@/server/api/web/middleware/rate-limit.js"; import { CurrentSession } from "@/server/api/web/misc/decorators.js"; import { Sessions, UserProfiles, Users } from "@/models/index.js"; import { unauthorized, badRequest } from "@hapi/boom"; import { comparePassword } from "@/misc/password.js"; import { IsNull } from "typeorm"; import { genId } from "@/misc/gen-id.js"; import { secureRndstr } from "@/misc/secure-rndstr.js"; @Controller('/auth') export class AuthController { @Get('/') async getAuth( @CurrentUser() me: ILocalUser | null, @CurrentSession() session: Session | null, ): Promise<AuthResponse> { const user = me ? await UserHandler.getUser(me, me.id) : null; return { authenticated: !!session?.active, status: user && session?.active ? null : '2fa', token: session?.token ?? null, user: user, }; } @Post('/') @Flow([RatelimitRouteMiddleware("auth", 10, 60000, true)]) async login(@Body({ required: true }) request: AuthRequest): Promise<AuthResponse> { if (request.username == null || request.password == null) throw badRequest(); const user = await Users.findOneBy({ usernameLower: request.username.toLowerCase(), host: IsNull() }); if (!user) throw unauthorized(); const profile = await UserProfiles.findOneBy( { userId: user.id }); if (!profile || profile.password == null) throw unauthorized(); if (!await comparePassword(request.password, profile.password)) throw unauthorized(); const result = await Sessions.insert({ id: genId(), createdAt: new Date(), active: !profile.twoFactorEnabled, userId: user.id, token: secureRndstr(32), }); const session = await Sessions.findOneByOrFail(result.identifiers[0]); return this.getAuth(user as ILocalUser, session); } }