update product full

This commit is contained in:
2026-03-26 12:25:46 +03:00
parent f2b5f7006b
commit 4f5b557085
31733 changed files with 2762883 additions and 5 deletions

75
dist/modules/auth/auth.controller.d.ts vendored Normal file
View File

@@ -0,0 +1,75 @@
import { Request } from 'express';
import { UserRole } from '../users/enums/user-role.enum';
import { AuthService } from './auth.service';
import { LoginPasswordDto } from './dto/login-password.dto';
import { RefreshTokenDto } from './dto/refresh-token.dto';
import { RegisterPasswordDto } from './dto/register-password.dto';
import { RequestOtpDto } from './dto/request-otp.dto';
import { VerifyOtpDto } from './dto/verify-otp.dto';
import { JwtPayload } from './interfaces/jwt-payload.interface';
export declare class AuthController {
private readonly authService;
constructor(authService: AuthService);
requestOtp(dto: RequestOtpDto): Promise<{
message: string;
expiresInSeconds: number;
phone: string;
smsSent: boolean;
otpPreview: string | undefined;
}>;
registerWithPassword(dto: RegisterPasswordDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: import("../users/enums/user-level.enum").UserLevel;
};
}>;
loginWithPassword(dto: LoginPasswordDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: import("../users/enums/user-level.enum").UserLevel;
};
}>;
verifyOtp(dto: VerifyOtpDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: import("../users/enums/user-level.enum").UserLevel;
};
}>;
refresh(dto: RefreshTokenDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: import("../users/enums/user-level.enum").UserLevel;
};
}>;
logout(request: Request & {
user: JwtPayload;
}): Promise<{
message: string;
}>;
adminCheck(request: Request & {
user: JwtPayload;
}): {
user: Express.User & JwtPayload;
authorized: boolean;
};
}

121
dist/modules/auth/auth.controller.js vendored Normal file
View File

@@ -0,0 +1,121 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthController = void 0;
const common_1 = require("@nestjs/common");
const swagger_1 = require("@nestjs/swagger");
const permissions_decorator_1 = require("../../common/decorators/permissions.decorator");
const roles_decorator_1 = require("../../common/decorators/roles.decorator");
const permissions_guard_1 = require("../../common/guards/permissions.guard");
const roles_guard_1 = require("../../common/guards/roles.guard");
const user_role_enum_1 = require("../users/enums/user-role.enum");
const auth_service_1 = require("./auth.service");
const login_password_dto_1 = require("./dto/login-password.dto");
const refresh_token_dto_1 = require("./dto/refresh-token.dto");
const register_password_dto_1 = require("./dto/register-password.dto");
const request_otp_dto_1 = require("./dto/request-otp.dto");
const verify_otp_dto_1 = require("./dto/verify-otp.dto");
const jwt_auth_guard_1 = require("./guards/jwt-auth.guard");
let AuthController = class AuthController {
authService;
constructor(authService) {
this.authService = authService;
}
requestOtp(dto) {
return this.authService.requestOtp(dto.phone, dto.fullName);
}
registerWithPassword(dto) {
return this.authService.registerWithPassword(dto);
}
loginWithPassword(dto) {
return this.authService.loginWithPassword(dto);
}
verifyOtp(dto) {
return this.authService.verifyOtp(dto.phone, dto.otp);
}
refresh(dto) {
return this.authService.refreshToken(dto.refreshToken);
}
logout(request) {
return this.authService.logout(request.user.sub);
}
adminCheck(request) {
return {
user: request.user,
authorized: true,
};
}
};
exports.AuthController = AuthController;
__decorate([
(0, common_1.Post)('otp/request'),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [request_otp_dto_1.RequestOtpDto]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "requestOtp", null);
__decorate([
(0, common_1.Post)('register/password'),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [register_password_dto_1.RegisterPasswordDto]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "registerWithPassword", null);
__decorate([
(0, common_1.Post)('login/password'),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [login_password_dto_1.LoginPasswordDto]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "loginWithPassword", null);
__decorate([
(0, common_1.Post)('otp/verify'),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [verify_otp_dto_1.VerifyOtpDto]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "verifyOtp", null);
__decorate([
(0, common_1.Post)('refresh'),
__param(0, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [refresh_token_dto_1.RefreshTokenDto]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "refresh", null);
__decorate([
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
(0, swagger_1.ApiBearerAuth)(),
(0, common_1.Post)('logout'),
__param(0, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "logout", null);
__decorate([
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard, permissions_guard_1.PermissionsGuard),
(0, swagger_1.ApiBearerAuth)(),
(0, roles_decorator_1.Roles)(user_role_enum_1.UserRole.ADMIN),
(0, permissions_decorator_1.Permissions)('users.manage'),
(0, common_1.Get)('me/admin-check'),
__param(0, (0, common_1.Req)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], AuthController.prototype, "adminCheck", null);
exports.AuthController = AuthController = __decorate([
(0, swagger_1.ApiTags)('Auth'),
(0, common_1.Controller)('auth'),
__metadata("design:paramtypes", [auth_service_1.AuthService])
], AuthController);
//# sourceMappingURL=auth.controller.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAOwB;AAExB,6CAAyD;AACzD,yFAA4E;AAC5E,6EAAgE;AAChE,6EAAyE;AACzE,iEAA6D;AAC7D,kEAAyD;AACzD,iDAA6C;AAC7C,iEAA4D;AAC5D,+DAA0D;AAC1D,uEAAkE;AAClE,2DAAsD;AACtD,yDAAoD;AACpD,4DAAuD;AAKhD,IAAM,cAAc,GAApB,MAAM,cAAc;IACI;IAA7B,YAA6B,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAGzD,UAAU,CAAS,GAAkB;QACnC,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAGD,oBAAoB,CAAS,GAAwB;QACnD,OAAO,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;IAGD,iBAAiB,CAAS,GAAqB;QAC7C,OAAO,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IAGD,SAAS,CAAS,GAAiB;QACjC,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAGD,OAAO,CAAS,GAAoB;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;IAKD,MAAM,CAAQ,OAAuC;QACnD,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,CAAC;IAOD,UAAU,CAAQ,OAAuC;QACvD,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;CACF,CAAA;AA9CY,wCAAc;AAIzB;IADC,IAAA,aAAI,EAAC,aAAa,CAAC;IACR,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,+BAAa;;gDAEpC;AAGD;IADC,IAAA,aAAI,EAAC,mBAAmB,CAAC;IACJ,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,2CAAmB;;0DAEpD;AAGD;IADC,IAAA,aAAI,EAAC,gBAAgB,CAAC;IACJ,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,qCAAgB;;uDAE9C;AAGD;IADC,IAAA,aAAI,EAAC,YAAY,CAAC;IACR,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,6BAAY;;+CAElC;AAGD;IADC,IAAA,aAAI,EAAC,SAAS,CAAC;IACP,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAM,mCAAe;;6CAEnC;AAKD;IAHC,IAAA,kBAAS,EAAC,6BAAY,CAAC;IACvB,IAAA,uBAAa,GAAE;IACf,IAAA,aAAI,EAAC,QAAQ,CAAC;IACP,WAAA,IAAA,YAAG,GAAE,CAAA;;;;4CAEZ;AAOD;IALC,IAAA,kBAAS,EAAC,6BAAY,EAAE,wBAAU,EAAE,oCAAgB,CAAC;IACrD,IAAA,uBAAa,GAAE;IACf,IAAA,uBAAK,EAAC,yBAAQ,CAAC,KAAK,CAAC;IACrB,IAAA,mCAAW,EAAC,cAAc,CAAC;IAC3B,IAAA,YAAG,EAAC,gBAAgB,CAAC;IACV,WAAA,IAAA,YAAG,GAAE,CAAA;;;;gDAKhB;yBA7CU,cAAc;IAF1B,IAAA,iBAAO,EAAC,MAAM,CAAC;IACf,IAAA,mBAAU,EAAC,MAAM,CAAC;qCAEyB,0BAAW;GAD1C,cAAc,CA8C1B"}

2
dist/modules/auth/auth.module.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare class AuthModule {
}

47
dist/modules/auth/auth.module.js vendored Normal file
View File

@@ -0,0 +1,47 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthModule = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const jwt_1 = require("@nestjs/jwt");
const passport_1 = require("@nestjs/passport");
const typeorm_1 = require("@nestjs/typeorm");
const auth_controller_1 = require("./auth.controller");
const auth_service_1 = require("./auth.service");
const auth_otp_entity_1 = require("./entities/auth-otp.entity");
const user_session_entity_1 = require("./entities/user-session.entity");
const sms_service_1 = require("./sms.service");
const jwt_strategy_1 = require("./strategies/jwt.strategy");
const users_module_1 = require("../users/users.module");
const roles_guard_1 = require("../../common/guards/roles.guard");
const permissions_guard_1 = require("../../common/guards/permissions.guard");
let AuthModule = class AuthModule {
};
exports.AuthModule = AuthModule;
exports.AuthModule = AuthModule = __decorate([
(0, common_1.Module)({
imports: [
users_module_1.UsersModule,
passport_1.PassportModule,
config_1.ConfigModule,
typeorm_1.TypeOrmModule.forFeature([auth_otp_entity_1.AuthOtp, user_session_entity_1.UserSession]),
jwt_1.JwtModule.registerAsync({
imports: [config_1.ConfigModule],
inject: [config_1.ConfigService],
useFactory: (configService) => ({
secret: configService.getOrThrow('jwt.secret'),
}),
}),
],
controllers: [auth_controller_1.AuthController],
providers: [auth_service_1.AuthService, sms_service_1.SmsService, jwt_strategy_1.JwtStrategy, roles_guard_1.RolesGuard, permissions_guard_1.PermissionsGuard],
exports: [auth_service_1.AuthService],
})
], AuthModule);
//# sourceMappingURL=auth.module.js.map

1
dist/modules/auth/auth.module.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2CAA6D;AAC7D,qCAAwC;AACxC,+CAAkD;AAClD,6CAAgD;AAChD,uDAAmD;AACnD,iDAA6C;AAC7C,gEAAqD;AACrD,wEAA6D;AAC7D,+CAA2C;AAC3C,4DAAwD;AACxD,wDAAoD;AACpD,iEAA6D;AAC7D,6EAAyE;AAoBlE,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAlBtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,0BAAW;YACX,yBAAc;YACd,qBAAY;YACZ,uBAAa,CAAC,UAAU,CAAC,CAAC,yBAAO,EAAE,iCAAW,CAAC,CAAC;YAChD,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,aAA4B,EAAE,EAAE,CAAC,CAAC;oBAC7C,MAAM,EAAE,aAAa,CAAC,UAAU,CAAS,YAAY,CAAC;iBACvD,CAAC;aACH,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,EAAE,wBAAU,EAAE,0BAAW,EAAE,wBAAU,EAAE,oCAAgB,CAAC;QAC/E,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"}

81
dist/modules/auth/auth.service.d.ts vendored Normal file
View File

@@ -0,0 +1,81 @@
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { Repository } from 'typeorm';
import { AuthOtp } from './entities/auth-otp.entity';
import { UserSession } from './entities/user-session.entity';
import { UserLevel } from '../users/enums/user-level.enum';
import { UserRole } from '../users/enums/user-role.enum';
import { UsersService } from '../users/users.service';
import { LoginPasswordDto } from './dto/login-password.dto';
import { RegisterPasswordDto } from './dto/register-password.dto';
import { SmsService } from './sms.service';
export declare class AuthService {
private readonly usersService;
private readonly jwtService;
private readonly configService;
private readonly smsService;
private readonly authOtpsRepository;
private readonly userSessionsRepository;
constructor(usersService: UsersService, jwtService: JwtService, configService: ConfigService, smsService: SmsService, authOtpsRepository: Repository<AuthOtp>, userSessionsRepository: Repository<UserSession>);
requestOtp(phone: string, fullName?: string): Promise<{
message: string;
expiresInSeconds: number;
phone: string;
smsSent: boolean;
otpPreview: string | undefined;
}>;
registerWithPassword(dto: RegisterPasswordDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: UserLevel;
};
}>;
loginWithPassword(dto: LoginPasswordDto): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: UserLevel;
};
}>;
verifyOtp(phone: string, otp: string): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: UserLevel;
};
}>;
refreshToken(refreshToken: string): Promise<{
accessToken: string;
refreshToken: string;
user: {
id: string;
phone: string;
fullName: string;
role: UserRole;
level: UserLevel;
};
}>;
logout(userId: string): Promise<{
message: string;
}>;
private issueTokens;
private storeRefreshToken;
private generateOtp;
private resolvePermissions;
private findUserById;
private findMatchingSession;
private parseDurationToMs;
}

276
dist/modules/auth/auth.service.js vendored Normal file
View File

@@ -0,0 +1,276 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const typeorm_1 = require("@nestjs/typeorm");
const jwt_1 = require("@nestjs/jwt");
const bcrypt = require("bcrypt");
const typeorm_2 = require("typeorm");
const auth_otp_entity_1 = require("./entities/auth-otp.entity");
const user_session_entity_1 = require("./entities/user-session.entity");
const user_level_enum_1 = require("../users/enums/user-level.enum");
const user_role_enum_1 = require("../users/enums/user-role.enum");
const users_service_1 = require("../users/users.service");
const sms_service_1 = require("./sms.service");
let AuthService = class AuthService {
usersService;
jwtService;
configService;
smsService;
authOtpsRepository;
userSessionsRepository;
constructor(usersService, jwtService, configService, smsService, authOtpsRepository, userSessionsRepository) {
this.usersService = usersService;
this.jwtService = jwtService;
this.configService = configService;
this.smsService = smsService;
this.authOtpsRepository = authOtpsRepository;
this.userSessionsRepository = userSessionsRepository;
}
async requestOtp(phone, fullName) {
const user = await this.usersService.findOrCreateByPhone(phone, fullName);
const otpCode = this.generateOtp();
const ttlSeconds = this.configService.get('otp.ttlSeconds', 120);
const otp = this.authOtpsRepository.create({
phone: user.phone,
codeHash: await bcrypt.hash(otpCode, 10),
purpose: 'login',
expiresAt: new Date(Date.now() + ttlSeconds * 1000),
attemptCount: 0,
});
await this.authOtpsRepository.save(otp);
const smsSent = await this.smsService.sendOtp(phone, otpCode);
return {
message: 'OTP generated successfully',
expiresInSeconds: ttlSeconds,
phone,
smsSent,
otpPreview: this.configService.get('app.nodeEnv') === 'development'
? otpCode
: undefined,
};
}
async registerWithPassword(dto) {
const existingPhone = await this.usersService.findByPhone(dto.phone);
if (existingPhone) {
throw new common_1.BadRequestException('Phone already exists');
}
const existingUsername = await this.usersService.findByUsername(dto.username);
if (existingUsername) {
throw new common_1.BadRequestException('Username already exists');
}
const savedUser = await this.usersService.create({
phone: dto.phone,
username: dto.username,
fullName: dto.fullName ?? dto.username,
passwordHash: await bcrypt.hash(dto.password, 10),
isVerified: true,
role: user_role_enum_1.UserRole.USER,
});
const tokens = await this.issueTokens(savedUser);
await this.storeRefreshToken(savedUser, tokens.refreshToken);
return tokens;
}
async loginWithPassword(dto) {
const user = await this.usersService.findByUsername(dto.username);
if (!user?.passwordHash) {
throw new common_1.UnauthorizedException('Invalid username or password');
}
const isPasswordValid = await bcrypt.compare(dto.password, user.passwordHash);
if (!isPasswordValid) {
throw new common_1.UnauthorizedException('Invalid username or password');
}
const tokens = await this.issueTokens(user);
await this.storeRefreshToken(user, tokens.refreshToken);
return tokens;
}
async verifyOtp(phone, otp) {
const user = await this.usersService.findByPhone(phone);
const otpRecord = await this.authOtpsRepository.findOne({
where: { phone, purpose: 'login', usedAt: (0, typeorm_2.IsNull)() },
order: { createdAt: 'DESC' },
});
if (!user || !otpRecord) {
throw new common_1.UnauthorizedException('OTP not requested');
}
if (otpRecord.expiresAt.getTime() < Date.now()) {
throw new common_1.UnauthorizedException('OTP expired');
}
const isOtpValid = await bcrypt.compare(otp, otpRecord.codeHash);
if (!isOtpValid) {
otpRecord.attemptCount += 1;
await this.authOtpsRepository.save(otpRecord);
throw new common_1.BadRequestException('Invalid OTP');
}
user.isVerified = true;
otpRecord.usedAt = new Date();
await Promise.all([
this.usersService.save(user),
this.authOtpsRepository.save(otpRecord),
]);
const tokens = await this.issueTokens(user);
await this.storeRefreshToken(user, tokens.refreshToken);
return tokens;
}
async refreshToken(refreshToken) {
const payload = await this.jwtService.verifyAsync(refreshToken, {
secret: this.configService.getOrThrow('jwt.secret'),
});
if (payload.type !== 'refresh') {
throw new common_1.UnauthorizedException('Invalid token type');
}
const user = await this.usersService.findByPhone(payload.phone);
if (!user) {
throw new common_1.UnauthorizedException('Refresh token not found');
}
const sessions = await this.userSessionsRepository.find({
where: {
user: { id: user.id },
revokedAt: (0, typeorm_2.IsNull)(),
},
relations: { user: true },
order: { createdAt: 'DESC' },
});
const validSession = await this.findMatchingSession(sessions, refreshToken);
if (!validSession || validSession.expiresAt.getTime() < Date.now()) {
throw new common_1.UnauthorizedException('Invalid refresh token');
}
validSession.revokedAt = new Date();
await this.userSessionsRepository.save(validSession);
const tokens = await this.issueTokens(user);
await this.storeRefreshToken(user, tokens.refreshToken);
return tokens;
}
async logout(userId) {
const user = await this.findUserById(userId);
await this.userSessionsRepository
.createQueryBuilder()
.update(user_session_entity_1.UserSession)
.set({ revokedAt: new Date() })
.where('userId = :userId', { userId: user.id })
.andWhere('revoked_at IS NULL')
.execute();
return { message: 'Logged out successfully' };
}
async issueTokens(user) {
const currentLevel = user.loyaltyProfile?.currentLevel ?? user_level_enum_1.UserLevel.BRONZE;
const accessPayload = {
sub: user.id,
phone: user.phone,
role: user.role,
level: currentLevel,
permissions: this.resolvePermissions(user),
type: 'access',
};
const refreshPayload = {
...accessPayload,
type: 'refresh',
};
const [accessToken, refreshToken] = await Promise.all([
this.jwtService.signAsync(accessPayload, {
secret: this.configService.getOrThrow('jwt.secret'),
expiresIn: this.configService.getOrThrow('jwt.accessTtl'),
}),
this.jwtService.signAsync(refreshPayload, {
secret: this.configService.getOrThrow('jwt.secret'),
expiresIn: this.configService.getOrThrow('jwt.refreshTtl'),
}),
]);
return {
accessToken,
refreshToken,
user: {
id: user.id,
phone: user.phone,
fullName: user.fullName,
role: user.role,
level: currentLevel,
},
};
}
async storeRefreshToken(user, refreshToken) {
const refreshTtl = this.configService.getOrThrow('jwt.refreshTtl');
const session = this.userSessionsRepository.create({
user,
refreshTokenHash: await bcrypt.hash(refreshToken, 10),
expiresAt: new Date(Date.now() + this.parseDurationToMs(refreshTtl)),
});
await this.userSessionsRepository.save(session);
}
generateOtp() {
return Math.floor(100000 + Math.random() * 900000).toString();
}
resolvePermissions(user) {
if (user.role === user_role_enum_1.UserRole.ADMIN) {
return [
'products.manage',
'categories.manage',
'brands.manage',
'users.manage',
'media.manage',
];
}
if (user.role === user_role_enum_1.UserRole.AGENT) {
return ['orders.assist', 'customers.assist'];
}
return ['profile.read'];
}
async findUserById(userId) {
const user = await this.usersService.findById(userId);
if (!user) {
throw new common_1.UnauthorizedException('User not found');
}
return user;
}
async findMatchingSession(sessions, refreshToken) {
for (const session of sessions) {
const isValid = await bcrypt.compare(refreshToken, session.refreshTokenHash);
if (isValid) {
return session;
}
}
return null;
}
parseDurationToMs(value) {
const match = /^(\d+)(ms|s|m|h|d)$/i.exec(value);
if (!match) {
throw new common_1.BadRequestException(`Unsupported duration format: ${value}`);
}
const amount = Number(match[1]);
const unit = match[2].toLowerCase();
const unitMap = {
ms: 1,
s: 1000,
m: 60 * 1000,
h: 60 * 60 * 1000,
d: 24 * 60 * 60 * 1000,
};
return amount * unitMap[unit];
}
};
exports.AuthService = AuthService;
exports.AuthService = AuthService = __decorate([
(0, common_1.Injectable)(),
__param(4, (0, typeorm_1.InjectRepository)(auth_otp_entity_1.AuthOtp)),
__param(5, (0, typeorm_1.InjectRepository)(user_session_entity_1.UserSession)),
__metadata("design:paramtypes", [users_service_1.UsersService,
jwt_1.JwtService,
config_1.ConfigService,
sms_service_1.SmsService,
typeorm_2.Repository,
typeorm_2.Repository])
], AuthService);
//# sourceMappingURL=auth.service.js.map

1
dist/modules/auth/auth.service.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
export declare class LoginPasswordDto {
username: string;
password: string;
}

View File

@@ -0,0 +1,31 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoginPasswordDto = void 0;
const class_validator_1 = require("class-validator");
class LoginPasswordDto {
username;
password;
}
exports.LoginPasswordDto = LoginPasswordDto;
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(3),
(0, class_validator_1.MaxLength)(50),
__metadata("design:type", String)
], LoginPasswordDto.prototype, "username", void 0);
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(6),
(0, class_validator_1.MaxLength)(100),
__metadata("design:type", String)
], LoginPasswordDto.prototype, "password", void 0);
//# sourceMappingURL=login-password.dto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"login-password.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/login-password.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAiE;AAEjE,MAAa,gBAAgB;IAI3B,QAAQ,CAAS;IAKjB,QAAQ,CAAS;CAClB;AAVD,4CAUC;AANC;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,EAAE,CAAC;;kDACG;AAKjB;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;kDACE"}

View File

@@ -0,0 +1,3 @@
export declare class RefreshTokenDto {
refreshToken: string;
}

View File

@@ -0,0 +1,23 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RefreshTokenDto = void 0;
const class_validator_1 = require("class-validator");
class RefreshTokenDto {
refreshToken;
}
exports.RefreshTokenDto = RefreshTokenDto;
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(10),
__metadata("design:type", String)
], RefreshTokenDto.prototype, "refreshToken", void 0);
//# sourceMappingURL=refresh-token.dto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"refresh-token.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/refresh-token.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAsD;AAEtD,MAAa,eAAe;IAG1B,YAAY,CAAS;CACtB;AAJD,0CAIC;AADC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,EAAE,CAAC;;qDACO"}

View File

@@ -0,0 +1,6 @@
export declare class RegisterPasswordDto {
phone: string;
username: string;
password: string;
fullName?: string;
}

View File

@@ -0,0 +1,44 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegisterPasswordDto = void 0;
const class_validator_1 = require("class-validator");
class RegisterPasswordDto {
phone;
username;
password;
fullName;
}
exports.RegisterPasswordDto = RegisterPasswordDto;
__decorate([
(0, class_validator_1.Matches)(/^\+?[1-9]\d{7,14}$/),
__metadata("design:type", String)
], RegisterPasswordDto.prototype, "phone", void 0);
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(3),
(0, class_validator_1.MaxLength)(50),
__metadata("design:type", String)
], RegisterPasswordDto.prototype, "username", void 0);
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(6),
(0, class_validator_1.MaxLength)(100),
__metadata("design:type", String)
], RegisterPasswordDto.prototype, "password", void 0);
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(2),
(0, class_validator_1.MaxLength)(150),
__metadata("design:type", String)
], RegisterPasswordDto.prototype, "fullName", void 0);
//# sourceMappingURL=register-password.dto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"register-password.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/register-password.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAsF;AAEtF,MAAa,mBAAmB;IAE9B,KAAK,CAAS;IAKd,QAAQ,CAAS;IAKjB,QAAQ,CAAS;IAMjB,QAAQ,CAAU;CACnB;AAnBD,kDAmBC;AAjBC;IADC,IAAA,yBAAO,EAAC,oBAAoB,CAAC;;kDAChB;AAKd;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,EAAE,CAAC;;qDACG;AAKjB;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;qDACE;AAMjB;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;qDACG"}

