TofuStack/src/lib/server/api/services/iam.service.ts

95 lines
2.9 KiB
TypeScript
Raw Normal View History

2024-05-25 06:02:26 +00:00
import { inject, injectable } from 'tsyringe';
import type { RegisterEmailDto } from '../dtos/register-email.dto';
import { UsersRepository } from '../repositories/users.repository';
import { MailerService } from './mailer.service';
import { TokensService } from './tokens.service';
import type { SignInEmailDto } from '../dtos/signin-email.dto';
import { BadRequest } from '../common/errors';
import { LuciaProvider } from '../providers/lucia.provider';
import type { UpdateEmailDto } from '../dtos/update-email.dto';
import type { VerifyEmailDto } from '../dtos/verify-email.dto';
@injectable()
export class IamService {
constructor(
@inject(UsersRepository) private usersRepository: UsersRepository,
@inject(TokensService) private tokensService: TokensService,
@inject(MailerService) private mailerService: MailerService,
@inject(LuciaProvider) private lucia: LuciaProvider
) {}
async registerEmail(data: RegisterEmailDto) {
const existingUser = await this.usersRepository.findOneByEmail(data.email);
if (!existingUser) {
const newUser = await this.usersRepository.create({ email: data.email, verified: false });
return this.createValidationReuqest(newUser.id, newUser.email);
}
return this.createValidationReuqest(existingUser.id, existingUser.email);
}
async signinEmail(data: SignInEmailDto) {
const user = await this.usersRepository.findOneByEmail(data.email);
if (!user) {
throw BadRequest('Bad credentials');
}
const isValidToken = await this.tokensService.validateToken(user.id, data.token);
if (!isValidToken) {
throw BadRequest('Bad credentials');
}
// if this is a new unverified user, send a welcome email and update the user
if (!user.verified) {
await this.usersRepository.update(user.id, { verified: true });
await this.mailerService.send({
to: user.email,
subject: 'Welcome!',
html: 'Welcome to example.com'
});
}
return this.lucia.createSession(user.id, {});
}
async verifyEmail(userId: string, token: string) {
const user = await this.usersRepository.findOneById(userId);
if (!user) {
throw BadRequest('User not found');
}
const validToken = await this.tokensService.validateToken(user.id, token);
if (!validToken) {
throw BadRequest('Invalid token');
}
await this.usersRepository.update(user.id, { email: validToken.email });
}
async updateEmail(userId: string, data: UpdateEmailDto) {
return this.createValidationReuqest(userId, data.email);
}
async logout(sessionId: string) {
return this.lucia.invalidateSession(sessionId);
}
private async createValidationReuqest(userId: string, email: string) {
const validationToken = await this.tokensService.create(userId, email);
await this.mailerService.sendEmailVerification({
to: email,
props: { token: validationToken.token }
});
// return await this.mailerService.send({
// to: email,
// subject: 'Verify your email',
// html: `Your token is ${validationToken.token}`
// });
}
}