auth : update
This commit is contained in:
@@ -7,6 +7,6 @@ export class RequestOtpDto {
|
||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||
@ApiProperty({ description: "phone number", default: "09922320740" })
|
||||
@ApiProperty({ description: "phone number", default: "09185290775" })
|
||||
phone: string;
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsMobilePhone, IsNotEmpty, IsNumberString, IsEnum, Length } from "class-validator";
|
||||
|
||||
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export enum ResellerType {
|
||||
agent = 'agent',
|
||||
reseller = 'reseller'
|
||||
}
|
||||
|
||||
export class VerifyResellerOtpDto {
|
||||
@IsNotEmpty({ message: AuthMessage.PHONE_NOT_EMPTY })
|
||||
@Length(11, 11, { message: AuthMessage.PHONE_SHOULD_BE_11_DIGIT })
|
||||
@IsMobilePhone("fa-IR", {}, { message: AuthMessage.INVALID_PHONE_FORMAT })
|
||||
@ApiProperty({ description: "phone number", default: "09185290775" })
|
||||
phone: string;
|
||||
|
||||
@ApiProperty({ description: "OTP code received via SMS", example: "" })
|
||||
@IsNotEmpty({ message: AuthMessage.OTP_NOT_EMPTY })
|
||||
@IsNumberString(undefined, { message: AuthMessage.OTP_FORMAT_INVALID })
|
||||
@Length(5, 5, { message: AuthMessage.OTP_FORMAT_INVALID })
|
||||
code: string;
|
||||
|
||||
@ApiProperty({ enum: ResellerType })
|
||||
@IsEnum(ResellerType)
|
||||
type: ResellerType;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import { UserDec } from "../../common/decorators/user.decorator";
|
||||
import { User } from "../users/entities/user.entity";
|
||||
import { ForgetPasswordDto } from "./DTO/forget-password.dto";
|
||||
import { VerifyForgotPasswordOtpDto } from "./DTO/verify-forgot-otp.dto";
|
||||
import { VerifyResellerOtpDto } from "./DTO/verify-reseller-otp.dto";
|
||||
|
||||
@ApiTags("Auth")
|
||||
@Controller("auth")
|
||||
@@ -80,7 +81,7 @@ export class AuthController {
|
||||
@ApiOperation({ summary: "verify otp for login" })
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post("otp/verify/reseller")
|
||||
resellerVerifyOtp(@Body() verifyOtpDto: VerifyOtpDto) {
|
||||
resellerVerifyOtp(@Body() verifyOtpDto: VerifyResellerOtpDto) {
|
||||
return this.authService.resellerVerifyLoginOtp(verifyOtpDto);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,13 @@ export class ResellerRouteGuard implements CanActivate {
|
||||
|
||||
if (!requiredReseller) return true;
|
||||
|
||||
console.log('hi')
|
||||
const req = context.switchToHttp().getRequest<FastifyRequest>();
|
||||
const user = req.user;
|
||||
|
||||
console.log(user)
|
||||
|
||||
if (!user) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
|
||||
|
||||
// if (!user.isReseller) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
|
||||
if (!user.resellerType) throw new ForbiddenException(AuthMessage.UNAUTHORIZED_ACCESS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
import { ResellerType } from "../DTO/verify-reseller-otp.dto";
|
||||
// import { RoleEnum } from "../../users/enums/role.enum";
|
||||
|
||||
export interface ITokenPayload {
|
||||
id: string;
|
||||
isAdmin: boolean;
|
||||
isReseller: boolean;
|
||||
resellerType?: ResellerType;
|
||||
permissions: PermissionEnum[];
|
||||
audience?: string; // Client application identifier for SSO
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { ForgetPasswordDto } from "../DTO/forget-password.dto";
|
||||
import { VerifyForgotPasswordOtpDto } from "../DTO/verify-forgot-otp.dto";
|
||||
import { EmailService } from "../../utils/providers/email.service";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { ResellerType, VerifyResellerOtpDto } from "../DTO/verify-reseller-otp.dto";
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
@@ -115,8 +116,14 @@ export class AuthService {
|
||||
async requestLoginOtpReseller(requestOtpDto: RequestOtpDto) {
|
||||
const { phone } = requestOtpDto;
|
||||
|
||||
// check if agent with this phone exist or not
|
||||
await this.checkAgentExistWithPhone(phone)
|
||||
|
||||
let user: User | null = null
|
||||
|
||||
user = (await this.usersService.getAgentByUserPhone(phone)) ?? (await this.usersService.getResellerByUserPhone(phone))
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException(AuthMessage.USER_NOT_FOUND)
|
||||
}
|
||||
|
||||
const existCode = await this.otpService.checkExistOtp(phone, "LOGIN_RESELLER_AGENT");
|
||||
if (existCode) {
|
||||
@@ -227,15 +234,18 @@ export class AuthService {
|
||||
}
|
||||
//****************** */
|
||||
|
||||
async resellerVerifyLoginOtp(verifyOtpDto: VerifyOtpDto) {
|
||||
const { code, phone } = verifyOtpDto;
|
||||
async resellerVerifyLoginOtp(verifyOtpDto: VerifyResellerOtpDto) {
|
||||
const { code, phone, type } = verifyOtpDto;
|
||||
|
||||
await this.checkResellerOtpWithPhone(phone, code)
|
||||
|
||||
const { agent, reseller } = await this.checkAgentExistWithPhone(phone);
|
||||
let user: User | null = null
|
||||
|
||||
|
||||
const user: User | null = agent ?? reseller
|
||||
if (type == ResellerType.agent) {
|
||||
user = await this.usersService.getAgentByUserPhone(phone)
|
||||
} else if (type == ResellerType.reseller) {
|
||||
user = await this.usersService.getResellerByUserPhone(phone)
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException(AuthMessage.USER_NOT_FOUND)
|
||||
@@ -243,7 +253,7 @@ export class AuthService {
|
||||
|
||||
if (user.deletedAt) throw new BadRequestException(AuthMessage.ACCESS_DENIED);
|
||||
|
||||
const tokens = await this.tokensService.generateTokensForReseller(user);
|
||||
const tokens = await this.tokensService.generateTokensForReseller(user, type);
|
||||
|
||||
return {
|
||||
message: AuthMessage.LOGIN_SUCCESS,
|
||||
@@ -310,20 +320,7 @@ export class AuthService {
|
||||
|
||||
return true;
|
||||
}
|
||||
//****************** */
|
||||
//****************** */
|
||||
private async checkAgentExistWithPhone(phone: string) {
|
||||
|
||||
const { reseller } = await this.usersService.getResellerByUserPhone(phone);
|
||||
|
||||
const { agent } = await this.usersService.getAgentByUserPhone(phone);
|
||||
|
||||
if (!reseller && !agent) {
|
||||
throw new BadRequestException(AuthMessage.USER_NOT_FOUND)
|
||||
}
|
||||
|
||||
return { reseller, agent }
|
||||
}
|
||||
//****************** */
|
||||
//****************** */
|
||||
async requestForgotPasswordOtp(dto: ForgetPasswordDto) {
|
||||
@@ -383,7 +380,5 @@ export class AuthService {
|
||||
}
|
||||
//****************** */
|
||||
//****************** */
|
||||
// private checkUserIsAgent(roles: Role[]) {
|
||||
// return roles.some((role) => role.isAgent);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ export class SSOService {
|
||||
// Generate token with client-specific audience
|
||||
const payload: ITokenPayload = {
|
||||
id: user.id,
|
||||
isReseller:false,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
audience: clientId,
|
||||
@@ -106,7 +105,6 @@ export class SSOService {
|
||||
const payload: ITokenPayload = {
|
||||
id: user.id,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
isReseller:false,
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
audience: clientId,
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import { AuthMessage } from "../../../common/enums/message.enum";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { RefreshTokensRepository } from "../../users/repositories/refresh-token.repository";
|
||||
import { ITokenPayload } from "../interfaces/IToken-payload";
|
||||
import { ResellerType } from "../DTO/verify-reseller-otp.dto";
|
||||
|
||||
@Injectable()
|
||||
export class TokensService {
|
||||
@@ -27,19 +28,18 @@ export class TokensService {
|
||||
{
|
||||
id: user.id,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
isReseller: false,
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
// -----------------------------
|
||||
async generateTokensForReseller(user: User, queryRunner?: QueryRunner) {
|
||||
async generateTokensForReseller(user: User, resellerType: ResellerType, queryRunner?: QueryRunner) {
|
||||
return this.generateAccessAndRefreshToken(
|
||||
{
|
||||
id: user.id,
|
||||
isAdmin: false,
|
||||
isReseller: true,
|
||||
resellerType,
|
||||
permissions: [],
|
||||
},
|
||||
queryRunner,
|
||||
|
||||
@@ -21,6 +21,11 @@ export class JwtStrategy extends PassportStrategy(Strategy, JWT_STRATEGY_NAME) {
|
||||
}
|
||||
|
||||
async validate(payload: ITokenPayload) {
|
||||
return { id: payload.id, permissions: payload.permissions, isAdmin: payload.isAdmin };
|
||||
return {
|
||||
id: payload.id,
|
||||
permissions: payload.permissions,
|
||||
isAdmin: payload.isAdmin,
|
||||
resellerType: payload.resellerType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user