mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-21 17:37:29 -07:00
[backend/web-api] Move auth code into handler
This commit is contained in:
parent
ba76c5e67b
commit
a168e4ec03
2 changed files with 48 additions and 34 deletions
|
@ -1,16 +1,10 @@
|
|||
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";
|
||||
import { AuthHandler } from "@/server/api/web/handlers/auth.js";
|
||||
|
||||
@Controller('/auth')
|
||||
export class AuthController {
|
||||
|
@ -19,37 +13,12 @@ export class AuthController {
|
|||
@CurrentUser() me: ILocalUser | null,
|
||||
@CurrentSession() session: Session | null,
|
||||
): Promise<AuthResponse> {
|
||||
const user = me ? await UserHandler.getUser(me, me.id) : null;
|
||||
return {
|
||||
status: !user ? 'guest' : session?.active ? 'authenticated' : '2fa',
|
||||
token: session?.token ?? null,
|
||||
user: user,
|
||||
};
|
||||
return AuthHandler.getAuthStatus(me, session);
|
||||
}
|
||||
|
||||
@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("Missing username or password");
|
||||
|
||||
const user = await Users.findOneBy({ usernameLower: request.username.toLowerCase(), host: IsNull() });
|
||||
if (!user) throw unauthorized("Invalid username or password");
|
||||
|
||||
const profile = await UserProfiles.findOneBy( { userId: user.id });
|
||||
if (!profile || profile.password == null) throw unauthorized("Invalid username or password");
|
||||
|
||||
if (!await comparePassword(request.password, profile.password)) throw unauthorized("Invalid username or password");
|
||||
|
||||
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.getAuthStatus(user as ILocalUser, session);
|
||||
return AuthHandler.login(request);
|
||||
}
|
||||
}
|
||||
|
|
45
packages/backend/src/server/api/web/handlers/auth.ts
Normal file
45
packages/backend/src/server/api/web/handlers/auth.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { ILocalUser } from "@/models/entities/user.js";
|
||||
import { Session } from "@/models/entities/session.js";
|
||||
import { AuthRequest, AuthResponse } from "@/server/api/web/entities/auth.js";
|
||||
import { UserHandler } from "@/server/api/web/handlers/user.js";
|
||||
import { Sessions, UserProfiles, Users } from "@/models/index.js";
|
||||
import { comparePassword } from "@/misc/password.js";
|
||||
import { genId } from "@/misc/gen-id.js";
|
||||
import { secureRndstr } from "@/misc/secure-rndstr.js";
|
||||
import { unauthorized, badRequest } from "@hapi/boom";
|
||||
import { IsNull } from "typeorm";
|
||||
|
||||
export class AuthHandler {
|
||||
public static async getAuthStatus(me: ILocalUser | null, session: Session | null): Promise<AuthResponse> {
|
||||
const user = me ? await UserHandler.getUser(me, me.id) : null;
|
||||
return {
|
||||
status: !user ? 'guest' : session?.active ? 'authenticated' : '2fa',
|
||||
token: session?.token ?? null,
|
||||
user: user,
|
||||
};
|
||||
}
|
||||
|
||||
public static async login(request: AuthRequest): Promise<AuthResponse> {
|
||||
if (request.username == null || request.password == null) throw badRequest("Missing username or password");
|
||||
|
||||
const user = await Users.findOneBy({ usernameLower: request.username.toLowerCase(), host: IsNull() });
|
||||
if (!user) throw unauthorized("Invalid username or password");
|
||||
|
||||
const profile = await UserProfiles.findOneBy( { userId: user.id });
|
||||
if (!profile || profile.password == null) throw unauthorized("Invalid username or password");
|
||||
|
||||
if (!await comparePassword(request.password, profile.password)) throw unauthorized("Invalid username or password");
|
||||
|
||||
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.getAuthStatus(user as ILocalUser, session);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue