boredgame/src/lib/server/api/services/loginrequest.service.ts
2024-08-14 18:07:50 -07:00

91 lines
No EOL
3.9 KiB
TypeScript

import { inject, injectable } from 'tsyringe';
import { BadRequest } from '../common/errors';
import { DatabaseProvider } from '../providers';
import { MailerService } from './mailer.service';
import { TokensService } from './tokens.service';
import { LuciaProvider } from '../providers/lucia.provider';
import { UsersRepository } from '../repositories/users.repository';
import { CredentialsRepository } from '../repositories/credentials.repository';
import type { HonoRequest } from 'hono';
import type {SigninUsernameDto} from "$lib/dtos/signin-username.dto";
@injectable()
export class LoginRequestsService {
constructor(
@inject(LuciaProvider) private readonly lucia: LuciaProvider,
@inject(DatabaseProvider) private readonly db: DatabaseProvider,
@inject(TokensService) private readonly tokensService: TokensService,
@inject(MailerService) private readonly mailerService: MailerService,
@inject(UsersRepository) private readonly usersRepository: UsersRepository,
@inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository,
) { }
// async create(data: RegisterEmailDto) {
// // generate a token, expiry date, and hash
// const { token, expiry, hashedToken } = await this.tokensService.generateTokenWithExpiryAndHash(15, 'm');
// // save the login request to the database - ensuring we save the hashedToken
// await this.loginRequestsRepository.create({ email: data.email, hashedToken, expiresAt: expiry });
// // send the login request email
// await this.mailerService.sendLoginRequest({
// to: data.email,
// props: { token: token }
// });
// }
async verify(data: SigninUsernameDto, req: HonoRequest) {
const requestIpAddress = req.header('x-real-ip');
const requestIpCountry = req.header('x-vercel-ip-country');
const existingUser = await this.usersRepository.findOneByUsername(data.username);
if (!existingUser) {
throw BadRequest('User not found');
}
const credential = await this.credentialsRepository.findPasswordCredentialsByUserId(existingUser.id);
if (!credential) {
throw BadRequest('Invalid credentials');
}
if (!await this.tokensService.verifyHashedToken(credential.secret_data, data.password)) {
throw BadRequest('Invalid credentials');
}
const totpCredentials = await this.credentialsRepository.findTOTPCredentialsByUserId(existingUser.id);
return this.lucia.createSession(existingUser.id, {
ip_country: requestIpCountry || 'unknown',
ip_address: requestIpAddress || 'unknown',
twoFactorAuthEnabled:
!!totpCredentials &&
totpCredentials?.secret_data !== null &&
totpCredentials?.secret_data !== '',
isTwoFactorAuthenticated: false,
});
}
// Create a new user and send a welcome email - or other onboarding process
private async handleNewUserRegistration(email: string) {
const newUser = await this.usersRepository.create({ email, verified: true })
this.mailerService.sendWelcome({ to: email, props: null });
// TODO: add whatever onboarding process or extra data you need here
return newUser
}
// Fetch a valid request from the database, verify the token and burn the request if it is valid
// private async fetchValidRequest(email: string, token: string) {
// return await this.db.transaction(async (trx) => {
// // fetch the login request
// const loginRequest = await this.loginRequestsRepository.trxHost(trx).findOneByEmail(email)
// if (!loginRequest) return null;
// // check if the token is valid
// const isValidRequest = await this.tokensService.verifyHashedToken(loginRequest.hashedToken, token);
// if (!isValidRequest) return null
// // if the token is valid, burn the request
// await this.loginRequestsRepository.trxHost(trx).deleteById(loginRequest.id);
// return loginRequest
// })
// }
}