View File

@@ -0,0 +1,4 @@
export declare class RequestOtpDto {
phone: string;
fullName?: string;
}

View File

@@ -0,0 +1,30 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RequestOtpDto = void 0;
const class_validator_1 = require("class-validator");
class RequestOtpDto {
phone;
fullName;
}
exports.RequestOtpDto = RequestOtpDto;
__decorate([
(0, class_validator_1.Matches)(/^\+?[1-9]\d{7,14}$/),
__metadata("design:type", String)
], RequestOtpDto.prototype, "phone", void 0);
__decorate([
(0, class_validator_1.IsOptional)(),
(0, class_validator_1.IsString)(),
(0, class_validator_1.MinLength)(2),
(0, class_validator_1.MaxLength)(150),
__metadata("design:type", String)
], RequestOtpDto.prototype, "fullName", void 0);
//# sourceMappingURL=request-otp.dto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"request-otp.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/request-otp.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAsF;AAEtF,MAAa,aAAa;IAExB,KAAK,CAAS;IAMd,QAAQ,CAAU;CACnB;AATD,sCASC;AAPC;IADC,IAAA,yBAAO,EAAC,oBAAoB,CAAC;;4CAChB;AAMd;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,CAAC,CAAC;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;+CACG"}

View File

@@ -0,0 +1,4 @@
export declare class VerifyOtpDto {
phone: string;
otp: string;
}

