79 lines
2.9 KiB
TypeScript

import { Inject, Injectable } from "@nestjs/common";
import { AccountService } from "./account.service";
import * as tokenService from "../contracts/services/token.service";
import * as passwordService from "../contracts/services/password.service";
import * as sessionService from "../contracts/services/session.service";
import { ISignIn } from "../contracts/models/sign.in";
@Injectable()
export class LoginService {
constructor(
@Inject("@apihub24/token_service")
private readonly tokenService: tokenService.ITokenService,
@Inject("@apihub24/password_service")
private readonly passwordService: passwordService.IPasswordService,
@Inject("@apihub24/session_service")
private readonly sessionService: sessionService.ISessionService,
@Inject(AccountService)
private readonly accountService: AccountService
) {}
/**
* This asynchronous method authenticates a user and creates a JWT token for a new session.
* It first finds an active account with the given `accountName`, verifies the password, and if successful, creates a new session and generates a signed token.
* @param signIn An `ISignIn` object containing the `accountName` and `password`.
* @param expires An optional string specifying the token's expiration duration (default: "1h").
* @param algorithm An optional string specifying the signing algorithm for the token (default: "HS512").
* @returns A Promise that resolves to a JWT token string. Returns an empty string if authentication fails.
*/
async signIn(
signIn: ISignIn,
expires: string = "1h",
algorithm: tokenService.Algorithm = "HS512"
): Promise<string> {
const accounts = await this.accountService.getBy(
(x) =>
x.accountName === signIn.accountName &&
x.active &&
!!x.passwordHash?.length
);
if (
!accounts.length ||
!(await this.passwordService.verify(
signIn.password,
accounts[0].passwordHash
))
) {
return "";
}
const session = await this.sessionService.create(accounts[0]);
const token = await this.tokenService.generate(
session,
signIn.accountName,
expires,
algorithm
);
return token;
}
/**
* This asynchronous method logs a user out by removing their active session.
* It finds the account by its `id` and then locates and removes the corresponding session.
* @param accountId The unique identifier (`id`) of the account to be logged out.
* @returns A Promise that resolves to `void` after the operation is complete.
*/
async signOut(accountId: string): Promise<void> {
const accounts = await this.accountService.getBy((x) => x.id === accountId);
if (!accounts.length) {
return;
}
const sessions = await this.sessionService.getBy(
(x) => x.id === accounts[0].id
);
if (!sessions.length) {
return;
}
await this.sessionService.remove(sessions[0].id);
}
}