fix: join address to the customer get by admin

This commit is contained in:
mahyargdz
2025-03-06 10:35:12 +03:30
parent b92a65c22c
commit 144bfb2ac1
12 changed files with 257 additions and 75 deletions
+5
View File
@@ -56,6 +56,9 @@ export const enum AuthMessage {
TIMESTAMP_NOT_EMPTY = "زمان نمی‌تواند خالی باشد", TIMESTAMP_NOT_EMPTY = "زمان نمی‌تواند خالی باشد",
ADMIN_CAN_NOT_LOGIN = "ادمین نمی‌تواند وارد شود", ADMIN_CAN_NOT_LOGIN = "ادمین نمی‌تواند وارد شود",
NATIONAL_CODE_INVALID = "کد ملی نامعتبر است", NATIONAL_CODE_INVALID = "کد ملی نامعتبر است",
INVALID_REFRESH_TOKEN = "توکن رفرش نامعتبر است",
REFRESH_TOKEN_EXPIRED = "توکن رفرش منقضی شده است",
LOGOUT_SUCCESS = "خروج با موفقیت انجام شد",
} }
export const enum UserMessage { export const enum UserMessage {
@@ -95,6 +98,8 @@ export const enum UserMessage {
FINANCIAL_TYPE_IS_REAL = "نوع کاربر حقیقی می‌باشد", FINANCIAL_TYPE_IS_REAL = "نوع کاربر حقیقی می‌باشد",
LEGAL_DATA_NOT_FOUND = "اطلاعات حقوقی یافت نشد", LEGAL_DATA_NOT_FOUND = "اطلاعات حقوقی یافت نشد",
REAL_DATA_NOT_FOUND = "اطلاعات حقیقی یافت نشد", REAL_DATA_NOT_FOUND = "اطلاعات حقیقی یافت نشد",
REGISTRATION_NAME_EXIST = "نام ثبت قبلا ثبت شده است",
ADDRESS_NOT_FOUND = "آدرس یافت نشد",
} }
export const enum CommonMessage { export const enum CommonMessage {
+1 -1
View File
@@ -10,6 +10,6 @@ export class City {
@Column({ type: "varchar", length: 255 }) @Column({ type: "varchar", length: 255 })
name: string; name: string;
@ManyToOne(() => Province, (province) => province.cities, { eager: true, nullable: false }) @ManyToOne(() => Province, (province) => province.cities, { nullable: false })
province: Province; province: Province;
} }
@@ -0,0 +1,9 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsString } from "class-validator";
export class RefreshTokenDto {
@ApiProperty({ description: "Refresh token" })
@IsString({ message: "Refresh token must be a string" })
@IsNotEmpty({ message: "Refresh token is required" })
refreshToken: string;
}
+17
View File
@@ -5,6 +5,7 @@ import { Throttle, ThrottlerGuard } from "@nestjs/throttler";
import { ChangePasswordDto } from "./DTO/change-password.dto"; import { ChangePasswordDto } from "./DTO/change-password.dto";
import { CompleteRegistrationDto } from "./DTO/complete-register.dto"; import { CompleteRegistrationDto } from "./DTO/complete-register.dto";
import { CheckUserExistDto, LoginPasswordDTO } from "./DTO/loginPassword.dto"; import { CheckUserExistDto, LoginPasswordDTO } from "./DTO/loginPassword.dto";
import { RefreshTokenDto } from "./DTO/refresh-token.dto";
import { RequestOtpDto } from "./DTO/request-otp.dto"; import { RequestOtpDto } from "./DTO/request-otp.dto";
import { VerifyOtpDto } from "./DTO/verify-otp.dto"; import { VerifyOtpDto } from "./DTO/verify-otp.dto";
import { AuthService } from "./providers/auth.service"; import { AuthService } from "./providers/auth.service";
@@ -82,6 +83,22 @@ export class AuthController {
changePassword(@UserDec("id") userId: string, @Body() changePasswordDto: ChangePasswordDto) { changePassword(@UserDec("id") userId: string, @Body() changePasswordDto: ChangePasswordDto) {
return this.authService.changePassword(userId, changePasswordDto); return this.authService.changePassword(userId, changePasswordDto);
} }
@AuthGuards()
@ApiOperation({ summary: "refresh the user access token / refresh token" })
@HttpCode(HttpStatus.OK)
@Post("refresh")
refresh(@Body() refreshTokenDto: RefreshTokenDto) {
return this.authService.refreshToken(refreshTokenDto.refreshToken);
}
@AuthGuards()
@ApiOperation({ summary: "logout the user" })
@HttpCode(HttpStatus.OK)
@Post("logout")
logout(@Body() refreshTokenDto: RefreshTokenDto) {
return this.authService.logout(refreshTokenDto.refreshToken);
}
//***************************** */ //***************************** */
// @Post("forgot-password") // @Post("forgot-password")
+18 -18
View File
@@ -5,7 +5,6 @@ import { TokensService } from "./tokens.service";
import { AuthMessage, UserMessage } from "../../../common/enums/message.enum"; import { AuthMessage, UserMessage } from "../../../common/enums/message.enum";
import { NotificationsService } from "../../notifications/providers/notifications.service"; import { NotificationsService } from "../../notifications/providers/notifications.service";
import { Role } from "../../users/entities/role.entity"; import { Role } from "../../users/entities/role.entity";
import { User } from "../../users/entities/user.entity";
import { UsersService } from "../../users/providers/users.service"; import { UsersService } from "../../users/providers/users.service";
import { OTPService } from "../../utils/providers/otp.service"; import { OTPService } from "../../utils/providers/otp.service";
import { PasswordService } from "../../utils/providers/password.service"; import { PasswordService } from "../../utils/providers/password.service";
@@ -69,7 +68,7 @@ export class AuthService {
const hashedPassword = await this.passwordService.hashPassword(completeRegistrationDto.password); const hashedPassword = await this.passwordService.hashPassword(completeRegistrationDto.password);
const user = await this.usersService.createUser(completeRegistrationDto, hashedPassword, queryRunner); const user = await this.usersService.createUser(completeRegistrationDto, hashedPassword, queryRunner);
const tokens = this.generateAccessAndRefreshToken(user); const tokens = await this.tokensService.generateTokens(user);
await queryRunner.commitTransaction(); await queryRunner.commitTransaction();
@@ -93,7 +92,7 @@ export class AuthService {
if (!user.roles.some((role) => !role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN); if (!user.roles.some((role) => !role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN);
const tokens = this.generateAccessAndRefreshToken(user); const tokens = await this.tokensService.generateTokens(user);
await this.notificationService.createLoginNotification(user.id, { userPhone: user.phone }); await this.notificationService.createLoginNotification(user.id, { userPhone: user.phone });
@@ -113,7 +112,7 @@ export class AuthService {
const isAdmin = this.checkUserIsAdmin(user.roles); const isAdmin = this.checkUserIsAdmin(user.roles);
if (!isAdmin) throw new BadRequestException(AuthMessage.NOT_ADMIN); if (!isAdmin) throw new BadRequestException(AuthMessage.NOT_ADMIN);
const tokens = this.generateAccessAndRefreshToken(user); const tokens = await this.tokensService.generateTokens(user);
return { return {
message: AuthMessage.PASSWORD_LOGIN_SUCCESS, message: AuthMessage.PASSWORD_LOGIN_SUCCESS,
@@ -174,7 +173,7 @@ export class AuthService {
if (!user.roles.some((role) => !role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN); if (!user.roles.some((role) => !role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN);
// if (user.roles.some((role) => role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN); // if (user.roles.some((role) => role.isAdmin)) throw new BadRequestException(AuthMessage.ADMIN_CAN_NOT_LOGIN);
const tokens = this.generateAccessAndRefreshToken(user); const tokens = await this.tokensService.generateTokens(user);
await this.notificationService.createLoginNotification(user.id, { userPhone: user.phone }); await this.notificationService.createLoginNotification(user.id, { userPhone: user.phone });
return { return {
@@ -183,7 +182,6 @@ export class AuthService {
}; };
} }
//****************** */
//****************** */ //****************** */
async adminVerifyLoginOtp(verifyOtpDto: VerifyOtpDto) { async adminVerifyLoginOtp(verifyOtpDto: VerifyOtpDto) {
@@ -195,7 +193,7 @@ export class AuthService {
if (!isUserAdmin) throw new BadRequestException(AuthMessage.NOT_ADMIN); if (!isUserAdmin) throw new BadRequestException(AuthMessage.NOT_ADMIN);
const tokens = this.generateAccessAndRefreshToken(user); const tokens = await this.tokensService.generateTokens(user);
return { return {
message: AuthMessage.LOGIN_SUCCESS, message: AuthMessage.LOGIN_SUCCESS,
@@ -219,6 +217,19 @@ export class AuthService {
message: AuthMessage.PASSWORD_CHANGED_SUCCESSFULLY, message: AuthMessage.PASSWORD_CHANGED_SUCCESSFULLY,
}; };
} }
//****************** */
async refreshToken(oldRefreshToken: string) {
return this.tokensService.refreshToken(oldRefreshToken);
}
//****************** */
async logout(refreshToken: string) {
await this.tokensService.invalidateRefreshToken(refreshToken);
return {
message: AuthMessage.LOGOUT_SUCCESS,
};
}
//****************** */ //****************** */
@@ -245,17 +256,6 @@ export class AuthService {
return user; return user;
} }
//****************** */
//****************** */
private generateAccessAndRefreshToken(user: User) {
return this.tokensService.generateAccessAndRefreshToken({
id: user.id,
isAdmin: user.roles.some((r) => r.isAdmin),
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
});
}
//****************** */
//****************** */
// private checkUserPerm(user: User, perm: PermissionEnum) { // private checkUserPerm(user: User, perm: PermissionEnum) {
// return user.roles.some((role) => role?.permissions?.some((p) => p.name === perm)); // return user.roles.some((role) => role?.permissions?.some((p) => p.name === perm));
// } // }
+62 -32
View File
@@ -1,53 +1,83 @@
import { Injectable } from "@nestjs/common"; import { Injectable, UnauthorizedException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config"; import { ConfigService } from "@nestjs/config";
import { JwtService } from "@nestjs/jwt"; import { JwtService } from "@nestjs/jwt";
import dayjs from "dayjs";
import { AuthMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity";
import { UsersService } from "../../users/providers/users.service";
import { RefreshTokensRepository } from "../../users/repositories/refresh-token.repository";
import { ITokenPayload } from "../interfaces/IToken-payload"; import { ITokenPayload } from "../interfaces/IToken-payload";
// import { UserRepository } from "../users/providers/users.repository";
@Injectable() @Injectable()
export class TokensService { export class TokensService {
constructor( constructor(
private readonly configService: ConfigService, private readonly configService: ConfigService,
private readonly jwtService: JwtService, private readonly jwtService: JwtService,
// private readonly userRepository: UserRepository, private readonly refreshTokensRepository: RefreshTokensRepository,
private readonly usersService: UsersService,
) {} ) {}
// ----------- generate token ----------------- // ----------- generate token -----------------
generateAccessAndRefreshToken(payload: ITokenPayload) {
const access_expire = this.configService.getOrThrow<number>("ACCESS_TOKEN_EXPIRE");
const refresh_expire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
const accessToken = this.jwtService.sign(payload, { expiresIn: `${access_expire}h` }); async generateTokens(user: User) {
return this.generateAccessAndRefreshToken({
id: user.id,
isAdmin: user.roles.some((r) => r.isAdmin),
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
});
}
const refreshToken = this.jwtService.sign(payload, { expiresIn: `${refresh_expire}d` }); //**************************************************************** */
private async generateAccessAndRefreshToken(payload: ITokenPayload) {
const accessExpire = this.configService.getOrThrow<number>("ACCESS_TOKEN_EXPIRE");
const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
const accessToken = this.jwtService.sign(payload, { expiresIn: `${accessExpire}h` });
const refreshToken = this.jwtService.sign(payload, { expiresIn: `${refreshExpire}d` });
await this.storeRefreshToken(payload.id, refreshToken);
return { return {
accessToken: { token: accessToken, expire: Date.now() + 1000 * 60 * 60 * access_expire }, accessToken: { token: accessToken, expire: Date.now() + 1000 * 60 * 60 * accessExpire },
refreshToken: { token: refreshToken, expire: Date.now() + 1000 * 60 * 60 * 24 * refresh_expire }, refreshToken: { token: refreshToken, expire: Date.now() + 1000 * 60 * 60 * 24 * refreshExpire },
}; };
} }
//****************************** */ //**************************************************************** */
// validateRefreshToken(token: string) { async storeRefreshToken(userId: string, refreshToken: string) {
// const { sub } = this.verifyToken(token, "refresh"); const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
// return this.generateAccessAndRefreshToken({ sub: sub });
// }
// verifyToken(token: string, type: "access" | "refresh"): ITokenPayload { const expiresAt = dayjs().add(refreshExpire, "day").toDate();
// try {
// if (type === "access") { const token = this.refreshTokensRepository.create({
// return this.jwtService.verify(token, { token: refreshToken,
// secret: process.env.ACCESS_TOKEN_SECRET, user: { id: userId },
// ignoreExpiration: false, expiresAt,
// }); });
// } else if (type === "refresh") {
// return this.jwtService.verify(token, { await this.refreshTokensRepository.save(token);
// secret: process.env.REFRESH_TOKEN_SECRET, }
// ignoreExpiration: false, /************************************************************ */
// });
// } else throw new Error("Invalid token type => access / refresh"); async refreshToken(oldRefreshToken: string) {
// } catch { const token = await this.refreshTokensRepository.findOne({ where: { token: oldRefreshToken }, relations: { user: true } });
// throw new HttpException(AuthMessage.LoginAgain, HttpStatus.UNAUTHORIZED);
// } if (!token) throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN);
// }
if (dayjs(token.expiresAt).isBefore(dayjs())) throw new UnauthorizedException(AuthMessage.REFRESH_TOKEN_EXPIRED);
const { user } = await this.usersService.findOneById(token.user.id);
await this.refreshTokensRepository.delete({ id: token.id });
return await this.generateTokens(user);
}
/************************************************************ */
async invalidateRefreshToken(oldRefreshToken: string) {
const token = await this.refreshTokensRepository.findOne({ where: { token: oldRefreshToken }, relations: { user: true } });
if (token) await this.refreshTokensRepository.delete({ id: token.id });
}
} }
@@ -0,0 +1,16 @@
import { Column, Entity, ManyToOne } from "typeorm";
import { User } from "./user.entity";
import { BaseEntity } from "../../../common/entities/base.entity";
@Entity()
export class RefreshToken extends BaseEntity {
@Column({ type: "text" })
token: string;
@ManyToOne(() => User, (user) => user.refreshTokens, { onDelete: "CASCADE" })
user: User;
@Column({ type: "timestamptz", nullable: true })
expiresAt: Date;
}
@@ -3,6 +3,7 @@ import { Column, Entity, JoinTable, ManyToMany, OneToMany, OneToOne } from "type
import { LegalUser } from "./legal-user.entity"; import { LegalUser } from "./legal-user.entity";
import { RealUser } from "./real-user.entity"; import { RealUser } from "./real-user.entity";
import { RefreshToken } from "./refresh-token.entity";
import { Role } from "./role.entity"; import { Role } from "./role.entity";
import { UserGroup } from "./user-group.entity"; import { UserGroup } from "./user-group.entity";
import { BaseEntity } from "../../../common/entities/base.entity"; import { BaseEntity } from "../../../common/entities/base.entity";
@@ -120,6 +121,9 @@ export class User extends BaseEntity {
@OneToMany(() => UserQuickAccess, (quickAccess) => quickAccess.user) @OneToMany(() => UserQuickAccess, (quickAccess) => quickAccess.user)
quickAccesses: UserQuickAccess[]; quickAccesses: UserQuickAccess[];
@OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user, { cascade: true })
refreshTokens: RefreshToken[];
} }
// @ManyToMany(() => DanakService, (danakService) => danakService.users) // @ManyToMany(() => DanakService, (danakService) => danakService.users)
@@ -2,6 +2,7 @@ import { BadRequestException, Injectable, Logger } from "@nestjs/common";
import { DataSource, Not } from "typeorm"; import { DataSource, Not } from "typeorm";
import { CommonMessage, UserMessage } from "../../../common/enums/message.enum"; import { CommonMessage, UserMessage } from "../../../common/enums/message.enum";
import { Address } from "../../address/entities/address.entity";
import { AddressService } from "../../address/providers/address.service"; import { AddressService } from "../../address/providers/address.service";
import { UserSettingsService } from "../../settings/providers/user-settings.service"; import { UserSettingsService } from "../../settings/providers/user-settings.service";
import { PasswordService } from "../../utils/providers/password.service"; import { PasswordService } from "../../utils/providers/password.service";
@@ -83,67 +84,144 @@ export class CustomersService {
await queryRunner.connect(); await queryRunner.connect();
await queryRunner.startTransaction(); await queryRunner.startTransaction();
const {
registrationName,
economicCode,
nationalIdentity,
registrationCode,
postalCode,
nationalCode,
address,
cityId,
birthDate,
email,
firstName,
lastName,
password,
phone,
} = updateDto;
const legalUserUpdateData = {
registrationName,
economicCode,
nationalIdentity,
registrationCode,
phone,
};
const userUpdateData = {
email,
firstName,
lastName,
password,
phone,
birthDate,
};
// const addressUpdateData = {
// postalCode,
// address,
// cityId,
// };
const user = await queryRunner.manager.findOne(this.userRepository.target, { where: { id: customerId } }); const user = await queryRunner.manager.findOne(this.userRepository.target, { where: { id: customerId } });
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND); if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
if (updateDto.email) { if (email) {
const existingEmail = await queryRunner.manager.findOne(this.userRepository.target, { const existingEmail = await queryRunner.manager.findOne(this.userRepository.target, {
where: { email: updateDto.email, id: Not(user.id) }, where: { email, id: Not(user.id) },
}); });
if (existingEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST); if (existingEmail) throw new BadRequestException(UserMessage.EMAIL_EXIST);
} }
if (updateDto.nationalCode) { if (nationalCode) {
const existingNationalCode = await queryRunner.manager.findOne(this.userRepository.target, { const existingNationalCode = await queryRunner.manager.findOne(this.userRepository.target, {
where: { nationalCode: updateDto.nationalCode, id: Not(user.id) }, where: { nationalCode: nationalCode, id: Not(user.id) },
}); });
if (existingNationalCode) throw new BadRequestException(UserMessage.NATIONAL_CODE_EXIST); if (existingNationalCode) throw new BadRequestException(UserMessage.NATIONAL_CODE_EXIST);
} }
if (updateDto.phone) { if (phone) {
const existingPhone = await queryRunner.manager.findOne(this.userRepository.target, { const existingPhone = await queryRunner.manager.findOne(this.userRepository.target, {
where: { phone: updateDto.phone, id: Not(user.id) }, where: { phone: phone, id: Not(user.id) },
}); });
if (existingPhone) throw new BadRequestException(UserMessage.PHONE_EXIST); if (existingPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
} }
await queryRunner.manager.update(this.userRepository.target, { id: customerId }, updateDto); if (nationalCode) {
const existingNationalCode = await queryRunner.manager.findOne(this.realUserRepository.target, {
where: { nationalCode: nationalCode, id: Not(user.id) },
});
if (existingNationalCode) throw new BadRequestException(UserMessage.NATIONAL_CODE_EXIST);
}
const legalUser = await queryRunner.manager.findOne(this.legalUserRepository.target, { where: { user: { id: customerId } } }); await queryRunner.manager.update(this.userRepository.target, { id: customerId }, userUpdateData);
if (password) {
const hashPassword = await this.passwordService.hashPassword(password);
await queryRunner.manager.update(this.userRepository.target, { id: customerId }, { password: hashPassword });
}
const legalUser = await queryRunner.manager.findOne(this.legalUserRepository.target, {
where: { user: { id: customerId } },
relations: { address: true },
});
if (!legalUser) throw new BadRequestException(UserMessage.LEGAL_DATA_NOT_FOUND); if (!legalUser) throw new BadRequestException(UserMessage.LEGAL_DATA_NOT_FOUND);
if (updateDto.economicCode) { if (economicCode) {
const existingEconomicCode = await queryRunner.manager.findOne(this.legalUserRepository.target, { const existingEconomicCode = await queryRunner.manager.findOne(this.legalUserRepository.target, {
where: { economicCode: updateDto.economicCode, id: Not(legalUser.id) }, where: { economicCode, id: Not(legalUser.id) },
}); });
if (existingEconomicCode) throw new BadRequestException(UserMessage.ECONOMIC_CODE_EXIST); if (existingEconomicCode) throw new BadRequestException(UserMessage.ECONOMIC_CODE_EXIST);
} }
if (updateDto.registrationCode) { if (registrationCode) {
const existingRegistrationCode = await queryRunner.manager.findOne(this.legalUserRepository.target, { const existingRegistrationCode = await queryRunner.manager.findOne(this.legalUserRepository.target, {
where: { registrationCode: updateDto.registrationCode, id: Not(legalUser.id) }, where: { registrationCode, id: Not(legalUser.id) },
}); });
if (existingRegistrationCode) throw new BadRequestException(UserMessage.REGISTRATION_CODE_EXIST); if (existingRegistrationCode) throw new BadRequestException(UserMessage.REGISTRATION_CODE_EXIST);
} }
if (updateDto.nationalIdentity) { if (nationalIdentity) {
const existingNationalIdentity = await queryRunner.manager.findOne(this.legalUserRepository.target, { const existingNationalIdentity = await queryRunner.manager.findOne(this.legalUserRepository.target, {
where: { nationalIdentity: updateDto.nationalIdentity, id: Not(legalUser.id) }, where: { nationalIdentity, id: Not(legalUser.id) },
}); });
if (existingNationalIdentity) throw new BadRequestException(UserMessage.NATIONAL_IDENTITY_EXIST); if (existingNationalIdentity) throw new BadRequestException(UserMessage.NATIONAL_IDENTITY_EXIST);
} }
if (updateDto.cityId) { if (registrationName) {
const { city } = await this.addressService.getCity(+updateDto.cityId); const existingRegistrationName = await queryRunner.manager.findOne(this.legalUserRepository.target, {
await queryRunner.manager.update(this.legalUserRepository.target, { id: legalUser.id }, { address: { city } }); where: { registrationName, id: Not(legalUser.id) },
});
if (existingRegistrationName) throw new BadRequestException(UserMessage.REGISTRATION_NAME_EXIST);
} }
const { address, ...legalUserUpdateData } = updateDto;
await queryRunner.manager.update(this.legalUserRepository.target, { id: legalUser.id }, legalUserUpdateData); await queryRunner.manager.update(this.legalUserRepository.target, { id: legalUser.id }, legalUserUpdateData);
if (address) { // Update address if needed
await queryRunner.manager.update(this.legalUserRepository.target, { id: legalUser.id }, { address: { fullAddress: address } }); if (cityId || address || postalCode) {
// Get the address entity
const addressEntity = legalUser.address;
if (!addressEntity) throw new BadRequestException(UserMessage.ADDRESS_NOT_FOUND);
// Prepare address updates
const addressUpdates: any = {};
if (cityId) {
const { city } = await this.addressService.getCity(+cityId);
addressUpdates.city = city;
}
if (address) {
addressUpdates.fullAddress = address;
}
if (postalCode) {
addressUpdates.postalCode = postalCode;
}
await queryRunner.manager.update(Address, { id: addressEntity.id }, addressUpdates);
} }
await queryRunner.commitTransaction(); await queryRunner.commitTransaction();
@@ -306,7 +384,7 @@ export class CustomersService {
async getCustomerById(userId: string) { async getCustomerById(userId: string) {
const customer = await this.userRepository.findOne({ const customer = await this.userRepository.findOne({
where: { id: userId, roles: { name: RoleEnum.USER } }, where: { id: userId, roles: { name: RoleEnum.USER } },
relations: { legalUser: true, realUser: true }, relations: { legalUser: { address: { city: { province: true } } }, realUser: { address: { city: { province: true } } } },
}); });
return { customer }; return { customer };
@@ -0,0 +1,12 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { RefreshToken } from "../entities/refresh-token.entity";
@Injectable()
export class RefreshTokensRepository extends Repository<RefreshToken> {
constructor(@InjectRepository(RefreshToken) refreshTokenRepository: Repository<RefreshToken>) {
super(refreshTokenRepository.target, refreshTokenRepository.manager, refreshTokenRepository.queryRunner);
}
}
+9 -1
View File
@@ -12,6 +12,7 @@ import { CreateRoleDto } from "./DTO/create-role.dto";
import { SearchAdminQueryDto } from "./DTO/search-admins-query.dto"; import { SearchAdminQueryDto } from "./DTO/search-admins-query.dto";
import { SearchCustomersDto } from "./DTO/search-customers.dto"; import { SearchCustomersDto } from "./DTO/search-customers.dto";
import { SearchRolesQueryDto } from "./DTO/search-roles.dto"; import { SearchRolesQueryDto } from "./DTO/search-roles.dto";
import { UpdateCustomerDto } from "./DTO/update-customer.dto";
import { UpdateProfileDto } from "./DTO/update-profile.dto"; import { UpdateProfileDto } from "./DTO/update-profile.dto";
import { CreateUserGroupDto } from "./DTO/user-group.dto"; import { CreateUserGroupDto } from "./DTO/user-group.dto";
import { EmailVerifyQueryDto } from "./DTO/verify-email-query.dto"; import { EmailVerifyQueryDto } from "./DTO/verify-email-query.dto";
@@ -144,11 +145,18 @@ export class UsersController {
@ApiOperation({ summary: "Create customer" }) @ApiOperation({ summary: "Create customer" })
@AuthGuards() @AuthGuards()
@HttpCode(HttpStatus.CREATED) @HttpCode(HttpStatus.CREATED)
@Post("customer") @Post("customers")
createCustomer(@Body() createDto: CreateCustomerDto) { createCustomer(@Body() createDto: CreateCustomerDto) {
return this.customersService.createCustomer(createDto); return this.customersService.createCustomer(createDto);
} }
@ApiOperation({ summary: "Update customer" })
@AuthGuards()
@Patch("customers/:id")
updateCustomer(@Param() paramDto: ParamDto, @Body() updateDto: UpdateCustomerDto) {
return this.customersService.updateCustomer(paramDto.id, updateDto);
}
@ApiOperation({ summary: "get customers ==> admin route" }) @ApiOperation({ summary: "get customers ==> admin route" })
@AuthGuards() @AuthGuards()
@PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS) @PermissionsDec(PermissionEnum.ADMINS, PermissionEnum.CUSTOMERS)
+5 -2
View File
@@ -3,6 +3,7 @@ import { TypeOrmModule } from "@nestjs/typeorm";
import { LegalUser } from "./entities/legal-user.entity"; import { LegalUser } from "./entities/legal-user.entity";
import { Permission } from "./entities/permission.entity"; import { Permission } from "./entities/permission.entity";
import { RefreshToken } from "./entities/refresh-token.entity";
import { Role } from "./entities/role.entity"; import { Role } from "./entities/role.entity";
import { UserGroup } from "./entities/user-group.entity"; import { UserGroup } from "./entities/user-group.entity";
import { User } from "./entities/user.entity"; import { User } from "./entities/user.entity";
@@ -24,10 +25,11 @@ import { UsersController } from "./users.controller";
import { UtilsModule } from "../utils/utils.module"; import { UtilsModule } from "../utils/utils.module";
import { AdminsService } from "./providers/admins.service"; import { AdminsService } from "./providers/admins.service";
import { CustomersService } from "./providers/customers.service"; import { CustomersService } from "./providers/customers.service";
import { RefreshTokensRepository } from "./repositories/refresh-token.repository";
@Module({ @Module({
imports: [ imports: [
TypeOrmModule.forFeature([User, Role, UserGroup, UserSetting, RealUser, LegalUser, Permission]), TypeOrmModule.forFeature([User, Role, UserGroup, UserSetting, RealUser, LegalUser, Permission, RefreshToken]),
WalletsModule, WalletsModule,
UtilsModule, UtilsModule,
AddressModule, AddressModule,
@@ -37,6 +39,7 @@ import { CustomersService } from "./providers/customers.service";
AdminsService, AdminsService,
CustomersService, CustomersService,
UserRepository, UserRepository,
RefreshTokensRepository,
RoleRepository, RoleRepository,
UserGroupRepository, UserGroupRepository,
UserSettingsRepository, UserSettingsRepository,
@@ -47,6 +50,6 @@ import { CustomersService } from "./providers/customers.service";
AddressService, AddressService,
], ],
controllers: [UsersController], controllers: [UsersController],
exports: [UsersService, UserRepository, CustomersService, AdminsService], exports: [UsersService, UserRepository, CustomersService, AdminsService, RefreshTokensRepository],
}) })
export class UsersModule {} export class UsersModule {}