import { Injectable } from '@nestjs/common'; import { InjectKysely } from 'nestjs-kysely'; import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types'; import { Users } from '@docmost/db/types/db'; import { hashPassword } from '../../../common/helpers'; import { dbOrTx } from '@docmost/db/utils'; import { InsertableUser, Space, UpdatableUser, User, } from '@docmost/db/types/entity.types'; import { PaginationOptions } from '../../pagination/pagination-options'; import { executeWithPagination, PaginationResult, } from '@docmost/db/pagination/pagination'; @Injectable() export class UserRepo { constructor(@InjectKysely() private readonly db: KyselyDB) {} public baseFields: Array = [ 'id', 'email', 'name', 'emailVerifiedAt', 'avatarUrl', 'role', 'workspaceId', 'locale', 'timezone', 'settings', 'lastLoginAt', 'deactivatedAt', 'createdAt', 'updatedAt', 'deletedAt', ]; async findById( userId: string, workspaceId: string, opts?: { includePassword?: boolean; trx?: KyselyTransaction; }, ): Promise { const db = dbOrTx(this.db, opts?.trx); return db .selectFrom('users') .select(this.baseFields) .$if(opts?.includePassword, (qb) => qb.select('password')) .where('id', '=', userId) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); } async findByEmail( email: string, workspaceId: string, includePassword?: boolean, ): Promise { return this.db .selectFrom('users') .select(this.baseFields) .$if(includePassword, (qb) => qb.select('password')) .where('email', '=', email) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); } async updateUser( updatableUser: UpdatableUser, userId: string, workspaceId: string, trx?: KyselyTransaction, ) { const db = dbOrTx(this.db, trx); return await db .updateTable('users') .set({ ...updatableUser, updatedAt: new Date() }) .where('id', '=', userId) .where('workspaceId', '=', workspaceId) .execute(); } async updateLastLogin(userId: string, workspaceId: string) { return await this.db .updateTable('users') .set({ lastLoginAt: new Date(), }) .where('id', '=', userId) .where('workspaceId', '=', workspaceId) .execute(); } async insertUser( insertableUser: InsertableUser, trx?: KyselyTransaction, ): Promise { const user: InsertableUser = { name: insertableUser.name || insertableUser.email.toLowerCase(), email: insertableUser.email.toLowerCase(), password: await hashPassword(insertableUser.password), locale: 'en', role: insertableUser?.role, lastLoginAt: new Date(), }; const db = dbOrTx(this.db, trx); return db .insertInto('users') .values(user) .returningAll() .executeTakeFirst(); } async roleCountByWorkspaceId( role: string, workspaceId: string, ): Promise { const { count } = await this.db .selectFrom('users') .select((eb) => eb.fn.count('role').as('count')) .where('role', '=', role) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); return count as number; } async getUsersPaginated(workspaceId: string, pagination: PaginationOptions) { let query = this.db .selectFrom('users') .select(this.baseFields) .where('workspaceId', '=', workspaceId) .orderBy('createdAt', 'asc'); if (pagination.query) { query = query.where((eb) => eb('users.name', 'ilike', `%${pagination.query}%`).or( 'users.email', 'ilike', `%${pagination.query}%`, ), ); } const result = executeWithPagination(query, { page: pagination.page, perPage: pagination.limit, }); return result; } /* async getSpaceIds( workspaceId: string, pagination: PaginationOptions, ): Promise> { const spaces = await this.spaceRepo.getSpacesInWorkspace( workspaceId, pagination, ); return spaces; } async getUserSpaces( workspaceId: string, pagination: PaginationOptions, ): Promise> { const spaces = await this.spaceRepo.getSpacesInWorkspace( workspaceId, pagination, ); return spaces; } */ }