All files / src/platform/user user.service.ts

0% Statements 0/27
0% Branches 0/18
0% Functions 0/6
0% Lines 0/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                                                                                                                                                                   
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './schemas/user.schema';
import { Tenant } from '../tenants/schemas/tenant.schema';
 
@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private readonly userModel: Model<User>,
    @InjectModel(Tenant.name) private readonly tenantModel: Model<Tenant>,
  ) {}
 
  async findAll(tenantId: string, page = 1, limit = 20) {
    const skip = (page - 1) * limit;
    const [users, total] = await Promise.all([
      this.userModel
        .find({ tenantId })
        .skip(skip)
        .limit(limit)
        .sort({ createdAt: -1 })
        .lean()
        .exec(),
      this.userModel.countDocuments({ tenantId }).exec(),
    ]);
 
    return {
      data: users.map((u) => ({
        id: (u as any)._id.toString(),
        email: u.email,
        firstName: u.firstName,
        lastName: u.lastName,
        avatar: u.avatar,
        isActive: u.isActive,
        isEmailVerified: u.isEmailVerified,
        roles: u.roles,
        lastLoginAt: u.lastLoginAt,
        createdAt: u.createdAt,
      })),
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }
 
  async findById(id: string) {
    const user = await this.userModel.findById(id).lean().exec();
    if (!user) throw new NotFoundException('User not found');
 
    const tenant = await this.tenantModel.findById(user.tenantId).lean().exec();
 
    return {
      id: (user as any)._id.toString(),
      email: user.email,
      firstName: user.firstName,
      lastName: user.lastName,
      avatar: user.avatar,
      phone: user.phone,
      isActive: user.isActive,
      isEmailVerified: user.isEmailVerified,
      twoFactorEnabled: user.twoFactorEnabled,
      roles: user.roles,
      tenant: tenant
        ? {
            id: (tenant as any)._id.toString(),
            name: tenant.name,
            slug: tenant.slug,
          }
        : null,
      lastLoginAt: user.lastLoginAt,
      createdAt: user.createdAt,
    };
  }
 
  async updateProfile(
    id: string,
    data: Partial<{
      firstName: string;
      lastName: string;
      phone: string;
      avatar: string;
    }>,
  ) {
    const updated = await this.userModel
      .findByIdAndUpdate(id, data, { new: true })
      .lean()
      .exec();
 
    if (!updated) throw new NotFoundException('User not found');
 
    return {
      id: (updated as any)._id.toString(),
      email: updated.email,
      firstName: updated.firstName,
      lastName: updated.lastName,
      phone: updated.phone,
      avatar: updated.avatar,
    };
  }
 
  async deactivate(id: string) {
    const updated = await this.userModel
      .findByIdAndUpdate(id, { isActive: false }, { new: true })
      .lean()
      .exec();
 
    if (!updated) throw new NotFoundException('User not found');
    return updated;
  }
}