28
dist/modules/auth/dto/verify-otp.dto.js vendored Normal file
View File

@@ -0,0 +1,28 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.VerifyOtpDto = void 0;
const class_validator_1 = require("class-validator");
class VerifyOtpDto {
phone;
otp;
}
exports.VerifyOtpDto = VerifyOtpDto;
__decorate([
(0, class_validator_1.Matches)(/^\+?[1-9]\d{7,14}$/),
__metadata("design:type", String)
], VerifyOtpDto.prototype, "phone", void 0);
__decorate([
(0, class_validator_1.IsString)(),
(0, class_validator_1.Length)(4, 6),
__metadata("design:type", String)
], VerifyOtpDto.prototype, "otp", void 0);
//# sourceMappingURL=verify-otp.dto.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"verify-otp.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/verify-otp.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA4D;AAE5D,MAAa,YAAY;IAEvB,KAAK,CAAS;IAId,GAAG,CAAS;CACb;AAPD,oCAOC;AALC;IADC,IAAA,yBAAO,EAAC,oBAAoB,CAAC;;2CAChB;AAId;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAM,EAAC,CAAC,EAAE,CAAC,CAAC;;yCACD"}

View File

@@ -0,0 +1,11 @@
export declare class AuthOtp {
id: string;
phone: string;
codeHash: string;
purpose: string;
expiresAt: Date;
usedAt?: Date | null;
attemptCount: number;
createdAt: Date;
updatedAt: Date;
}

