48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import { BcryptCrypto, Crypto } from "./crypto.ts";
|
|
import { Database } from "./database.ts";
|
|
import { Err, Ok, Result } from "./utils.ts";
|
|
|
|
export type LoginReq = {
|
|
username: string;
|
|
password: string;
|
|
};
|
|
|
|
export type LoginRes = {
|
|
sessionId: number;
|
|
};
|
|
|
|
export type LoginError =
|
|
| "internal"
|
|
| "wrong username/password"
|
|
| "account banned";
|
|
|
|
export class Sessions {
|
|
public constructor(
|
|
private db: Database,
|
|
private crypto: Crypto = new BcryptCrypto(),
|
|
) {}
|
|
|
|
public async login(req: LoginReq): Promise<Result<LoginRes, LoginError>> {
|
|
const findUserResult = await this.db.userWithUsername(req.username);
|
|
if (!findUserResult.ok) {
|
|
return Err("internal");
|
|
}
|
|
if (!findUserResult.value.some) {
|
|
return Err("wrong username/password");
|
|
}
|
|
const user = findUserResult.value.value;
|
|
if (!await this.crypto.compare(req.password, user.passwordHash)) {
|
|
return Err("wrong username/password");
|
|
}
|
|
const session = await this.db.createSession({
|
|
userId: user.id,
|
|
});
|
|
if (!session.ok) {
|
|
return Err("internal");
|
|
}
|
|
return Ok({
|
|
sessionId: session.value.id,
|
|
});
|
|
}
|
|
}
|