mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
149 lines
5.1 KiB
TypeScript
149 lines
5.1 KiB
TypeScript
import type { SignupUsernameEmailDto } from '$lib/server/api/dtos/signup-username-email.dto'
|
|
import { CredentialsRepository } from '$lib/server/api/repositories/credentials.repository'
|
|
import { FederatedIdentityRepository } from '$lib/server/api/repositories/federated_identity.repository'
|
|
import { WishlistsRepository } from '$lib/server/api/repositories/wishlists.repository'
|
|
import { TokensService } from '$lib/server/api/services/tokens.service'
|
|
import { UserRolesService } from '$lib/server/api/services/user_roles.service'
|
|
import { inject, injectable } from 'tsyringe'
|
|
import {CredentialsType, RoleName} from '../databases/tables'
|
|
import { type UpdateUser, UsersRepository } from '../repositories/users.repository'
|
|
import { CollectionsService } from './collections.service'
|
|
import { DrizzleService } from './drizzle.service'
|
|
import { WishlistsService } from './wishlists.service'
|
|
import type {OAuthUser} from "$lib/server/api/common/types/oauth-user";
|
|
|
|
@injectable()
|
|
export class UsersService {
|
|
constructor(
|
|
@inject(CollectionsService) private readonly collectionsService: CollectionsService,
|
|
@inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository,
|
|
@inject(DrizzleService) private readonly drizzleService: DrizzleService,
|
|
@inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository,
|
|
@inject(TokensService) private readonly tokenService: TokensService,
|
|
@inject(UsersRepository) private readonly usersRepository: UsersRepository,
|
|
@inject(UserRolesService) private readonly userRolesService: UserRolesService,
|
|
@inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository,
|
|
@inject(WishlistsService) private readonly wishlistsService: WishlistsService,
|
|
) {}
|
|
|
|
async create(data: SignupUsernameEmailDto) {
|
|
const { firstName, lastName, email, username, password } = data
|
|
|
|
const hashedPassword = await this.tokenService.createHashedToken(password)
|
|
return await this.drizzleService.db.transaction(async (trx) => {
|
|
const createdUser = await this.usersRepository.create(
|
|
{
|
|
first_name: firstName,
|
|
last_name: lastName,
|
|
email,
|
|
username,
|
|
},
|
|
trx,
|
|
)
|
|
|
|
if (!createdUser) {
|
|
return null
|
|
}
|
|
|
|
const credentials = await this.credentialsRepository.create(
|
|
{
|
|
user_id: createdUser.id,
|
|
type: CredentialsType.PASSWORD,
|
|
secret_data: hashedPassword,
|
|
},
|
|
trx,
|
|
)
|
|
|
|
if (!credentials) {
|
|
await this.usersRepository.delete(createdUser.id)
|
|
return null
|
|
}
|
|
|
|
await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx)
|
|
|
|
await this.wishlistsService.createEmptyNoName(createdUser.id, trx)
|
|
await this.collectionsService.createEmptyNoName(createdUser.id, trx)
|
|
})
|
|
}
|
|
|
|
async createOAuthUser(oAuthUser: OAuthUser, oauthProvider: string) {
|
|
return await this.drizzleService.db.transaction(async (trx) => {
|
|
const createdUser = await this.usersRepository.create(
|
|
{
|
|
username: oAuthUser.username || oAuthUser.username,
|
|
email: oAuthUser.email || null,
|
|
first_name: oAuthUser.given_name || null,
|
|
last_name: oAuthUser.family_name || null,
|
|
picture: oAuthUser.picture || null,
|
|
email_verified: oAuthUser.email_verified || false,
|
|
},
|
|
trx,
|
|
)
|
|
|
|
if (!createdUser) {
|
|
return null
|
|
}
|
|
|
|
await this.federatedIdentityRepository.create(
|
|
{
|
|
identity_provider: oauthProvider,
|
|
user_id: createdUser.id,
|
|
federated_user_id: oAuthUser.sub,
|
|
federated_username: oAuthUser.email || oAuthUser.username,
|
|
},
|
|
trx,
|
|
)
|
|
|
|
await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx)
|
|
|
|
await this.wishlistsService.createEmptyNoName(createdUser.id, trx)
|
|
await this.collectionsService.createEmptyNoName(createdUser.id, trx)
|
|
return createdUser
|
|
})
|
|
}
|
|
|
|
async updateUser(userId: string, data: UpdateUser) {
|
|
return this.usersRepository.update(userId, data)
|
|
}
|
|
|
|
async findOneByUsername(username: string) {
|
|
return this.usersRepository.findOneByUsername(username)
|
|
}
|
|
|
|
async findOneByEmail(email: string) {
|
|
return this.usersRepository.findOneByEmail(email)
|
|
}
|
|
|
|
async findOneById(id: string) {
|
|
return this.usersRepository.findOneById(id)
|
|
}
|
|
|
|
async updatePassword(userId: string, password: string) {
|
|
const hashedPassword = await this.tokenService.createHashedToken(password)
|
|
const currentCredentials = await this.credentialsRepository.findPasswordCredentialsByUserId(userId)
|
|
if (!currentCredentials) {
|
|
await this.credentialsRepository.create({
|
|
user_id: userId,
|
|
type: CredentialsType.PASSWORD,
|
|
secret_data: hashedPassword,
|
|
})
|
|
} else {
|
|
await this.credentialsRepository.update(currentCredentials.id, {
|
|
secret_data: hashedPassword,
|
|
})
|
|
}
|
|
}
|
|
|
|
async verifyPassword(userId: string, data: { password: string }) {
|
|
const user = await this.usersRepository.findOneById(userId)
|
|
if (!user) {
|
|
throw new Error('User not found')
|
|
}
|
|
const credential = await this.credentialsRepository.findOneByUserIdAndType(userId, CredentialsType.PASSWORD)
|
|
if (!credential) {
|
|
throw new Error('Password credentials not found')
|
|
}
|
|
const { password } = data
|
|
return this.tokenService.verifyHashedToken(credential.secret_data, password)
|
|
}
|
|
}
|