View File

@@ -0,0 +1,66 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthOtp = void 0;
const typeorm_1 = require("typeorm");
let AuthOtp = class AuthOtp {
id;
phone;
codeHash;
purpose;
expiresAt;
usedAt;
attemptCount;
createdAt;
updatedAt;
};
exports.AuthOtp = AuthOtp;
__decorate([
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
__metadata("design:type", String)
], AuthOtp.prototype, "id", void 0);
__decorate([
(0, typeorm_1.Index)(),
(0, typeorm_1.Column)({ length: 20 }),
__metadata("design:type", String)
], AuthOtp.prototype, "phone", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'code_hash', length: 255 }),
__metadata("design:type", String)
], AuthOtp.prototype, "codeHash", void 0);
__decorate([
(0, typeorm_1.Column)({ length: 30, default: 'login' }),
__metadata("design:type", String)
], AuthOtp.prototype, "purpose", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'expires_at', type: 'timestamp with time zone' }),
__metadata("design:type", Date)
], AuthOtp.prototype, "expiresAt", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'used_at', type: 'timestamp with time zone', nullable: true }),
__metadata("design:type", Object)
], AuthOtp.prototype, "usedAt", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'attempt_count', type: 'int', default: 0 }),
__metadata("design:type", Number)
], AuthOtp.prototype, "attemptCount", void 0);
__decorate([
(0, typeorm_1.CreateDateColumn)({ name: 'created_at' }),
__metadata("design:type", Date)
], AuthOtp.prototype, "createdAt", void 0);
__decorate([
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at' }),
__metadata("design:type", Date)
], AuthOtp.prototype, "updatedAt", void 0);
exports.AuthOtp = AuthOtp = __decorate([
(0, typeorm_1.Entity)({ name: 'auth_otps' })
], AuthOtp);
//# sourceMappingURL=auth-otp.entity.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"auth-otp.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/auth-otp.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAOiB;AAGV,IAAM,OAAO,GAAb,MAAM,OAAO;IAElB,EAAE,CAAS;IAIX,KAAK,CAAS;IAGd,QAAQ,CAAS;IAGjB,OAAO,CAAS;IAGhB,SAAS,CAAO;IAGhB,MAAM,CAAe;IAGrB,YAAY,CAAS;IAGrB,SAAS,CAAO;IAGhB,SAAS,CAAO;CACjB,CAAA;AA5BY,0BAAO;AAElB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;mCACpB;AAIX;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;sCACT;AAGd;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;yCAC1B;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;;wCACzB;AAGhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;8BACtD,IAAI;0CAAC;AAGhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,0BAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;uCACzD;AAGrB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;;6CACtC;AAGrB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;0CAAC;AAGhB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;0CAAC;kBA3BL,OAAO;IADnB,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;GACjB,OAAO,CA4BnB"}

