feat: remove OTP gate from transactions, fix categories auth, add implementation plan
- Remove OtpGateGuard from transactions controller (OTP verified at login) - Fix categories controller to use authenticated user instead of TEMP_USER_ID - Add comprehensive implementation plan document - Update .env.example with WEB_APP_URL - Prepare for admin dashboard development
This commit is contained in:
83
apps/api/dist/auth/auth.controller.d.ts
vendored
Normal file
83
apps/api/dist/auth/auth.controller.d.ts
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import { AuthService } from './auth.service';
|
||||
import type { Response } from 'express';
|
||||
interface RequestWithUser {
|
||||
user: {
|
||||
userId: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
export declare class AuthController {
|
||||
private authService;
|
||||
constructor(authService: AuthService);
|
||||
register(body: {
|
||||
email: string;
|
||||
password: string;
|
||||
name?: string;
|
||||
}): Promise<{
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
}>;
|
||||
login(body: {
|
||||
email: string;
|
||||
password: string;
|
||||
}): Promise<{
|
||||
requiresOtp: boolean;
|
||||
availableMethods: {
|
||||
email: boolean;
|
||||
whatsapp: boolean;
|
||||
totp: boolean;
|
||||
};
|
||||
tempToken: string;
|
||||
user?: undefined;
|
||||
token?: undefined;
|
||||
} | {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
requiresOtp?: undefined;
|
||||
availableMethods?: undefined;
|
||||
tempToken?: undefined;
|
||||
}>;
|
||||
verifyOtp(body: {
|
||||
tempToken: string;
|
||||
otpCode: string;
|
||||
method: 'email' | 'totp';
|
||||
}): Promise<{
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
}>;
|
||||
googleAuth(): Promise<void>;
|
||||
googleAuthCallback(req: any, res: Response): Promise<void>;
|
||||
getProfile(req: RequestWithUser): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
emailVerified: boolean;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
}>;
|
||||
changePassword(req: RequestWithUser, body: {
|
||||
currentPassword: string;
|
||||
newPassword: string;
|
||||
isSettingPassword?: boolean;
|
||||
}): Promise<{
|
||||
message: string;
|
||||
}>;
|
||||
}
|
||||
export {};
|
||||
112
apps/api/dist/auth/auth.controller.js
vendored
Normal file
112
apps/api/dist/auth/auth.controller.js
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
"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 auth_guard_1 = require("./auth.guard");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
let AuthController = class AuthController {
|
||||
authService;
|
||||
constructor(authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
async register(body) {
|
||||
return this.authService.register(body.email, body.password, body.name);
|
||||
}
|
||||
async login(body) {
|
||||
return this.authService.login(body.email, body.password);
|
||||
}
|
||||
async verifyOtp(body) {
|
||||
return this.authService.verifyOtpAndLogin(body.tempToken, body.otpCode, body.method);
|
||||
}
|
||||
async googleAuth() {
|
||||
}
|
||||
async googleAuthCallback(req, res) {
|
||||
const result = await this.authService.googleLogin(req.user);
|
||||
const frontendUrl = process.env.WEB_APP_URL || 'http://localhost:5174';
|
||||
if (result.requiresOtp) {
|
||||
res.redirect(`${frontendUrl}/auth/otp?token=${result.tempToken}&methods=${JSON.stringify(result.availableMethods)}`);
|
||||
}
|
||||
else {
|
||||
res.redirect(`${frontendUrl}/auth/callback?token=${result.token}`);
|
||||
}
|
||||
}
|
||||
async getProfile(req) {
|
||||
return this.authService.getUserProfile(req.user.userId);
|
||||
}
|
||||
async changePassword(req, body) {
|
||||
return this.authService.changePassword(req.user.userId, body.currentPassword, body.newPassword, body.isSettingPassword);
|
||||
}
|
||||
};
|
||||
exports.AuthController = AuthController;
|
||||
__decorate([
|
||||
(0, common_1.Post)('register'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "register", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('login'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "login", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('verify-otp'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "verifyOtp", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('google'),
|
||||
(0, common_1.UseGuards)((0, passport_1.AuthGuard)('google')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "googleAuth", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('google/callback'),
|
||||
(0, common_1.UseGuards)((0, passport_1.AuthGuard)('google')),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__param(1, (0, common_1.Res)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "googleAuthCallback", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('me'),
|
||||
(0, common_1.UseGuards)(auth_guard_1.AuthGuard),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "getProfile", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('change-password'),
|
||||
(0, common_1.UseGuards)(auth_guard_1.AuthGuard),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "changePassword", null);
|
||||
exports.AuthController = AuthController = __decorate([
|
||||
(0, common_1.Controller)('auth'),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
||||
], AuthController);
|
||||
//# sourceMappingURL=auth.controller.js.map
|
||||
1
apps/api/dist/auth/auth.controller.js.map
vendored
Normal file
1
apps/api/dist/auth/auth.controller.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}
|
||||
15
apps/api/dist/auth/auth.guard.d.ts
vendored
15
apps/api/dist/auth/auth.guard.d.ts
vendored
@@ -1,8 +1,9 @@
|
||||
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
import { FirebaseService } from './firebase.service';
|
||||
export declare class AuthGuard implements CanActivate {
|
||||
private firebaseService;
|
||||
constructor(firebaseService: FirebaseService);
|
||||
canActivate(context: ExecutionContext): Promise<boolean>;
|
||||
private extractTokenFromHeader;
|
||||
import { ExecutionContext } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
declare const AuthGuard_base: import("@nestjs/passport").Type<import("@nestjs/passport").IAuthGuard>;
|
||||
export declare class AuthGuard extends AuthGuard_base {
|
||||
private reflector;
|
||||
constructor(reflector: Reflector);
|
||||
canActivate(context: ExecutionContext): boolean | Promise<boolean> | import("rxjs").Observable<boolean>;
|
||||
}
|
||||
export {};
|
||||
|
||||
41
apps/api/dist/auth/auth.guard.js
vendored
41
apps/api/dist/auth/auth.guard.js
vendored
@@ -11,39 +11,28 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const firebase_service_1 = require("./firebase.service");
|
||||
let AuthGuard = class AuthGuard {
|
||||
firebaseService;
|
||||
constructor(firebaseService) {
|
||||
this.firebaseService = firebaseService;
|
||||
const core_1 = require("@nestjs/core");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
let AuthGuard = class AuthGuard extends (0, passport_1.AuthGuard)('jwt') {
|
||||
reflector;
|
||||
constructor(reflector) {
|
||||
super();
|
||||
this.reflector = reflector;
|
||||
}
|
||||
async canActivate(context) {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
if (!this.firebaseService.isFirebaseConfigured()) {
|
||||
console.warn('⚠️ Firebase not configured - allowing request without auth');
|
||||
canActivate(context) {
|
||||
const isPublic = this.reflector.getAllAndOverride('isPublic', [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
]);
|
||||
if (isPublic) {
|
||||
return true;
|
||||
}
|
||||
const token = this.extractTokenFromHeader(request);
|
||||
if (!token) {
|
||||
throw new common_1.UnauthorizedException('No token provided');
|
||||
}
|
||||
try {
|
||||
const decodedToken = await this.firebaseService.verifyIdToken(token);
|
||||
request.user = decodedToken;
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
throw new common_1.UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
extractTokenFromHeader(request) {
|
||||
const [type, token] = request.headers.authorization?.split(' ') ?? [];
|
||||
return type === 'Bearer' ? token : undefined;
|
||||
return super.canActivate(context);
|
||||
}
|
||||
};
|
||||
exports.AuthGuard = AuthGuard;
|
||||
exports.AuthGuard = AuthGuard = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [firebase_service_1.FirebaseService])
|
||||
__metadata("design:paramtypes", [core_1.Reflector])
|
||||
], AuthGuard);
|
||||
//# sourceMappingURL=auth.guard.js.map
|
||||
2
apps/api/dist/auth/auth.guard.js.map
vendored
2
apps/api/dist/auth/auth.guard.js.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/auth/auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAkG;AAClG,yDAAqD;AAG9C,IAAM,SAAS,GAAf,MAAM,SAAS;IACA;IAApB,YAAoB,eAAgC;QAAhC,oBAAe,GAAf,eAAe,CAAiB;IAAG,CAAC;IAExD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAGpD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,oBAAoB,EAAE,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,8BAAqB,CAAC,mBAAmB,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACrE,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,8BAAqB,CAAC,eAAe,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAY;QACzC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AA/BY,8BAAS;oBAAT,SAAS;IADrB,IAAA,mBAAU,GAAE;qCAE0B,kCAAe;GADzC,SAAS,CA+BrB"}
|
||||
{"version":3,"file":"auth.guard.js","sourceRoot":"","sources":["../../src/auth/auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA8D;AAC9D,uCAAyC;AACzC,+CAAkE;AAG3D,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,IAAA,oBAAiB,EAAC,KAAK,CAAC;IACjC;IAApB,YAAoB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAExC,CAAC;IAED,WAAW,CAAC,OAAyB;QAEnC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,UAAU,EAAE;YACrE,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QAEH,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACF,CAAA;AAlBY,8BAAS;oBAAT,SAAS;IADrB,IAAA,mBAAU,GAAE;qCAEoB,gBAAS;GAD7B,SAAS,CAkBrB"}
|
||||
24
apps/api/dist/auth/auth.module.js
vendored
24
apps/api/dist/auth/auth.module.js
vendored
@@ -8,15 +8,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const firebase_service_1 = require("./firebase.service");
|
||||
const auth_guard_1 = require("./auth.guard");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
const auth_controller_1 = require("./auth.controller");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
const jwt_strategy_1 = require("./jwt.strategy");
|
||||
const google_strategy_1 = require("./google.strategy");
|
||||
const prisma_module_1 = require("../prisma/prisma.module");
|
||||
const otp_module_1 = require("../otp/otp.module");
|
||||
let AuthModule = class AuthModule {
|
||||
};
|
||||
exports.AuthModule = AuthModule;
|
||||
exports.AuthModule = AuthModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
providers: [firebase_service_1.FirebaseService, auth_guard_1.AuthGuard],
|
||||
exports: [firebase_service_1.FirebaseService, auth_guard_1.AuthGuard],
|
||||
imports: [
|
||||
prisma_module_1.PrismaModule,
|
||||
passport_1.PassportModule,
|
||||
(0, common_1.forwardRef)(() => otp_module_1.OtpModule),
|
||||
jwt_1.JwtModule.register({
|
||||
secret: process.env.JWT_SECRET || 'your-secret-key',
|
||||
signOptions: { expiresIn: '7d' },
|
||||
}),
|
||||
],
|
||||
controllers: [auth_controller_1.AuthController],
|
||||
providers: [auth_service_1.AuthService, jwt_strategy_1.JwtStrategy, google_strategy_1.GoogleStrategy],
|
||||
exports: [auth_service_1.AuthService],
|
||||
})
|
||||
], AuthModule);
|
||||
//# sourceMappingURL=auth.module.js.map
|
||||
2
apps/api/dist/auth/auth.module.js.map
vendored
2
apps/api/dist/auth/auth.module.js.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,yDAAqD;AACrD,6CAAyC;AAMlC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAJtB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,kCAAe,EAAE,sBAAS,CAAC;QACvC,OAAO,EAAE,CAAC,kCAAe,EAAE,sBAAS,CAAC;KACtC,CAAC;GACW,UAAU,CAAG"}
|
||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,qCAAwC;AACxC,+CAAkD;AAClD,uDAAmD;AACnD,iDAA6C;AAC7C,iDAA6C;AAC7C,uDAAmD;AACnD,2DAAuD;AACvD,kDAA8C;AAgBvC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAdtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,4BAAY;YACZ,yBAAc;YACd,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,sBAAS,CAAC;YAC3B,eAAS,CAAC,QAAQ,CAAC;gBACjB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,iBAAiB;gBACnD,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;aACjC,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,EAAE,0BAAW,EAAE,gCAAc,CAAC;QACrD,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"}
|
||||
93
apps/api/dist/auth/auth.service.d.ts
vendored
Normal file
93
apps/api/dist/auth/auth.service.d.ts
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { OtpService } from '../otp/otp.service';
|
||||
export declare class AuthService {
|
||||
private readonly prisma;
|
||||
private readonly jwtService;
|
||||
private readonly otpService;
|
||||
constructor(prisma: PrismaService, jwtService: JwtService, otpService: OtpService);
|
||||
register(email: string, password: string, name?: string): Promise<{
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
}>;
|
||||
login(email: string, password: string): Promise<{
|
||||
requiresOtp: boolean;
|
||||
availableMethods: {
|
||||
email: boolean;
|
||||
whatsapp: boolean;
|
||||
totp: boolean;
|
||||
};
|
||||
tempToken: string;
|
||||
user?: undefined;
|
||||
token?: undefined;
|
||||
} | {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
requiresOtp?: undefined;
|
||||
availableMethods?: undefined;
|
||||
tempToken?: undefined;
|
||||
}>;
|
||||
googleLogin(googleProfile: {
|
||||
googleId: string;
|
||||
email: string;
|
||||
name: string;
|
||||
avatarUrl?: string;
|
||||
}): Promise<{
|
||||
requiresOtp: boolean;
|
||||
availableMethods: {
|
||||
email: boolean;
|
||||
whatsapp: boolean;
|
||||
totp: boolean;
|
||||
};
|
||||
tempToken: string;
|
||||
user?: undefined;
|
||||
token?: undefined;
|
||||
} | {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
requiresOtp?: undefined;
|
||||
availableMethods?: undefined;
|
||||
tempToken?: undefined;
|
||||
}>;
|
||||
verifyOtpAndLogin(tempToken: string, otpCode: string, method: 'email' | 'whatsapp' | 'totp'): Promise<{
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
};
|
||||
token: string;
|
||||
}>;
|
||||
private generateToken;
|
||||
private generateTempToken;
|
||||
getUserProfile(userId: string): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
emailVerified: boolean;
|
||||
name: string | null;
|
||||
avatarUrl: string | null;
|
||||
}>;
|
||||
changePassword(userId: string, currentPassword: string, newPassword: string, isSettingPassword?: boolean): Promise<{
|
||||
message: string;
|
||||
}>;
|
||||
private downloadAndStoreAvatar;
|
||||
}
|
||||
404
apps/api/dist/auth/auth.service.js
vendored
Normal file
404
apps/api/dist/auth/auth.service.js
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
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 __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
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); }
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const prisma_service_1 = require("../prisma/prisma.service");
|
||||
const otp_service_1 = require("../otp/otp.service");
|
||||
const bcrypt = __importStar(require("bcrypt"));
|
||||
const fs = __importStar(require("fs"));
|
||||
const path = __importStar(require("path"));
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
let AuthService = class AuthService {
|
||||
prisma;
|
||||
jwtService;
|
||||
otpService;
|
||||
constructor(prisma, jwtService, otpService) {
|
||||
this.prisma = prisma;
|
||||
this.jwtService = jwtService;
|
||||
this.otpService = otpService;
|
||||
}
|
||||
async register(email, password, name) {
|
||||
const existing = await this.prisma.user.findUnique({ where: { email } });
|
||||
if (existing) {
|
||||
throw new common_1.ConflictException('Email already registered');
|
||||
}
|
||||
const passwordHash = await bcrypt.hash(password, 10);
|
||||
const user = await this.prisma.user.create({
|
||||
data: {
|
||||
email,
|
||||
passwordHash,
|
||||
name,
|
||||
emailVerified: false,
|
||||
},
|
||||
});
|
||||
const token = this.generateToken(user.id, user.email);
|
||||
return {
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
avatarUrl: user.avatarUrl,
|
||||
emailVerified: user.emailVerified,
|
||||
},
|
||||
token,
|
||||
};
|
||||
}
|
||||
async login(email, password) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { email },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
passwordHash: true,
|
||||
name: true,
|
||||
avatarUrl: true,
|
||||
emailVerified: true,
|
||||
otpEmailEnabled: true,
|
||||
otpWhatsappEnabled: true,
|
||||
otpTotpEnabled: true,
|
||||
},
|
||||
});
|
||||
if (!user || !user.passwordHash) {
|
||||
throw new common_1.UnauthorizedException('Invalid credentials');
|
||||
}
|
||||
const isValid = await bcrypt.compare(password, user.passwordHash);
|
||||
if (!isValid) {
|
||||
throw new common_1.UnauthorizedException('Invalid credentials');
|
||||
}
|
||||
const requiresOtp = user.otpEmailEnabled || user.otpWhatsappEnabled || user.otpTotpEnabled;
|
||||
if (requiresOtp) {
|
||||
if (user.otpEmailEnabled) {
|
||||
try {
|
||||
await this.otpService.sendEmailOtp(user.id);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to send email OTP during login:', error);
|
||||
}
|
||||
}
|
||||
if (user.otpWhatsappEnabled) {
|
||||
try {
|
||||
await this.otpService.sendWhatsappOtp(user.id, 'live');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to send WhatsApp OTP during login:', error);
|
||||
}
|
||||
}
|
||||
return {
|
||||
requiresOtp: true,
|
||||
availableMethods: {
|
||||
email: user.otpEmailEnabled,
|
||||
whatsapp: user.otpWhatsappEnabled,
|
||||
totp: user.otpTotpEnabled,
|
||||
},
|
||||
tempToken: this.generateTempToken(user.id, user.email),
|
||||
};
|
||||
}
|
||||
const token = this.generateToken(user.id, user.email);
|
||||
return {
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
avatarUrl: user.avatarUrl,
|
||||
emailVerified: user.emailVerified,
|
||||
},
|
||||
token,
|
||||
};
|
||||
}
|
||||
async googleLogin(googleProfile) {
|
||||
let user = await this.prisma.user.findUnique({
|
||||
where: { email: googleProfile.email },
|
||||
});
|
||||
if (!user) {
|
||||
user = await this.prisma.user.create({
|
||||
data: {
|
||||
email: googleProfile.email,
|
||||
name: googleProfile.name,
|
||||
avatarUrl: googleProfile.avatarUrl,
|
||||
emailVerified: true,
|
||||
authAccounts: {
|
||||
create: {
|
||||
provider: 'google',
|
||||
issuer: 'google.com',
|
||||
subject: googleProfile.googleId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
const existingAuth = await this.prisma.authAccount.findUnique({
|
||||
where: {
|
||||
issuer_subject: {
|
||||
issuer: 'google.com',
|
||||
subject: googleProfile.googleId,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!existingAuth) {
|
||||
await this.prisma.authAccount.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
provider: 'google',
|
||||
issuer: 'google.com',
|
||||
subject: googleProfile.googleId,
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log('Updating user with Google profile:', {
|
||||
name: googleProfile.name,
|
||||
avatarUrl: googleProfile.avatarUrl,
|
||||
});
|
||||
let avatarUrl = user.avatarUrl;
|
||||
if (googleProfile.avatarUrl) {
|
||||
try {
|
||||
avatarUrl = await this.downloadAndStoreAvatar(googleProfile.avatarUrl, user.id);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to download avatar:', error);
|
||||
avatarUrl = googleProfile.avatarUrl;
|
||||
}
|
||||
}
|
||||
user = await this.prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: {
|
||||
name: googleProfile.name || user.name,
|
||||
avatarUrl: avatarUrl || user.avatarUrl,
|
||||
emailVerified: true,
|
||||
},
|
||||
});
|
||||
console.log('User updated, avatar:', user.avatarUrl);
|
||||
}
|
||||
const requiresOtp = user.otpEmailEnabled || user.otpWhatsappEnabled || user.otpTotpEnabled;
|
||||
if (requiresOtp) {
|
||||
if (user.otpEmailEnabled) {
|
||||
try {
|
||||
await this.otpService.sendEmailOtp(user.id);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to send email OTP during Google login:', error);
|
||||
}
|
||||
}
|
||||
if (user.otpWhatsappEnabled) {
|
||||
try {
|
||||
await this.otpService.sendWhatsappOtp(user.id, 'live');
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to send WhatsApp OTP during Google login:', error);
|
||||
}
|
||||
}
|
||||
return {
|
||||
requiresOtp: true,
|
||||
availableMethods: {
|
||||
email: user.otpEmailEnabled,
|
||||
whatsapp: user.otpWhatsappEnabled,
|
||||
totp: user.otpTotpEnabled,
|
||||
},
|
||||
tempToken: this.generateTempToken(user.id, user.email),
|
||||
};
|
||||
}
|
||||
const token = this.generateToken(user.id, user.email);
|
||||
return {
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
avatarUrl: user.avatarUrl,
|
||||
emailVerified: user.emailVerified,
|
||||
},
|
||||
token,
|
||||
};
|
||||
}
|
||||
async verifyOtpAndLogin(tempToken, otpCode, method) {
|
||||
let payload;
|
||||
try {
|
||||
payload = this.jwtService.verify(tempToken);
|
||||
}
|
||||
catch {
|
||||
throw new common_1.UnauthorizedException('Invalid or expired token');
|
||||
}
|
||||
if (!payload.temp) {
|
||||
throw new common_1.UnauthorizedException('Invalid token type');
|
||||
}
|
||||
const userId = payload.userId || payload.sub;
|
||||
const email = payload.email;
|
||||
if (!userId || !email) {
|
||||
throw new common_1.UnauthorizedException('Invalid token payload');
|
||||
}
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
});
|
||||
if (!user) {
|
||||
throw new common_1.UnauthorizedException('User not found');
|
||||
}
|
||||
if (method === 'email') {
|
||||
const isValid = this.otpService.verifyEmailOtpForLogin(userId, otpCode);
|
||||
if (!isValid) {
|
||||
throw new common_1.UnauthorizedException('Invalid or expired email OTP code');
|
||||
}
|
||||
}
|
||||
else if (method === 'whatsapp') {
|
||||
const isValid = this.otpService.verifyWhatsappOtpForLogin(userId, otpCode);
|
||||
if (!isValid) {
|
||||
throw new common_1.UnauthorizedException('Invalid or expired WhatsApp OTP code');
|
||||
}
|
||||
}
|
||||
else if (method === 'totp') {
|
||||
if (!user.otpTotpSecret) {
|
||||
throw new common_1.UnauthorizedException('TOTP not set up');
|
||||
}
|
||||
const { authenticator } = await import('otplib');
|
||||
const isValid = authenticator.verify({
|
||||
token: otpCode,
|
||||
secret: user.otpTotpSecret,
|
||||
});
|
||||
if (!isValid) {
|
||||
throw new common_1.UnauthorizedException('Invalid TOTP code');
|
||||
}
|
||||
}
|
||||
const token = this.generateToken(userId, email);
|
||||
return {
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
avatarUrl: user.avatarUrl,
|
||||
emailVerified: user.emailVerified,
|
||||
},
|
||||
token,
|
||||
};
|
||||
}
|
||||
generateToken(userId, email) {
|
||||
return this.jwtService.sign({
|
||||
sub: userId,
|
||||
email,
|
||||
});
|
||||
}
|
||||
generateTempToken(userId, email) {
|
||||
return this.jwtService.sign({ userId, email, temp: true }, { expiresIn: '5m' });
|
||||
}
|
||||
async getUserProfile(userId) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
avatarUrl: true,
|
||||
emailVerified: true,
|
||||
},
|
||||
});
|
||||
if (!user) {
|
||||
throw new common_1.UnauthorizedException('User not found');
|
||||
}
|
||||
return user;
|
||||
}
|
||||
async changePassword(userId, currentPassword, newPassword, isSettingPassword) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { passwordHash: true },
|
||||
});
|
||||
if (!user) {
|
||||
throw new common_1.BadRequestException('User not found');
|
||||
}
|
||||
if (isSettingPassword && !user.passwordHash) {
|
||||
const newPasswordHash = await bcrypt.hash(newPassword, 10);
|
||||
await this.prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: { passwordHash: newPasswordHash },
|
||||
});
|
||||
return { message: 'Password set successfully' };
|
||||
}
|
||||
if (!user.passwordHash) {
|
||||
throw new common_1.BadRequestException('Cannot change password for this account');
|
||||
}
|
||||
const isValid = await bcrypt.compare(currentPassword, user.passwordHash);
|
||||
if (!isValid) {
|
||||
throw new common_1.UnauthorizedException('Current password is incorrect');
|
||||
}
|
||||
const newPasswordHash = await bcrypt.hash(newPassword, 10);
|
||||
await this.prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: { passwordHash: newPasswordHash },
|
||||
});
|
||||
return { message: 'Password changed successfully' };
|
||||
}
|
||||
async downloadAndStoreAvatar(avatarUrl, userId) {
|
||||
try {
|
||||
const uploadsDir = path.join(process.cwd(), 'public', 'avatars');
|
||||
if (!fs.existsSync(uploadsDir)) {
|
||||
fs.mkdirSync(uploadsDir, { recursive: true });
|
||||
}
|
||||
const response = await axios_1.default.get(avatarUrl, {
|
||||
responseType: 'arraybuffer',
|
||||
});
|
||||
const ext = 'jpg';
|
||||
const filename = `${userId}.${ext}`;
|
||||
const filepath = path.join(uploadsDir, filename);
|
||||
fs.writeFileSync(filepath, response.data);
|
||||
return `/avatars/${filename}`;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error downloading avatar:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.AuthService = AuthService;
|
||||
exports.AuthService = AuthService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(2, (0, common_1.Inject)((0, common_1.forwardRef)(() => otp_service_1.OtpService))),
|
||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
||||
jwt_1.JwtService,
|
||||
otp_service_1.OtpService])
|
||||
], AuthService);
|
||||
//# sourceMappingURL=auth.service.js.map
|
||||
1
apps/api/dist/auth/auth.service.js.map
vendored
Normal file
1
apps/api/dist/auth/auth.service.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
9
apps/api/dist/auth/firebase.service.d.ts
vendored
9
apps/api/dist/auth/firebase.service.d.ts
vendored
@@ -1,9 +0,0 @@
|
||||
import * as admin from 'firebase-admin';
|
||||
export declare class FirebaseService {
|
||||
private app;
|
||||
private isConfigured;
|
||||
constructor();
|
||||
verifyIdToken(idToken: string): Promise<admin.auth.DecodedIdToken>;
|
||||
getUser(uid: string): Promise<admin.auth.UserRecord>;
|
||||
isFirebaseConfigured(): boolean;
|
||||
}
|
||||
113
apps/api/dist/auth/firebase.service.js
vendored
113
apps/api/dist/auth/firebase.service.js
vendored
@@ -1,113 +0,0 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
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 __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
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.FirebaseService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const admin = __importStar(require("firebase-admin"));
|
||||
let FirebaseService = class FirebaseService {
|
||||
app = null;
|
||||
isConfigured = false;
|
||||
constructor() {
|
||||
const projectId = process.env.FIREBASE_PROJECT_ID;
|
||||
const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;
|
||||
const privateKey = process.env.FIREBASE_PRIVATE_KEY;
|
||||
if (projectId && clientEmail && privateKey) {
|
||||
try {
|
||||
if (!admin.apps.length) {
|
||||
this.app = admin.initializeApp({
|
||||
credential: admin.credential.cert({
|
||||
projectId,
|
||||
clientEmail,
|
||||
privateKey: privateKey.replace(/\\n/g, '\n'),
|
||||
}),
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.app = admin.app();
|
||||
}
|
||||
this.isConfigured = true;
|
||||
console.log('✅ Firebase Admin initialized successfully');
|
||||
}
|
||||
catch (error) {
|
||||
console.warn('⚠️ Firebase Admin initialization failed:', error.message);
|
||||
this.isConfigured = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.warn('⚠️ Firebase credentials not found. Auth will use fallback mode.');
|
||||
this.isConfigured = false;
|
||||
}
|
||||
}
|
||||
async verifyIdToken(idToken) {
|
||||
if (!this.isConfigured || !this.app) {
|
||||
throw new Error('Firebase not configured');
|
||||
}
|
||||
try {
|
||||
return await admin.auth().verifyIdToken(idToken);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error('Invalid token');
|
||||
}
|
||||
}
|
||||
async getUser(uid) {
|
||||
if (!this.isConfigured || !this.app) {
|
||||
throw new Error('Firebase not configured');
|
||||
}
|
||||
try {
|
||||
return await admin.auth().getUser(uid);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
}
|
||||
isFirebaseConfigured() {
|
||||
return this.isConfigured;
|
||||
}
|
||||
};
|
||||
exports.FirebaseService = FirebaseService;
|
||||
exports.FirebaseService = FirebaseService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [])
|
||||
], FirebaseService);
|
||||
//# sourceMappingURL=firebase.service.js.map
|
||||
1
apps/api/dist/auth/firebase.service.js.map
vendored
1
apps/api/dist/auth/firebase.service.js.map
vendored
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"firebase.service.js","sourceRoot":"","sources":["../../src/auth/firebase.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,sDAAwC;AAGjC,IAAM,eAAe,GAArB,MAAM,eAAe;IAClB,GAAG,GAAyB,IAAI,CAAC;IACjC,YAAY,GAAY,KAAK,CAAC;IAEtC;QAEE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAClD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACtD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QAEpD,IAAI,SAAS,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;YAC3C,IAAI,CAAC;gBACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACvB,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC;wBAC7B,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;4BAChC,SAAS;4BACT,WAAW;4BACX,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;yBAC7C,CAAC;qBACH,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;gBACzB,CAAC;gBACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBACxE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC5B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;YAChF,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe;QACjC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,oBAAoB;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF,CAAA;AA5DY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;;GACA,eAAe,CA4D3B"}
|
||||
9
apps/api/dist/auth/google.strategy.d.ts
vendored
Normal file
9
apps/api/dist/auth/google.strategy.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
|
||||
declare const GoogleStrategy_base: new (...args: [options: import("passport-google-oauth20").StrategyOptionsWithRequest] | [options: import("passport-google-oauth20").StrategyOptions] | [options: import("passport-google-oauth20").StrategyOptions] | [options: import("passport-google-oauth20").StrategyOptionsWithRequest]) => Strategy & {
|
||||
validate(...args: any[]): unknown;
|
||||
};
|
||||
export declare class GoogleStrategy extends GoogleStrategy_base {
|
||||
constructor();
|
||||
validate(accessToken: string, refreshToken: string, profile: any, done: VerifyCallback): Promise<any>;
|
||||
}
|
||||
export {};
|
||||
42
apps/api/dist/auth/google.strategy.js
vendored
Normal file
42
apps/api/dist/auth/google.strategy.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
"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.GoogleStrategy = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
const passport_google_oauth20_1 = require("passport-google-oauth20");
|
||||
let GoogleStrategy = class GoogleStrategy extends (0, passport_1.PassportStrategy)(passport_google_oauth20_1.Strategy, 'google') {
|
||||
constructor() {
|
||||
super({
|
||||
clientID: process.env.GOOGLE_CLIENT_ID || '',
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
|
||||
callbackURL: process.env.GOOGLE_CALLBACK_URL ||
|
||||
'http://localhost:3001/api/auth/google/callback',
|
||||
scope: ['email', 'profile'],
|
||||
});
|
||||
}
|
||||
async validate(accessToken, refreshToken, profile, done) {
|
||||
const { id, name, emails, photos } = profile;
|
||||
const user = {
|
||||
googleId: id,
|
||||
email: emails[0].value,
|
||||
name: name.givenName + ' ' + name.familyName,
|
||||
avatarUrl: photos[0]?.value,
|
||||
};
|
||||
done(null, user);
|
||||
}
|
||||
};
|
||||
exports.GoogleStrategy = GoogleStrategy;
|
||||
exports.GoogleStrategy = GoogleStrategy = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [])
|
||||
], GoogleStrategy);
|
||||
//# sourceMappingURL=google.strategy.js.map
|
||||
1
apps/api/dist/auth/google.strategy.js.map
vendored
Normal file
1
apps/api/dist/auth/google.strategy.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"google.strategy.js","sourceRoot":"","sources":["../../src/auth/google.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAoD;AACpD,qEAAmE;AAG5D,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,IAAA,2BAAgB,EAAC,kCAAQ,EAAE,QAAQ,CAAC;IACtE;QACE,KAAK,CAAC;YACJ,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;YAC5C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;YACpD,WAAW,EACT,OAAO,CAAC,GAAG,CAAC,mBAAmB;gBAC/B,gDAAgD;YAClD,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,WAAmB,EACnB,YAAoB,EACpB,OAAY,EACZ,IAAoB;QAEpB,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAE7C,MAAM,IAAI,GAAG;YACX,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU;YAC5C,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK;SAC5B,CAAC;QAEF,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnB,CAAC;CACF,CAAA;AA7BY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;;GACA,cAAc,CA6B1B"}
|
||||
18
apps/api/dist/auth/jwt.strategy.d.ts
vendored
Normal file
18
apps/api/dist/auth/jwt.strategy.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Strategy } from 'passport-jwt';
|
||||
export interface JwtPayload {
|
||||
sub: string;
|
||||
email: string;
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
||||
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();
|
||||
validate(payload: JwtPayload): Promise<{
|
||||
userId: string;
|
||||
email: string;
|
||||
}>;
|
||||
}
|
||||
export {};
|
||||
33
apps/api/dist/auth/jwt.strategy.js
vendored
Normal file
33
apps/api/dist/auth/jwt.strategy.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
"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 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() {
|
||||
super({
|
||||
jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: process.env.JWT_SECRET || 'your-secret-key-change-this',
|
||||
});
|
||||
}
|
||||
async validate(payload) {
|
||||
return { userId: payload.sub, email: payload.email };
|
||||
}
|
||||
};
|
||||
exports.JwtStrategy = JwtStrategy;
|
||||
exports.JwtStrategy = JwtStrategy = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [])
|
||||
], JwtStrategy);
|
||||
//# sourceMappingURL=jwt.strategy.js.map
|
||||
1
apps/api/dist/auth/jwt.strategy.js.map
vendored
Normal file
1
apps/api/dist/auth/jwt.strategy.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/auth/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAoD;AACpD,+CAAoD;AAU7C,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,2BAAgB,EAAC,uBAAQ,CAAC;IACzD;QACE,KAAK,CAAC;YACJ,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,6BAA6B;SACrE,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAmB;QAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;IACvD,CAAC;CACF,CAAA;AAZY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;;GACA,WAAW,CAYvB"}
|
||||
Reference in New Issue
Block a user