View File

@@ -0,0 +1,12 @@
import { User } from '../../users/entities/user.entity';
export declare class UserSession {
id: string;
user: User;
refreshTokenHash: string;
expiresAt: Date;
revokedAt?: Date | null;
deviceInfo?: string | null;
ipAddress?: string | null;
createdAt: Date;
updatedAt: Date;
}

View File

@@ -0,0 +1,67 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserSession = void 0;
const typeorm_1 = require("typeorm");
const user_entity_1 = require("../../users/entities/user.entity");
let UserSession = class UserSession {
id;
user;
refreshTokenHash;
expiresAt;
revokedAt;
deviceInfo;
ipAddress;
createdAt;
updatedAt;
};
exports.UserSession = UserSession;
__decorate([
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
__metadata("design:type", String)
], UserSession.prototype, "id", void 0);
__decorate([
(0, typeorm_1.Index)(),
(0, typeorm_1.ManyToOne)(() => user_entity_1.User, (user) => user.sessions, { onDelete: 'CASCADE' }),
__metadata("design:type", user_entity_1.User)
], UserSession.prototype, "user", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'refresh_token_hash', length: 255 }),
__metadata("design:type", String)
], UserSession.prototype, "refreshTokenHash", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'expires_at', type: 'timestamp with time zone' }),
__metadata("design:type", Date)
], UserSession.prototype, "expiresAt", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'revoked_at', type: 'timestamp with time zone', nullable: true }),
__metadata("design:type", Object)
], UserSession.prototype, "revokedAt", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'device_info', type: 'varchar', length: 255, nullable: true }),
__metadata("design:type", Object)
], UserSession.prototype, "deviceInfo", void 0);
__decorate([
(0, typeorm_1.Column)({ name: 'ip_address', type: 'varchar', length: 64, nullable: true }),
__metadata("design:type", Object)
], UserSession.prototype, "ipAddress", void 0);
__decorate([
(0, typeorm_1.CreateDateColumn)({ name: 'created_at' }),
__metadata("design:type", Date)
], UserSession.prototype, "createdAt", void 0);
__decorate([
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at' }),
__metadata("design:type", Date)
], UserSession.prototype, "updatedAt", void 0);
exports.UserSession = UserSession = __decorate([
(0, typeorm_1.Entity)({ name: 'user_sessions' })
], UserSession);
//# sourceMappingURL=user-session.entity.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"user-session.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/user-session.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAQiB;AACjB,kEAAwD;AAGjD,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEtB,EAAE,CAAS;IAIX,IAAI,CAAO;IAGX,gBAAgB,CAAS;IAGzB,SAAS,CAAO;IAGhB,SAAS,CAAe;IAGxB,UAAU,CAAiB;IAG3B,SAAS,CAAiB;IAG1B,SAAS,CAAO;IAGhB,SAAS,CAAO;CACjB,CAAA;AA5BY,kCAAW;AAEtB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;uCACpB;AAIX;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,kBAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;8BAClE,kBAAI;yCAAC;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;qDAC3B;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;8BACtD,IAAI;8CAAC;AAGhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACzD;AAGxB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACnD;AAG3B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CAClD;AAG1B;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;8CAAC;AAGhB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC9B,IAAI;8CAAC;sBA3BL,WAAW;IADvB,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;GACrB,WAAW,CA4BvB"}

View File

@@ -0,0 +1,4 @@
declare const JwtAuthGuard_base: import("@nestjs/passport").Type<import("@nestjs/passport").IAuthGuard>;
export declare class JwtAuthGuard extends JwtAuthGuard_base {
}
export {};

View File

@@ -0,0 +1,18 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtAuthGuard = void 0;
const common_1 = require("@nestjs/common");
const passport_1 = require("@nestjs/passport");
let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)('jwt') {
};
exports.JwtAuthGuard = JwtAuthGuard;
exports.JwtAuthGuard = JwtAuthGuard = __decorate([
(0, common_1.Injectable)()
], JwtAuthGuard);
//# sourceMappingURL=jwt-auth.guard.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../../src/modules/auth/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAC5C,+CAA6C;AAGtC,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,IAAA,oBAAS,EAAC,KAAK,CAAC;CAAG,CAAA;AAAxC,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;GACA,YAAY,CAA4B"}

View File

@@ -0,0 +1,10 @@
import { UserLevel } from '../../users/enums/user-level.enum';
import { UserRole } from '../../users/enums/user-role.enum';
export interface JwtPayload {
sub: string;
phone: string;
role: UserRole;
level: UserLevel;
permissions: string[];
type: 'access' | 'refresh';
}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jwt-payload.interface.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"jwt-payload.interface.js","sourceRoot":"","sources":["../../../../src/modules/auth/interfaces/jwt-payload.interface.ts"],"names":[],"mappings":""}

7
dist/modules/auth/sms.service.d.ts vendored Normal file
View File

@@ -0,0 +1,7 @@
import { ConfigService } from '@nestjs/config';
export declare class SmsService {
private readonly configService;
private readonly logger;
constructor(configService: ConfigService);
sendOtp(mobile: string, otpCode: string): Promise<boolean>;
}

56
dist/modules/auth/sms.service.js vendored Normal file
View File

@@ -0,0 +1,56 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var SmsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SmsService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const soap_1 = require("soap");
let SmsService = SmsService_1 = class SmsService {
configService;
logger = new common_1.Logger(SmsService_1.name);
constructor(configService) {
this.configService = configService;
}
async sendOtp(mobile, otpCode) {
const wsdlUrl = this.configService.get('sms.wsdlUrl');
const username = this.configService.get('sms.username');
const password = this.configService.get('sms.password');
const fromNumber = this.configService.get('sms.fromNumber');
if (!wsdlUrl || !username || !password || !fromNumber) {
this.logger.warn('SMS provider config is incomplete, OTP SMS skipped.');
return false;
}
const content = `آکادمی زبان آلمانی انجل\nکد تایید شما: ${otpCode}\nلغو11`;
try {
const client = await (0, soap_1.createClientAsync)(wsdlUrl);
const [result] = await client.SendSMSAsync(fromNumber, [mobile], content, '0', username, password);
if (Array.isArray(result) && result[0] > 0) {
return true;
}
if (typeof result === 'number' && result > 0) {
return true;
}
this.logger.warn(`SMS provider returned unsuccessful response: ${JSON.stringify(result)}`);
return false;
}
catch (error) {
this.logger.error('SOAP SMS send failed', error instanceof Error ? error.stack : undefined);
throw new common_1.InternalServerErrorException('OTP SMS sending failed');
}
}
};
exports.SmsService = SmsService;
exports.SmsService = SmsService = SmsService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [config_1.ConfigService])
], SmsService);
//# sourceMappingURL=sms.service.js.map

1
dist/modules/auth/sms.service.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"sms.service.js","sourceRoot":"","sources":["../../../src/modules/auth/sms.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAkF;AAClF,2CAA+C;AAC/C,+BAAyC;AAGlC,IAAM,UAAU,kBAAhB,MAAM,UAAU;IAGQ;IAFZ,MAAM,GAAG,IAAI,eAAM,CAAC,YAAU,CAAC,IAAI,CAAC,CAAC;IAEtD,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAE7D,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,OAAe;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,aAAa,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,gBAAgB,CAAC,CAAC;QAEpE,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YACxE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,0CAA0C,OAAO,SAAS,CAAC;QAE3E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAiB,EAAC,OAAO,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,YAAY,CACxC,UAAU,EACV,CAAC,MAAM,CAAC,EACR,OAAO,EACP,GAAG,EACH,QAAQ,EACR,QAAQ,CACT,CAAC;YAEF,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3C,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gDAAgD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3F,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC5F,MAAM,IAAI,qCAA4B,CAAC,wBAAwB,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;CACF,CAAA;AA5CY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;qCAIiC,sBAAa;GAH9C,UAAU,CA4CtB"}

View File

@@ -0,0 +1,11 @@
import { ConfigService } from '@nestjs/config';
import { Strategy } from 'passport-jwt';
import { JwtPayload } from '../interfaces/jwt-payload.interface';
declare const JwtStrategy_base: new (...args: [opt: import("passport-jwt").StrategyOptionsWithRequest] | [opt: import("passport-jwt").StrategyOptionsWithoutRequest]) => Strategy & {
validate(...args: any[]): unknown;
};
export declare class JwtStrategy extends JwtStrategy_base {
constructor(configService: ConfigService);
validate(payload: JwtPayload): JwtPayload;
}
export {};

View File

@@ -0,0 +1,34 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.JwtStrategy = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const passport_1 = require("@nestjs/passport");
const passport_jwt_1 = require("passport-jwt");
let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(passport_jwt_1.Strategy) {
constructor(configService) {
super({
jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: configService.getOrThrow('jwt.secret'),
});
}
validate(payload) {
return payload;
}
};
exports.JwtStrategy = JwtStrategy;
exports.JwtStrategy = JwtStrategy = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [config_1.ConfigService])
], JwtStrategy);
//# sourceMappingURL=jwt.strategy.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../../../src/modules/auth/strategies/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAA+C;AAC/C,+CAAoD;AACpD,+CAAoD;AAI7C,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,2BAAgB,EAAC,uBAAQ,CAAC;IACzD,YAAY,aAA4B;QACtC,KAAK,CAAC;YACJ,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,aAAa,CAAC,UAAU,CAAS,YAAY,CAAC;SAC5D,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,OAAmB;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAA;AAZY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEgB,sBAAa;GAD7B,WAAW,CAYvB"}