Compare commits
68
Commits
main
...
aa2b9f131f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa2b9f131f | ||
|
|
17e8f8eeac | ||
|
|
5e3be672ee | ||
|
|
c10fd2396c | ||
|
|
4a7859f4c2 | ||
|
|
7216d86740 | ||
|
|
96b22d1fc0 | ||
|
|
8a0cf35116 | ||
|
|
ad4b5d991c | ||
|
|
ff97821fd0 | ||
|
|
398daceffb | ||
|
|
0849b7b53c | ||
|
|
f14d40dac7 | ||
|
|
7572d6b4c5 | ||
|
|
e1e634fcb3 | ||
|
|
429496dd3c | ||
|
|
d7119a53eb | ||
|
|
50ecf9bfbf | ||
|
|
9e65afae59 | ||
|
|
81d88ee770 | ||
|
|
431d1f95ff | ||
|
|
4f6595b1eb | ||
|
|
52a912380f | ||
|
|
06895d6720 | ||
|
|
313c2f641f | ||
|
|
956dae8e75 | ||
|
|
b98ce56622 | ||
|
|
3d13d31101 | ||
|
|
470d6d959d | ||
|
|
aa2967964f | ||
|
|
ad231c6f20 | ||
|
|
9088af0534 | ||
|
|
fc4be2b8fd | ||
|
|
3109d782d3 | ||
|
|
ac4a74d0e0 | ||
|
|
c28d7f236e | ||
|
|
0d21c1bfbf | ||
|
|
bab24892c7 | ||
|
|
cb384765fb | ||
|
|
8375773898 | ||
|
|
5d813f3a3f | ||
|
|
f1e31cb721 | ||
|
|
13ff137359 | ||
|
|
c9b3249aa5 | ||
|
|
ba4ae15eab | ||
|
|
0a854c4302 | ||
|
|
57e3da7ea4 | ||
|
|
06543ee8e0 | ||
|
|
ba2f211438 | ||
|
|
c35f6e61f2 | ||
|
|
b039281972 | ||
|
|
b1ee482830 | ||
|
|
6bd0bc0ce5 | ||
|
|
91c36d99c9 | ||
|
|
23dde3c8e3 | ||
|
|
97b8b27ddf | ||
|
|
2691eb68eb | ||
|
|
9247499f50 | ||
|
|
941420f5c0 | ||
|
|
bd287d155b | ||
|
|
a0a5a09135 | ||
|
|
03cdc6fe9c | ||
|
|
b3ffa7c71d | ||
|
|
844774bd1b | ||
|
|
126761004c | ||
|
|
8061f3e7a3 | ||
|
|
3136a2b7aa | ||
|
|
32865e78df |
@@ -1,9 +0,0 @@
|
||||
Downloading Syria map data...
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
␍ 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0␍100 239 100 239 0 0 829 0 --:--:-- --:--:-- --:--:-- 829
|
||||
Warning: Failed to open the file
|
||||
Warning: /home/hamzadoctor/app/infrastructure/osm-data/syria-latest.osm.pbf:
|
||||
Warning: No such file or directory
|
||||
␍ 0 73.8M 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
|
||||
curl: (23) Failure writing output to destination, passed 4096 returned 4294967295
|
||||
+56
-11
@@ -1,28 +1,39 @@
|
||||
# Database Dumps
|
||||
# Database Dumps & Archives
|
||||
*.sql
|
||||
*.tar.gz
|
||||
*.zip
|
||||
*.mbtiles
|
||||
|
||||
# Node modules
|
||||
node_modules/
|
||||
.npm/
|
||||
# Node modules and Web build output
|
||||
**/node_modules/
|
||||
**/dist/
|
||||
**/.npm/
|
||||
**/.npm-cache/
|
||||
*.tsbuildinfo
|
||||
|
||||
# Environment Variables
|
||||
# Environment Variables & Secrets
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.key
|
||||
*.pem
|
||||
|
||||
# Virtual Environments
|
||||
# Python Virtual Environments
|
||||
venv/
|
||||
venv_overture/
|
||||
.venv/
|
||||
.venv*/
|
||||
env/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Map Data
|
||||
# Map Data & Intermediate Geodata
|
||||
*.osm.pbf
|
||||
*.pbf
|
||||
infrastructure/osm-data/default-gh/
|
||||
apps/.npm-cache/
|
||||
*.json.bak
|
||||
apps/api/src/telemetry/*.json
|
||||
**/dem_tiles/
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
@@ -32,6 +43,40 @@ apps/api/src/telemetry/*.json
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.venv-osm/
|
||||
__pycache__/
|
||||
infrastructure/osm-data/*.orig
|
||||
|
||||
# IDE & Editor files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Flutter / Dart Mobile SDKs (all packages)
|
||||
**/.dart_tool/
|
||||
**/.flutter-plugins
|
||||
**/.flutter-plugins-dependencies
|
||||
**/.packages
|
||||
**/.pub-cache/
|
||||
**/.pub/
|
||||
**/build/
|
||||
**/coverage/
|
||||
|
||||
# Android build artifacts
|
||||
**/.gradle/
|
||||
**/android/.gradle/
|
||||
**/android/app/build/
|
||||
**/android/app/debug/
|
||||
**/android/app/release/
|
||||
**/android/app/profile/
|
||||
*.apk
|
||||
*.aab
|
||||
|
||||
# iOS build artifacts
|
||||
**/ios/Pods/
|
||||
**/ios/.symlinks/
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/.last_build_id
|
||||
**/ios/DerivedData/
|
||||
*.ipa
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.git/
|
||||
.github/
|
||||
.idea/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
node_modules/
|
||||
build/
|
||||
.dart_tool/
|
||||
.gradle/
|
||||
Pods/
|
||||
.symlinks/
|
||||
*.apk
|
||||
*.aab
|
||||
*.ipa
|
||||
dem_tiles/
|
||||
infrastructure/osm-data/
|
||||
osm-data/
|
||||
venv/
|
||||
.venv*/
|
||||
dist/
|
||||
.npm/
|
||||
.npm-cache/
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
import { AppService } from './app.service';
|
||||
export declare class AppController {
|
||||
private readonly appService;
|
||||
constructor(appService: AppService);
|
||||
getHello(): string;
|
||||
}
|
||||
Vendored
-35
@@ -1,35 +0,0 @@
|
||||
"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.AppController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const app_service_1 = require("./app.service");
|
||||
let AppController = class AppController {
|
||||
appService;
|
||||
constructor(appService) {
|
||||
this.appService = appService;
|
||||
}
|
||||
getHello() {
|
||||
return this.appService.getHello();
|
||||
}
|
||||
};
|
||||
exports.AppController = AppController;
|
||||
__decorate([
|
||||
(0, common_1.Get)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", String)
|
||||
], AppController.prototype, "getHello", null);
|
||||
exports.AppController = AppController = __decorate([
|
||||
(0, common_1.Controller)(),
|
||||
__metadata("design:paramtypes", [app_service_1.AppService])
|
||||
], AppController);
|
||||
//# sourceMappingURL=app.controller.js.map
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiD;AACjD,+CAA2C;AAGpC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACK;IAA7B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAGvD,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;CACF,CAAA;AAPY,sCAAa;AAIxB;IADC,IAAA,YAAG,GAAE;;;;6CAGL;wBANU,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,aAAa,CAOzB"}
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
export declare class AppModule {
|
||||
}
|
||||
Vendored
-65
@@ -1,65 +0,0 @@
|
||||
"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.AppModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const core_1 = require("@nestjs/core");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const schedule_1 = require("@nestjs/schedule");
|
||||
const telemetry_module_1 = require("./telemetry/telemetry.module");
|
||||
const maps_module_1 = require("./maps/maps.module");
|
||||
const geocoding_module_1 = require("./geocoding/geocoding.module");
|
||||
const auth_module_1 = require("./auth/auth.module");
|
||||
const throttler_1 = require("@nestjs/throttler");
|
||||
const usage_module_1 = require("./usage/usage.module");
|
||||
const billing_module_1 = require("./billing/billing.module");
|
||||
const mail_module_1 = require("./common/mail.module");
|
||||
const usage_interceptor_1 = require("./usage/usage.interceptor");
|
||||
let AppModule = class AppModule {
|
||||
};
|
||||
exports.AppModule = AppModule;
|
||||
exports.AppModule = AppModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
config_1.ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
schedule_1.ScheduleModule.forRoot(),
|
||||
typeorm_1.TypeOrmModule.forRootAsync({
|
||||
imports: [config_1.ConfigModule],
|
||||
inject: [config_1.ConfigService],
|
||||
useFactory: (config) => ({
|
||||
type: 'postgres',
|
||||
url: config.get('DATABASE_URL'),
|
||||
autoLoadEntities: true,
|
||||
synchronize: false,
|
||||
}),
|
||||
}),
|
||||
throttler_1.ThrottlerModule.forRoot([{
|
||||
ttl: 60000,
|
||||
limit: 10,
|
||||
}]),
|
||||
auth_module_1.AuthModule,
|
||||
telemetry_module_1.TelemetryModule,
|
||||
maps_module_1.MapsModule,
|
||||
geocoding_module_1.GeocodingModule,
|
||||
usage_module_1.UsageModule,
|
||||
billing_module_1.BillingModule,
|
||||
mail_module_1.MailModule,
|
||||
],
|
||||
controllers: [],
|
||||
providers: [
|
||||
{
|
||||
provide: core_1.APP_INTERCEPTOR,
|
||||
useClass: usage_interceptor_1.UsageInterceptor,
|
||||
},
|
||||
],
|
||||
})
|
||||
], AppModule);
|
||||
//# sourceMappingURL=app.module.js.map
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uCAA0D;AAC1D,2CAA6D;AAC7D,6CAAgD;AAChD,+CAAkD;AAClD,mEAA+D;AAC/D,oDAAgD;AAChD,mEAA+D;AAC/D,oDAAgD;AAChD,iDAAoD;AACpD,uDAAmD;AACnD,6DAAyD;AACzD,sDAAkD;AAClD,iEAA6D;AAsCtD,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IApCrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,qBAAY,CAAC,OAAO,CAAC;gBACnB,QAAQ,EAAE,IAAI;aACf,CAAC;YACF,yBAAc,CAAC,OAAO,EAAE;YACxB,uBAAa,CAAC,YAAY,CAAC;gBACzB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,MAAM,EAAE,CAAC,sBAAa,CAAC;gBACvB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE,CAAC,CAAC;oBACtC,IAAI,EAAE,UAAU;oBAChB,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;oBAC/B,gBAAgB,EAAE,IAAI;oBACtB,WAAW,EAAE,KAAK;iBACnB,CAAC;aACH,CAAC;YACF,2BAAe,CAAC,OAAO,CAAC,CAAC;oBACvB,GAAG,EAAE,KAAK;oBACV,KAAK,EAAE,EAAE;iBACV,CAAC,CAAC;YACH,wBAAU;YACV,kCAAe;YACf,wBAAU;YACV,kCAAe;YACf,0BAAW;YACX,8BAAa;YACb,wBAAU;SACX;QACD,WAAW,EAAE,EAAE;QACf,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,sBAAe;gBACxB,QAAQ,EAAE,oCAAgB;aAC3B;SACF;KACF,CAAC;GACW,SAAS,CAAG"}
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
export declare class AppService {
|
||||
getHello(): string;
|
||||
}
|
||||
Vendored
-20
@@ -1,20 +0,0 @@
|
||||
"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.AppService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
let AppService = class AppService {
|
||||
getHello() {
|
||||
return 'Hello World!';
|
||||
}
|
||||
};
|
||||
exports.AppService = AppService;
|
||||
exports.AppService = AppService = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], AppService);
|
||||
//# sourceMappingURL=app.service.js.map
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"app.service.js","sourceRoot":"","sources":["../src/app.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAGrC,IAAM,UAAU,GAAhB,MAAM,UAAU;IACrB,QAAQ;QACN,OAAO,cAAc,CAAC;IACxB,CAAC;CACF,CAAA;AAJY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;GACA,UAAU,CAItB"}
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
import { OnModuleInit } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class AuthModule implements OnModuleInit {
|
||||
private readonly authService;
|
||||
private readonly configService;
|
||||
constructor(authService: AuthService, configService: ConfigService);
|
||||
onModuleInit(): Promise<void>;
|
||||
}
|
||||
Vendored
-53
@@ -1,53 +0,0 @@
|
||||
"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 _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
const tenant_entity_1 = require("./entities/tenant.entity");
|
||||
const api_key_entity_1 = require("./entities/api-key.entity");
|
||||
const redis_module_1 = require("../common/redis.module");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const tenant_controller_1 = require("./tenant.controller");
|
||||
const firebase_admin_service_1 = require("./firebase-admin.service");
|
||||
const firebase_auth_guard_1 = require("./guards/firebase-auth.guard");
|
||||
let AuthModule = class AuthModule {
|
||||
authService;
|
||||
configService;
|
||||
constructor(authService, configService) {
|
||||
this.authService = authService;
|
||||
this.configService = configService;
|
||||
}
|
||||
async onModuleInit() {
|
||||
const defaultKey = this.configService.get('MAP_API_KEY');
|
||||
if (defaultKey) {
|
||||
await this.authService.seedDefaultKey('Default System', 'admin@intaleq.xyz', defaultKey);
|
||||
console.log('✅ Default System API Key seeded successfully');
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.AuthModule = AuthModule;
|
||||
exports.AuthModule = AuthModule = __decorate([
|
||||
(0, common_1.Global)(),
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
typeorm_1.TypeOrmModule.forFeature([tenant_entity_1.Tenant, api_key_entity_1.ApiKey]),
|
||||
redis_module_1.RedisModule,
|
||||
],
|
||||
controllers: [tenant_controller_1.TenantController],
|
||||
providers: [auth_service_1.AuthService, firebase_admin_service_1.FirebaseAdminService, firebase_auth_guard_1.FirebaseAuthGuard],
|
||||
exports: [auth_service_1.AuthService, firebase_admin_service_1.FirebaseAdminService, firebase_auth_guard_1.FirebaseAuthGuard],
|
||||
}),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService, typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], AuthModule);
|
||||
//# sourceMappingURL=auth.module.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA8D;AAC9D,6CAAgD;AAChD,iDAA6C;AAC7C,4DAAkD;AAClD,8DAAmD;AACnD,yDAAqD;AACrD,2CAA+C;AAC/C,2DAAuD;AACvD,qEAAgE;AAChE,sEAAiE;AAY1D,IAAM,UAAU,GAAhB,MAAM,UAAU;IAEF;IACA;IAFnB,YACmB,WAAwB,EACxB,aAA4B;QAD5B,gBAAW,GAAX,WAAW,CAAa;QACxB,kBAAa,GAAb,aAAa,CAAe;IAC5C,CAAC;IAMJ,KAAK,CAAC,YAAY;QAChB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,aAAa,CAAC,CAAC;QACjE,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;YACzF,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;CACF,CAAA;AAjBY,gCAAU;qBAAV,UAAU;IAVtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC,CAAC,sBAAM,EAAE,uBAAM,CAAC,CAAC;YAC1C,0BAAW;SACZ;QACD,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE,CAAC,0BAAW,EAAE,6CAAoB,EAAE,uCAAiB,CAAC;QACjE,OAAO,EAAE,CAAC,0BAAW,EAAE,6CAAoB,EAAE,uCAAiB,CAAC;KAChE,CAAC;qCAGgC,0BAAW,sBACT,sBAAa,oBAAb,sBAAa;GAHpC,UAAU,CAiBtB"}
|
||||
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
import { Repository } from 'typeorm';
|
||||
import { ApiKey } from './entities/api-key.entity';
|
||||
import { Tenant } from './entities/tenant.entity';
|
||||
import { RedisService } from '../common/redis.service';
|
||||
export declare class AuthService {
|
||||
private readonly apiKeyRepository;
|
||||
private readonly tenantRepository;
|
||||
private readonly redisService;
|
||||
private readonly logger;
|
||||
constructor(apiKeyRepository: Repository<ApiKey>, tenantRepository: Repository<Tenant>, redisService: RedisService);
|
||||
validateApiKey(key: string, origin?: string, referer?: string): Promise<{
|
||||
tenant: Tenant;
|
||||
apiKey: ApiKey;
|
||||
rateLimit: number;
|
||||
}>;
|
||||
private validateRestrictions;
|
||||
private isDomainAllowed;
|
||||
hashSecret(secret: string): string;
|
||||
seedDefaultKey(name: string, email: string, keyString: string): Promise<void>;
|
||||
getApiKeys(tenantId: string): Promise<ApiKey[]>;
|
||||
createApiKey(tenantId: string, name: string, rateLimit?: number, allowedOrigins?: string[]): Promise<ApiKey>;
|
||||
getDefaultTenant(): Promise<Tenant>;
|
||||
findOrCreateByFirebaseUid(uid: string, email: string, name: string, photoUrl?: string): Promise<Tenant>;
|
||||
}
|
||||
Vendored
-180
@@ -1,180 +0,0 @@
|
||||
"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); }
|
||||
};
|
||||
var AuthService_1;
|
||||
var _a, _b;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const crypto_1 = require("crypto");
|
||||
const api_key_entity_1 = require("./entities/api-key.entity");
|
||||
const tenant_entity_1 = require("./entities/tenant.entity");
|
||||
const redis_service_1 = require("../common/redis.service");
|
||||
let AuthService = AuthService_1 = class AuthService {
|
||||
apiKeyRepository;
|
||||
tenantRepository;
|
||||
redisService;
|
||||
logger = new common_1.Logger(AuthService_1.name);
|
||||
constructor(apiKeyRepository, tenantRepository, redisService) {
|
||||
this.apiKeyRepository = apiKeyRepository;
|
||||
this.tenantRepository = tenantRepository;
|
||||
this.redisService = redisService;
|
||||
}
|
||||
async validateApiKey(key, origin, referer) {
|
||||
const cacheKey = `auth:apikey:${key}`;
|
||||
const cachedData = await this.redisService.get(cacheKey);
|
||||
if (cachedData) {
|
||||
this.validateRestrictions(cachedData.apiKey, origin, referer);
|
||||
return cachedData;
|
||||
}
|
||||
const apiKey = await this.apiKeyRepository.findOne({
|
||||
where: { key, isActive: true },
|
||||
relations: ['tenant'],
|
||||
});
|
||||
if (!apiKey || !apiKey.tenant || !apiKey.tenant.isActive) {
|
||||
throw new common_1.UnauthorizedException('Invalid or inactive API Key');
|
||||
}
|
||||
this.validateRestrictions(apiKey, origin, referer);
|
||||
const result = {
|
||||
tenant: apiKey.tenant,
|
||||
apiKey: apiKey,
|
||||
rateLimit: apiKey.rateLimit || tenant_entity_1.RATE_LIMITS[apiKey.tenant.plan] || 100,
|
||||
};
|
||||
await this.redisService.set(cacheKey, result, 3600);
|
||||
this.apiKeyRepository.update(apiKey.id, { lastUsedAt: new Date() }).catch(err => this.logger.error(`Failed to update lastUsedAt for API key ${apiKey.id}: ${err.message}`));
|
||||
return result;
|
||||
}
|
||||
validateRestrictions(apiKey, origin, referer) {
|
||||
if (apiKey.allowedOrigins && apiKey.allowedOrigins.length > 0) {
|
||||
if (!origin || !this.isDomainAllowed(origin, apiKey.allowedOrigins)) {
|
||||
this.logger.warn(`Origin mismatch for API key ${apiKey.id}. Received: ${origin}`);
|
||||
throw new common_1.UnauthorizedException('Request Origin not allowed for this API Key');
|
||||
}
|
||||
}
|
||||
if (apiKey.allowedReferrers && apiKey.allowedReferrers.length > 0) {
|
||||
if (!referer || !this.isDomainAllowed(referer, apiKey.allowedReferrers)) {
|
||||
this.logger.warn(`Referer mismatch for API key ${apiKey.id}. Received: ${referer}`);
|
||||
throw new common_1.UnauthorizedException('Request Referer not allowed for this API Key');
|
||||
}
|
||||
}
|
||||
}
|
||||
isDomainAllowed(domain, allowedList) {
|
||||
const cleanDomain = domain.replace(/^https?:\/\//, '').split('/')[0];
|
||||
return allowedList.some(allowed => {
|
||||
if (allowed === '*')
|
||||
return true;
|
||||
const regex = new RegExp('^' + allowed.replace(/\*/g, '.*') + '$');
|
||||
return regex.test(cleanDomain);
|
||||
});
|
||||
}
|
||||
hashSecret(secret) {
|
||||
return (0, crypto_1.createHash)('sha256').update(secret).digest('hex');
|
||||
}
|
||||
async seedDefaultKey(name, email, keyString) {
|
||||
let tenant = await this.tenantRepository.findOne({ where: { email } });
|
||||
if (!tenant) {
|
||||
tenant = await this.tenantRepository.save({
|
||||
name,
|
||||
email,
|
||||
isActive: true,
|
||||
plan: tenant_entity_1.TenantPlan.ENTERPRISE,
|
||||
});
|
||||
}
|
||||
const existingKey = await this.apiKeyRepository.findOne({ where: { key: keyString } });
|
||||
if (!existingKey) {
|
||||
await this.apiKeyRepository.save({
|
||||
key: keyString,
|
||||
secretHash: this.hashSecret(keyString),
|
||||
name: 'Default Production Key',
|
||||
isActive: true,
|
||||
tenantId: tenant.id,
|
||||
rateLimit: 1000
|
||||
});
|
||||
}
|
||||
}
|
||||
async getApiKeys(tenantId) {
|
||||
return this.apiKeyRepository.find({
|
||||
where: { tenantId },
|
||||
order: { createdAt: 'DESC' }
|
||||
});
|
||||
}
|
||||
async createApiKey(tenantId, name, rateLimit, allowedOrigins) {
|
||||
const existingKeysCount = await this.apiKeyRepository.count({ where: { tenantId } });
|
||||
if (existingKeysCount >= 1) {
|
||||
throw new common_1.ConflictException('Limit reached: Only 1 API key allowed per developer currently.');
|
||||
}
|
||||
const key = `in_${(0, crypto_1.createHash)('md5').update(Math.random().toString()).digest('hex').substring(0, 24)}`;
|
||||
const apiKey = this.apiKeyRepository.create({
|
||||
key,
|
||||
secretHash: this.hashSecret(key),
|
||||
name,
|
||||
tenantId,
|
||||
rateLimit: rateLimit || 100,
|
||||
allowedOrigins: allowedOrigins || [],
|
||||
isActive: true
|
||||
});
|
||||
return this.apiKeyRepository.save(apiKey);
|
||||
}
|
||||
async getDefaultTenant() {
|
||||
const tenant = await this.tenantRepository.findOne({ where: {} });
|
||||
if (!tenant)
|
||||
throw new common_1.NotFoundException('No tenants found in system');
|
||||
return tenant;
|
||||
}
|
||||
async findOrCreateByFirebaseUid(uid, email, name, photoUrl) {
|
||||
let tenant = await this.tenantRepository.findOne({ where: { firebaseUid: uid } });
|
||||
if (!tenant) {
|
||||
tenant = await this.tenantRepository.findOne({ where: { email } });
|
||||
if (tenant) {
|
||||
this.logger.log(`Linking existing tenant ${email} to Firebase UID: ${uid}`);
|
||||
tenant.firebaseUid = uid;
|
||||
if (photoUrl)
|
||||
tenant.photoUrl = photoUrl;
|
||||
tenant = await this.tenantRepository.save(tenant);
|
||||
}
|
||||
else {
|
||||
this.logger.log(`Creating new tenant for Firebase user: ${email} (${uid})`);
|
||||
const isAdmin = email === 'hamzaaleghwairyeen@gmail.com' || email === 'hamzadoctor@gmail.com' || email === 'hamzaayedpython@gmail.com';
|
||||
tenant = await this.tenantRepository.save({
|
||||
firebaseUid: uid,
|
||||
email,
|
||||
name,
|
||||
photoUrl,
|
||||
plan: isAdmin ? tenant_entity_1.TenantPlan.ENTERPRISE : tenant_entity_1.TenantPlan.FREE,
|
||||
isActive: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
const isAdmin = email === 'hamzaaleghwairyeen@gmail.com' || email === 'hamzadoctor@gmail.com' || email === 'hamzaayedpython@gmail.com';
|
||||
if (isAdmin && tenant.plan !== tenant_entity_1.TenantPlan.ENTERPRISE) {
|
||||
tenant.plan = tenant_entity_1.TenantPlan.ENTERPRISE;
|
||||
await this.tenantRepository.save(tenant);
|
||||
}
|
||||
if (tenant.photoUrl !== photoUrl || tenant.name !== name) {
|
||||
await this.tenantRepository.update(tenant.id, { photoUrl, name });
|
||||
}
|
||||
}
|
||||
return tenant;
|
||||
}
|
||||
};
|
||||
exports.AuthService = AuthService;
|
||||
exports.AuthService = AuthService = AuthService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(api_key_entity_1.ApiKey)),
|
||||
__param(1, (0, typeorm_1.InjectRepository)(tenant_entity_1.Tenant)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, redis_service_1.RedisService])
|
||||
], AuthService);
|
||||
//# sourceMappingURL=auth.service.js.map
|
||||
-1
File diff suppressed because one or more lines are too long
@@ -1,5 +0,0 @@
|
||||
export declare class CreateKeyDto {
|
||||
name: string;
|
||||
rateLimit?: number;
|
||||
allowedOrigins?: string[];
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
"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.CreateKeyDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class CreateKeyDto {
|
||||
name;
|
||||
rateLimit;
|
||||
allowedOrigins;
|
||||
}
|
||||
exports.CreateKeyDto = CreateKeyDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
__metadata("design:type", String)
|
||||
], CreateKeyDto.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
__metadata("design:type", Number)
|
||||
], CreateKeyDto.prototype, "rateLimit", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsArray)(),
|
||||
(0, class_validator_1.IsString)({ each: true }),
|
||||
__metadata("design:type", Array)
|
||||
], CreateKeyDto.prototype, "allowedOrigins", void 0);
|
||||
//# sourceMappingURL=create-key.dto.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"create-key.dto.js","sourceRoot":"","sources":["../../../../src/auth/dto/management/create-key.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA0E;AAE1E,MAAa,YAAY;IAEvB,IAAI,CAAS;IAIb,SAAS,CAAU;IAKnB,cAAc,CAAY;CAC3B;AAZD,oCAYC;AAVC;IADC,IAAA,0BAAQ,GAAE;;0CACE;AAIb;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;+CACQ;AAKnB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,yBAAO,GAAE;IACT,IAAA,0BAAQ,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;oDACC"}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
import { Tenant } from './tenant.entity';
|
||||
export declare class ApiKey {
|
||||
id: string;
|
||||
key: string;
|
||||
secretHash: string;
|
||||
name: string;
|
||||
isActive: boolean;
|
||||
rateLimit: number;
|
||||
allowedOrigins: string[];
|
||||
allowedReferrers: string[];
|
||||
tenant: Tenant;
|
||||
tenantId: string;
|
||||
lastUsedAt: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
"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.ApiKey = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const tenant_entity_1 = require("./tenant.entity");
|
||||
let ApiKey = class ApiKey {
|
||||
id;
|
||||
key;
|
||||
secretHash;
|
||||
name;
|
||||
isActive;
|
||||
rateLimit;
|
||||
allowedOrigins;
|
||||
allowedReferrers;
|
||||
tenant;
|
||||
tenantId;
|
||||
lastUsedAt;
|
||||
createdAt;
|
||||
updatedAt;
|
||||
};
|
||||
exports.ApiKey = ApiKey;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], ApiKey.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ unique: true }),
|
||||
(0, typeorm_1.Index)(),
|
||||
__metadata("design:type", String)
|
||||
], ApiKey.prototype, "key", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], ApiKey.prototype, "secretHash", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], ApiKey.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: true }),
|
||||
__metadata("design:type", Boolean)
|
||||
], ApiKey.prototype, "isActive", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ nullable: true }),
|
||||
__metadata("design:type", Number)
|
||||
], ApiKey.prototype, "rateLimit", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)('simple-array', { nullable: true }),
|
||||
__metadata("design:type", Array)
|
||||
], ApiKey.prototype, "allowedOrigins", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)('simple-array', { nullable: true }),
|
||||
__metadata("design:type", Array)
|
||||
], ApiKey.prototype, "allowedReferrers", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => tenant_entity_1.Tenant, (tenant) => tenant.apiKeys),
|
||||
__metadata("design:type", tenant_entity_1.Tenant)
|
||||
], ApiKey.prototype, "tenant", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], ApiKey.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ nullable: true }),
|
||||
__metadata("design:type", Date)
|
||||
], ApiKey.prototype, "lastUsedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], ApiKey.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], ApiKey.prototype, "updatedAt", void 0);
|
||||
exports.ApiKey = ApiKey = __decorate([
|
||||
(0, typeorm_1.Entity)('api_keys')
|
||||
], ApiKey);
|
||||
//# sourceMappingURL=api-key.entity.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"api-key.entity.js","sourceRoot":"","sources":["../../../src/auth/entities/api-key.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAuH;AACvH,mDAAyC;AAGlC,IAAM,MAAM,GAAZ,MAAM,MAAM;IAEjB,EAAE,CAAS;IAIX,GAAG,CAAS;IAGZ,UAAU,CAAS;IAGnB,IAAI,CAAS;IAGb,QAAQ,CAAU;IAGlB,SAAS,CAAS;IAGlB,cAAc,CAAW;IAGzB,gBAAgB,CAAW;IAG3B,MAAM,CAAS;IAGf,QAAQ,CAAS;IAGjB,UAAU,CAAO;IAGjB,SAAS,CAAO;IAGhB,SAAS,CAAO;CACjB,CAAA;AAxCY,wBAAM;AAEjB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;kCACpB;AAIX;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACxB,IAAA,eAAK,GAAE;;mCACI;AAGZ;IADC,IAAA,gBAAM,GAAE;;0CACU;AAGnB;IADC,IAAA,gBAAM,GAAE;;oCACI;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;wCACR;AAGlB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;yCACT;AAGlB;IADC,IAAA,gBAAM,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CAClB;AAGzB;IADC,IAAA,gBAAM,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDAChB;AAG3B;IADC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,sBAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;8BAC5C,sBAAM;sCAAC;AAGf;IADC,IAAA,gBAAM,GAAE;;wCACQ;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BACf,IAAI;0CAAC;AAGjB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;yCAAC;AAGhB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;yCAAC;iBAvCL,MAAM;IADlB,IAAA,gBAAM,EAAC,UAAU,CAAC;GACN,MAAM,CAwClB"}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
import { ApiKey } from './api-key.entity';
|
||||
export declare enum TenantPlan {
|
||||
FREE = "FREE",
|
||||
STARTER = "STARTER",
|
||||
PRO = "PRO",
|
||||
ENTERPRISE = "ENTERPRISE"
|
||||
}
|
||||
export declare enum TenantRole {
|
||||
USER = "USER",
|
||||
ADMIN = "ADMIN"
|
||||
}
|
||||
export declare const QUOTA_LIMITS: Record<TenantPlan, number>;
|
||||
export declare const RATE_LIMITS: Record<TenantPlan, number>;
|
||||
export declare class Tenant {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
plan: TenantPlan;
|
||||
firebaseUid: string;
|
||||
role: TenantRole;
|
||||
photoUrl: string;
|
||||
isActive: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
apiKeys: ApiKey[];
|
||||
}
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
"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.Tenant = exports.RATE_LIMITS = exports.QUOTA_LIMITS = exports.TenantRole = exports.TenantPlan = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const api_key_entity_1 = require("./api-key.entity");
|
||||
var TenantPlan;
|
||||
(function (TenantPlan) {
|
||||
TenantPlan["FREE"] = "FREE";
|
||||
TenantPlan["STARTER"] = "STARTER";
|
||||
TenantPlan["PRO"] = "PRO";
|
||||
TenantPlan["ENTERPRISE"] = "ENTERPRISE";
|
||||
})(TenantPlan || (exports.TenantPlan = TenantPlan = {}));
|
||||
var TenantRole;
|
||||
(function (TenantRole) {
|
||||
TenantRole["USER"] = "USER";
|
||||
TenantRole["ADMIN"] = "ADMIN";
|
||||
})(TenantRole || (exports.TenantRole = TenantRole = {}));
|
||||
exports.QUOTA_LIMITS = {
|
||||
[TenantPlan.FREE]: 8000,
|
||||
[TenantPlan.STARTER]: 25000,
|
||||
[TenantPlan.PRO]: 100000,
|
||||
[TenantPlan.ENTERPRISE]: 500000,
|
||||
};
|
||||
exports.RATE_LIMITS = {
|
||||
[TenantPlan.FREE]: 5,
|
||||
[TenantPlan.STARTER]: 100,
|
||||
[TenantPlan.PRO]: 500,
|
||||
[TenantPlan.ENTERPRISE]: 50000,
|
||||
};
|
||||
let Tenant = class Tenant {
|
||||
id;
|
||||
name;
|
||||
email;
|
||||
plan;
|
||||
firebaseUid;
|
||||
role;
|
||||
photoUrl;
|
||||
isActive;
|
||||
createdAt;
|
||||
updatedAt;
|
||||
apiKeys;
|
||||
};
|
||||
exports.Tenant = Tenant;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ unique: true }),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "email", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
type: 'enum',
|
||||
enum: TenantPlan,
|
||||
default: TenantPlan.FREE,
|
||||
}),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "plan", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ nullable: true, unique: true }),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "firebaseUid", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
type: 'enum',
|
||||
enum: TenantRole,
|
||||
default: TenantRole.USER,
|
||||
}),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "role", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], Tenant.prototype, "photoUrl", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: true }),
|
||||
__metadata("design:type", Boolean)
|
||||
], Tenant.prototype, "isActive", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], Tenant.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], Tenant.prototype, "updatedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.OneToMany)(() => api_key_entity_1.ApiKey, (apiKey) => apiKey.tenant),
|
||||
__metadata("design:type", Array)
|
||||
], Tenant.prototype, "apiKeys", void 0);
|
||||
exports.Tenant = Tenant = __decorate([
|
||||
(0, typeorm_1.Entity)('tenants')
|
||||
], Tenant);
|
||||
//# sourceMappingURL=tenant.entity.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"tenant.entity.js","sourceRoot":"","sources":["../../../src/auth/entities/tenant.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAgH;AAChH,qDAA0C;AAE1C,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,iCAAmB,CAAA;IACnB,yBAAW,CAAA;IACX,uCAAyB,CAAA;AAC3B,CAAC,EALW,UAAU,0BAAV,UAAU,QAKrB;AAED,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,6BAAe,CAAA;AACjB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB;AAEY,QAAA,YAAY,GAA+B;IACtD,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI;IACvB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK;IAC3B,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM;IACxB,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM;CAChC,CAAC;AAEW,QAAA,WAAW,GAA+B;IACrD,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;IACpB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG;IACzB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG;IACrB,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,KAAK;CAC/B,CAAC;AAGK,IAAM,MAAM,GAAZ,MAAM,MAAM;IAEjB,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,KAAK,CAAS;IAOd,IAAI,CAAa;IAGjB,WAAW,CAAS;IAOpB,IAAI,CAAa;IAGjB,QAAQ,CAAS;IAGjB,QAAQ,CAAU;IAGlB,SAAS,CAAO;IAGhB,SAAS,CAAO;IAGhB,OAAO,CAAW;CACnB,CAAA;AAzCY,wBAAM;AAEjB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;kCACpB;AAGX;IADC,IAAA,gBAAM,GAAE;;oCACI;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;qCACX;AAOd;IALC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,UAAU,CAAC,IAAI;KACzB,CAAC;;oCACe;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;2CACrB;AAOpB;IALC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,UAAU,CAAC,IAAI;KACzB,CAAC;;oCACe;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;wCACV;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;wCACR;AAGlB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;yCAAC;AAGhB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;yCAAC;AAGhB;IADC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,uBAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;;uCACjC;iBAxCP,MAAM;IADlB,IAAA,gBAAM,EAAC,SAAS,CAAC;GACL,MAAM,CAyClB"}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { OnModuleInit } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as admin from 'firebase-admin';
|
||||
export declare class FirebaseAdminService implements OnModuleInit {
|
||||
private configService;
|
||||
private readonly logger;
|
||||
private firebaseApp;
|
||||
constructor(configService: ConfigService);
|
||||
onModuleInit(): void;
|
||||
verifyIdToken(token: string): Promise<admin.auth.DecodedIdToken>;
|
||||
}
|
||||
-99
@@ -1,99 +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);
|
||||
};
|
||||
var FirebaseAdminService_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FirebaseAdminService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const admin = __importStar(require("firebase-admin"));
|
||||
const fs = __importStar(require("fs"));
|
||||
const path = __importStar(require("path"));
|
||||
let FirebaseAdminService = FirebaseAdminService_1 = class FirebaseAdminService {
|
||||
configService;
|
||||
logger = new common_1.Logger(FirebaseAdminService_1.name);
|
||||
firebaseApp;
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
}
|
||||
onModuleInit() {
|
||||
const keyPath = this.configService.get('FIREBASE_SERVICE_ACCOUNT_PATH');
|
||||
if (!keyPath) {
|
||||
this.logger.error('FIREBASE_SERVICE_ACCOUNT_PATH is not defined in environment variables');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const absolutePath = path.isAbsolute(keyPath)
|
||||
? keyPath
|
||||
: path.resolve(process.cwd(), keyPath);
|
||||
if (!fs.existsSync(absolutePath)) {
|
||||
this.logger.error(`Firebase service account key not found at: ${absolutePath}`);
|
||||
return;
|
||||
}
|
||||
const serviceAccount = JSON.parse(fs.readFileSync(absolutePath, 'utf8'));
|
||||
this.firebaseApp = admin.initializeApp({
|
||||
credential: admin.credential.cert(serviceAccount),
|
||||
});
|
||||
this.logger.log('✅ Firebase Admin SDK initialized successfully');
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Failed to initialize Firebase Admin SDK: ${error.message}`);
|
||||
}
|
||||
}
|
||||
async verifyIdToken(token) {
|
||||
try {
|
||||
return await admin.auth().verifyIdToken(token);
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Token verification failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.FirebaseAdminService = FirebaseAdminService;
|
||||
exports.FirebaseAdminService = FirebaseAdminService = FirebaseAdminService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], FirebaseAdminService);
|
||||
//# sourceMappingURL=firebase-admin.service.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"firebase-admin.service.js","sourceRoot":"","sources":["../../src/auth/firebase-admin.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAkE;AAClE,2CAA+C;AAC/C,sDAAwC;AACxC,uCAAyB;AACzB,2CAA6B;AAGtB,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAIX;IAHH,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IACxD,WAAW,CAAgB;IAEnC,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD,YAAY;QACV,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,+BAA+B,CAAC,CAAC;QAEhF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;YAC3F,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YAEH,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3C,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;YAEzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,YAAY,EAAE,CAAC,CAAC;gBAChF,OAAO;YACT,CAAC;YAED,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;YAEzE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC;gBACrC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC;aAClD,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACjE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF,CAAA;AA7CY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;yDAKwB,sBAAa,oBAAb,sBAAa;GAJrC,oBAAoB,CA6ChC"}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
import { FirebaseAdminService } from '../firebase-admin.service';
|
||||
import { AuthService } from '../auth.service';
|
||||
export declare class FirebaseAuthGuard implements CanActivate {
|
||||
private firebaseAdminService;
|
||||
private authService;
|
||||
private readonly logger;
|
||||
constructor(firebaseAdminService: FirebaseAdminService, authService: AuthService);
|
||||
canActivate(context: ExecutionContext): Promise<boolean>;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
"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 FirebaseAuthGuard_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FirebaseAuthGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const firebase_admin_service_1 = require("../firebase-admin.service");
|
||||
const auth_service_1 = require("../auth.service");
|
||||
let FirebaseAuthGuard = FirebaseAuthGuard_1 = class FirebaseAuthGuard {
|
||||
firebaseAdminService;
|
||||
authService;
|
||||
logger = new common_1.Logger(FirebaseAuthGuard_1.name);
|
||||
constructor(firebaseAdminService, authService) {
|
||||
this.firebaseAdminService = firebaseAdminService;
|
||||
this.authService = authService;
|
||||
}
|
||||
async canActivate(context) {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const authHeader = request.headers.authorization;
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
throw new common_1.UnauthorizedException('Missing or invalid Authorization header');
|
||||
}
|
||||
const token = authHeader.split('Bearer ')[1];
|
||||
try {
|
||||
const decodedToken = await this.firebaseAdminService.verifyIdToken(token);
|
||||
const tenant = await this.authService.findOrCreateByFirebaseUid(decodedToken.uid, decodedToken.email || '', decodedToken.name || decodedToken.email?.split('@')[0] || 'Unknown User', decodedToken.picture);
|
||||
if (!tenant.isActive) {
|
||||
throw new common_1.UnauthorizedException('Tenant account is disabled');
|
||||
}
|
||||
request['tenant'] = tenant;
|
||||
request['user'] = decodedToken;
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Firebase Auth failed: ${error.message}`);
|
||||
throw new common_1.UnauthorizedException(error.message || 'Authentication failed');
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.FirebaseAuthGuard = FirebaseAuthGuard;
|
||||
exports.FirebaseAuthGuard = FirebaseAuthGuard = FirebaseAuthGuard_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [firebase_admin_service_1.FirebaseAdminService,
|
||||
auth_service_1.AuthService])
|
||||
], FirebaseAuthGuard);
|
||||
//# sourceMappingURL=firebase-auth.guard.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"firebase-auth.guard.js","sourceRoot":"","sources":["../../../src/auth/guards/firebase-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAMwB;AACxB,sEAAiE;AACjE,kDAA8C;AAGvC,IAAM,iBAAiB,yBAAvB,MAAM,iBAAiB;IAIlB;IACA;IAJO,MAAM,GAAG,IAAI,eAAM,CAAC,mBAAiB,CAAC,IAAI,CAAC,CAAC;IAE7D,YACU,oBAA0C,EAC1C,WAAwB;QADxB,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,gBAAW,GAAX,WAAW,CAAa;IAC/B,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QAEjD,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,8BAAqB,CAAC,yCAAyC,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7C,IAAI,CAAC;YAEH,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAG1E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,yBAAyB,CAC7D,YAAY,CAAC,GAAG,EAChB,YAAY,CAAC,KAAK,IAAI,EAAE,EACxB,YAAY,CAAC,IAAI,IAAI,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,cAAc,EACxE,YAAY,CAAC,OAAO,CACrB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,IAAI,8BAAqB,CAAC,4BAA4B,CAAC,CAAC;YAChE,CAAC;YAGD,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC;YAE/B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,MAAM,IAAI,8BAAqB,CAAC,KAAK,CAAC,OAAO,IAAI,uBAAuB,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF,CAAA;AA5CY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAKqB,6CAAoB;QAC7B,0BAAW;GALvB,iBAAiB,CA4C7B"}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { AuthService } from './auth.service';
|
||||
import { CreateKeyDto } from './dto/management/create-key.dto';
|
||||
export declare class TenantController {
|
||||
private readonly authService;
|
||||
constructor(authService: AuthService);
|
||||
createKey(req: any, dto: CreateKeyDto): Promise<import("./entities/api-key.entity").ApiKey>;
|
||||
getKeys(req: any): Promise<import("./entities/api-key.entity").ApiKey[]>;
|
||||
getMe(req: any): Promise<any>;
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
"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.TenantController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
const create_key_dto_1 = require("./dto/management/create-key.dto");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const firebase_auth_guard_1 = require("./guards/firebase-auth.guard");
|
||||
let TenantController = class TenantController {
|
||||
authService;
|
||||
constructor(authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
async createKey(req, dto) {
|
||||
if (req.user && req.user.email_verified === false) {
|
||||
throw new common_1.ForbiddenException('You must verify your email address before creating an API key.');
|
||||
}
|
||||
const tenantId = req.tenant.id;
|
||||
return this.authService.createApiKey(tenantId, dto.name, dto.rateLimit, dto.allowedOrigins);
|
||||
}
|
||||
async getKeys(req) {
|
||||
const tenantId = req.tenant.id;
|
||||
return this.authService.getApiKeys(tenantId);
|
||||
}
|
||||
async getMe(req) {
|
||||
return req.tenant;
|
||||
}
|
||||
};
|
||||
exports.TenantController = TenantController;
|
||||
__decorate([
|
||||
(0, common_1.Post)('keys'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Create a new API key' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, create_key_dto_1.CreateKeyDto]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], TenantController.prototype, "createKey", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('keys'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Get all API keys for the authenticated tenant' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], TenantController.prototype, "getKeys", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('me'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Get current authenticated tenant info' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], TenantController.prototype, "getMe", null);
|
||||
exports.TenantController = TenantController = __decorate([
|
||||
(0, swagger_1.ApiTags)('auth'),
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
(0, common_1.UseGuards)(firebase_auth_guard_1.FirebaseAuthGuard),
|
||||
(0, common_1.Controller)('auth/management'),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
||||
], TenantController);
|
||||
//# sourceMappingURL=tenant.controller.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"tenant.controller.js","sourceRoot":"","sources":["../../src/auth/tenant.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwG;AACxG,iDAA6C;AAC7C,oEAA+D;AAC/D,6CAAuE;AACvE,sEAAiE;AAM1D,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IACE;IAA7B,YAA6B,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAInD,AAAN,KAAK,CAAC,SAAS,CACN,GAAQ,EACP,GAAiB;QAEzB,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;YAClD,MAAM,IAAI,2BAAkB,CAAC,gEAAgE,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,CAClC,QAAQ,EACR,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,SAAS,EACb,GAAG,CAAC,cAAc,CACnB,CAAC;IACJ,CAAC;IAIK,AAAN,KAAK,CAAC,OAAO,CAAQ,GAAQ;QAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAIK,AAAN,KAAK,CAAC,KAAK,CAAQ,GAAQ;QACzB,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;CACF,CAAA;AAlCY,4CAAgB;AAKrB;IAFL,IAAA,aAAI,EAAC,MAAM,CAAC;IACZ,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAE/C,WAAA,IAAA,YAAG,GAAE,CAAA;IACL,WAAA,IAAA,aAAI,GAAE,CAAA;;6CAAM,6BAAY;;iDAa1B;AAIK;IAFL,IAAA,YAAG,EAAC,MAAM,CAAC;IACX,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAC;IAC5D,WAAA,IAAA,YAAG,GAAE,CAAA;;;;+CAGnB;AAIK;IAFL,IAAA,YAAG,EAAC,IAAI,CAAC;IACT,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,uCAAuC,EAAE,CAAC;IACtD,WAAA,IAAA,YAAG,GAAE,CAAA;;;;6CAEjB;2BAjCU,gBAAgB;IAJ5B,IAAA,iBAAO,EAAC,MAAM,CAAC;IACf,IAAA,uBAAa,GAAE;IACf,IAAA,kBAAS,EAAC,uCAAiB,CAAC;IAC5B,IAAA,mBAAU,EAAC,iBAAiB,CAAC;qCAEc,0BAAW;GAD1C,gBAAgB,CAkC5B"}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
import { BillingService } from './billing.service';
|
||||
import { PayMobProvider } from './providers/paymob.provider';
|
||||
import { BinanceProvider } from './providers/binance.provider';
|
||||
import { PaymentProvider } from './entities/transaction.entity';
|
||||
export declare class BillingController {
|
||||
private billingService;
|
||||
private paymobProvider;
|
||||
private binanceProvider;
|
||||
private readonly logger;
|
||||
constructor(billingService: BillingService, paymobProvider: PayMobProvider, binanceProvider: BinanceProvider);
|
||||
getSubscription(req: any): Promise<import("./entities/subscription.entity").Subscription>;
|
||||
checkout(req: any, body: {
|
||||
plan: string;
|
||||
provider: PaymentProvider;
|
||||
}): Promise<{
|
||||
checkoutUrl: any;
|
||||
orderId: string;
|
||||
prepayId: any;
|
||||
} | {
|
||||
checkoutUrl: string;
|
||||
orderId: string;
|
||||
}>;
|
||||
handlePaymobCallback(query: any, req: any): Promise<string>;
|
||||
handlePaymobWebhook(body: any, hmac: string): Promise<{
|
||||
status: string;
|
||||
message: string;
|
||||
} | {
|
||||
status: string;
|
||||
message?: undefined;
|
||||
}>;
|
||||
handleBinanceWebhook(body: any, req: any): Promise<{
|
||||
returnCode: string;
|
||||
returnMessage: any;
|
||||
}>;
|
||||
getInvoices(req: any): Promise<import("./entities/transaction.entity").Transaction[]>;
|
||||
}
|
||||
-259
@@ -1,259 +0,0 @@
|
||||
"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); }
|
||||
};
|
||||
var BillingController_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BillingController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const billing_service_1 = require("./billing.service");
|
||||
const paymob_provider_1 = require("./providers/paymob.provider");
|
||||
const binance_provider_1 = require("./providers/binance.provider");
|
||||
const firebase_auth_guard_1 = require("../auth/guards/firebase-auth.guard");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const transaction_entity_1 = require("./entities/transaction.entity");
|
||||
let BillingController = BillingController_1 = class BillingController {
|
||||
billingService;
|
||||
paymobProvider;
|
||||
binanceProvider;
|
||||
logger = new common_1.Logger(BillingController_1.name);
|
||||
constructor(billingService, paymobProvider, binanceProvider) {
|
||||
this.billingService = billingService;
|
||||
this.paymobProvider = paymobProvider;
|
||||
this.binanceProvider = binanceProvider;
|
||||
}
|
||||
async getSubscription(req) {
|
||||
return this.billingService.getSubscription(req.tenant.id);
|
||||
}
|
||||
async checkout(req, body) {
|
||||
const tenantId = req.tenant.id;
|
||||
const plan = body.plan;
|
||||
const pricing = {
|
||||
'STARTER': 29,
|
||||
'PRO': 89,
|
||||
};
|
||||
const amount = pricing[plan] || 0;
|
||||
if (amount === 0 && plan !== 'FREE') {
|
||||
throw new common_1.BadRequestException('Invalid plan or price not configured');
|
||||
}
|
||||
if (body.provider === transaction_entity_1.PaymentProvider.PAYMOB) {
|
||||
const { paymentKey, orderId } = await this.paymobProvider.createPaymentKey(tenantId, amount, plan);
|
||||
const iframeId = this.billingService.getIframeId();
|
||||
const checkoutUrl = `https://accept.paymob.com/api/acceptance/iframes/${iframeId}?payment_token=${paymentKey}`;
|
||||
return { checkoutUrl, orderId };
|
||||
}
|
||||
if (body.provider === transaction_entity_1.PaymentProvider.BINANCE) {
|
||||
return this.binanceProvider.createOrder(tenantId, amount, plan);
|
||||
}
|
||||
throw new common_1.BadRequestException('Invalid payment provider');
|
||||
}
|
||||
async handlePaymobCallback(query, req) {
|
||||
this.logger.log(`🔄 PayMob Redirect Callback: ID ${query.id}, Success: ${query.success}`);
|
||||
if (query.success === 'true' && query.id) {
|
||||
try {
|
||||
const txDetails = await this.paymobProvider.getTransactionDetails(query.id);
|
||||
if (txDetails && txDetails.success === true) {
|
||||
const extraDesc = txDetails.order?.shipping_data?.extra_description || "";
|
||||
const [tenantId, plan] = extraDesc.split('|');
|
||||
if (tenantId) {
|
||||
await this.billingService.processSuccessfulPayment(query.id.toString(), transaction_entity_1.PaymentProvider.PAYMOB, txDetails.amount_cents / 100, { tenantId, plan: plan || 'PRO' });
|
||||
this.logger.log(`🚀 Immediate Activation triggered via Callback for Tenant ${tenantId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
this.logger.error(`Failed during immediate activation fallback: ${e.message}`);
|
||||
}
|
||||
}
|
||||
const targetUrl = `https://map-dashboard.intaleqapp.com/dashboard.html#billing?payment_status=${query.success === 'true' ? 'success' : 'failed'}&id=${query.id}`;
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Intaleq Maps | تمت العملية بنجاح</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700;900&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body { font-family: 'Cairo', sans-serif; background: #050505; color: white; overflow: hidden; }
|
||||
.pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
|
||||
@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .7; transform: scale(0.95); } }
|
||||
</style>
|
||||
</head>
|
||||
<body class="flex items-center justify-center h-screen">
|
||||
<div class="text-center space-y-8 max-w-md p-10 bg-white shadow-2xl rounded-[3rem] border border-white/10 relative overflow-hidden">
|
||||
<!-- Animated Background Glow -->
|
||||
<div class="absolute -top-20 -left-20 w-40 h-40 bg-blue-600/20 blur-[80px] rounded-full"></div>
|
||||
<div class="absolute -bottom-20 -right-20 w-40 h-40 bg-emerald-600/20 blur-[80px] rounded-full"></div>
|
||||
|
||||
<div class="relative z-10">
|
||||
<div class="w-24 h-24 bg-emerald-500 rounded-full mx-auto flex items-center justify-center shadow-[0_0_50px_rgba(16,185,129,0.4)] pulse mb-8">
|
||||
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h1 class="text-3xl font-black text-slate-900 mb-4">شكراً لك، حمزة!</h1>
|
||||
<p class="text-slate-500 font-bold mb-8">تم تفعيل خطة <span class="text-blue-600">PRO</span> بنجاح. يتم الآن توجيهك إلى لوحة التحكم...</p>
|
||||
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce"></div>
|
||||
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce [animation-delay:-0.15s]"></div>
|
||||
<div class="w-2 h-2 bg-blue-600 rounded-full animate-bounce [animation-delay:-0.3s]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
window.location.href = "${targetUrl}";
|
||||
}, 2500);
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
async handlePaymobWebhook(body, hmac) {
|
||||
this.logger.log(`📥 PayMob Webhook Received: Transaction ID ${body.obj?.id}`);
|
||||
if (!this.paymobProvider.verifyHmac(body.obj, hmac)) {
|
||||
this.logger.error('❌ PayMob HMAC Verification Failed');
|
||||
throw new common_1.BadRequestException('Invalid signature');
|
||||
}
|
||||
if (body.obj.success === true) {
|
||||
const extraDesc = body.obj.order?.shipping_data?.extra_description || "";
|
||||
const [tenantId, plan] = extraDesc.split('|');
|
||||
if (!tenantId) {
|
||||
this.logger.error(`❌ PayMob Webhook failed: No tenantId in metadata. Raw: ${extraDesc}`);
|
||||
return { status: 'error', message: 'No tenantId found' };
|
||||
}
|
||||
await this.billingService.processSuccessfulPayment(body.obj.id.toString(), transaction_entity_1.PaymentProvider.PAYMOB, body.obj.amount_cents / 100, {
|
||||
tenantId,
|
||||
plan: plan || 'PRO'
|
||||
});
|
||||
}
|
||||
return { status: 'success' };
|
||||
}
|
||||
async handleBinanceWebhook(body, req) {
|
||||
const timestamp = req.headers['binancepay-timestamp'];
|
||||
const nonce = req.headers['binancepay-nonce'];
|
||||
const signature = req.headers['binancepay-signature'];
|
||||
this.logger.log(`📥 Binance Webhook Received: Transaction ID ${body.bizId || 'UNKNOWN'}`);
|
||||
if (!timestamp || !nonce || !signature) {
|
||||
this.logger.error('❌ Binance Webhook: Missing required headers');
|
||||
throw new common_1.BadRequestException('Missing headers');
|
||||
}
|
||||
if (!this.binanceProvider.verifySignature(timestamp, nonce, signature, body)) {
|
||||
this.logger.error('❌ Binance Signature Verification Failed');
|
||||
throw new common_1.BadRequestException('Invalid signature');
|
||||
}
|
||||
if (body.bizStatus === 'PAY_SUCCESS') {
|
||||
try {
|
||||
let dataObj = {};
|
||||
if (body.data) {
|
||||
dataObj = JSON.parse(body.data);
|
||||
}
|
||||
let tenantId = '';
|
||||
let plan = 'PRO';
|
||||
if (dataObj.passThroughInfo) {
|
||||
const passThrough = JSON.parse(dataObj.passThroughInfo);
|
||||
tenantId = passThrough.tenantId;
|
||||
plan = passThrough.plan;
|
||||
}
|
||||
if (!tenantId) {
|
||||
this.logger.error(`❌ Binance Webhook failed: No tenantId found. Body: ${JSON.stringify(body)}`);
|
||||
return { returnCode: 'FAIL', returnMessage: 'No tenantId found' };
|
||||
}
|
||||
const externalTxId = dataObj.merchantTradeNo || body.bizId?.toString();
|
||||
await this.billingService.processSuccessfulPayment(externalTxId, transaction_entity_1.PaymentProvider.BINANCE, 0, { tenantId, plan });
|
||||
this.logger.log(`✅ Binance Payment Processed Successfully for Tenant ${tenantId}`);
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error(`❌ Failed to process Binance payment: ${err.message}`);
|
||||
return { returnCode: 'FAIL', returnMessage: err.message };
|
||||
}
|
||||
}
|
||||
return {
|
||||
returnCode: 'SUCCESS',
|
||||
returnMessage: null,
|
||||
};
|
||||
}
|
||||
async getInvoices(req) {
|
||||
return this.billingService.getTransactionHistory(req.tenant.id);
|
||||
}
|
||||
};
|
||||
exports.BillingController = BillingController;
|
||||
__decorate([
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
(0, common_1.UseGuards)(firebase_auth_guard_1.FirebaseAuthGuard),
|
||||
(0, common_1.Get)('subscription'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Get current subscription details' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], BillingController.prototype, "getSubscription", null);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
(0, common_1.UseGuards)(firebase_auth_guard_1.FirebaseAuthGuard),
|
||||
(0, common_1.Post)('checkout'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Initialize a checkout session' }),
|
||||
__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)
|
||||
], BillingController.prototype, "checkout", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('callback/paymob'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'PayMob Redirection Handler' }),
|
||||
__param(0, (0, common_1.Query)()),
|
||||
__param(1, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], BillingController.prototype, "handlePaymobCallback", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('webhooks/paymob'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'PayMob Payment Webhook' }),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__param(1, (0, common_1.Query)('hmac')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], BillingController.prototype, "handlePaymobWebhook", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('webhooks/binance'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Binance Payment Webhook' }),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__param(1, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], BillingController.prototype, "handleBinanceWebhook", null);
|
||||
__decorate([
|
||||
(0, swagger_1.ApiBearerAuth)(),
|
||||
(0, common_1.UseGuards)(firebase_auth_guard_1.FirebaseAuthGuard),
|
||||
(0, common_1.Get)('invoices'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Get payment history' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], BillingController.prototype, "getInvoices", null);
|
||||
exports.BillingController = BillingController = BillingController_1 = __decorate([
|
||||
(0, swagger_1.ApiTags)('billing'),
|
||||
(0, common_1.Controller)('billing'),
|
||||
__metadata("design:paramtypes", [billing_service_1.BillingService,
|
||||
paymob_provider_1.PayMobProvider,
|
||||
binance_provider_1.BinanceProvider])
|
||||
], BillingController);
|
||||
//# sourceMappingURL=billing.controller.js.map
|
||||
File diff suppressed because one or more lines are too long
-2
@@ -1,2 +0,0 @@
|
||||
export declare class BillingModule {
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
"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.BillingModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const subscription_entity_1 = require("./entities/subscription.entity");
|
||||
const transaction_entity_1 = require("./entities/transaction.entity");
|
||||
const billing_service_1 = require("./billing.service");
|
||||
const billing_controller_1 = require("./billing.controller");
|
||||
const paymob_provider_1 = require("./providers/paymob.provider");
|
||||
const binance_provider_1 = require("./providers/binance.provider");
|
||||
const tenant_entity_1 = require("../auth/entities/tenant.entity");
|
||||
let BillingModule = class BillingModule {
|
||||
};
|
||||
exports.BillingModule = BillingModule;
|
||||
exports.BillingModule = BillingModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
typeorm_1.TypeOrmModule.forFeature([subscription_entity_1.Subscription, transaction_entity_1.Transaction, tenant_entity_1.Tenant]),
|
||||
],
|
||||
providers: [billing_service_1.BillingService, paymob_provider_1.PayMobProvider, binance_provider_1.BinanceProvider],
|
||||
controllers: [billing_controller_1.BillingController],
|
||||
exports: [billing_service_1.BillingService],
|
||||
})
|
||||
], BillingModule);
|
||||
//# sourceMappingURL=billing.module.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"billing.module.js","sourceRoot":"","sources":["../../src/billing/billing.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,wEAA8D;AAC9D,sEAA4D;AAC5D,uDAAmD;AACnD,6DAAyD;AACzD,iEAA6D;AAC7D,mEAA+D;AAC/D,kEAAwD;AAUjD,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IARzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,uBAAa,CAAC,UAAU,CAAC,CAAC,kCAAY,EAAE,gCAAW,EAAE,sBAAM,CAAC,CAAC;SAC9D;QACD,SAAS,EAAE,CAAC,gCAAc,EAAE,gCAAc,EAAE,kCAAe,CAAC;QAC5D,WAAW,EAAE,CAAC,sCAAiB,CAAC;QAChC,OAAO,EAAE,CAAC,gCAAc,CAAC;KAC1B,CAAC;GACW,aAAa,CAAG"}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Subscription } from './entities/subscription.entity';
|
||||
import { Transaction, PaymentProvider } from './entities/transaction.entity';
|
||||
import { Tenant } from '../auth/entities/tenant.entity';
|
||||
import { MailService } from '../common/mail.service';
|
||||
export declare class BillingService {
|
||||
private subscriptionRepository;
|
||||
private transactionRepository;
|
||||
private tenantRepository;
|
||||
private configService;
|
||||
private mailService;
|
||||
private readonly logger;
|
||||
constructor(subscriptionRepository: Repository<Subscription>, transactionRepository: Repository<Transaction>, tenantRepository: Repository<Tenant>, configService: ConfigService, mailService: MailService);
|
||||
getIframeId(): string;
|
||||
getSubscription(tenantId: string): Promise<Subscription>;
|
||||
processSuccessfulPayment(externalTxId: string, provider: PaymentProvider, amount: number, metadata: any): Promise<void>;
|
||||
private upgradeTenantPlan;
|
||||
getTransactionHistory(tenantId: string): Promise<Transaction[]>;
|
||||
}
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
"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); }
|
||||
};
|
||||
var BillingService_1;
|
||||
var _a, _b, _c, _d;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BillingService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const subscription_entity_1 = require("./entities/subscription.entity");
|
||||
const transaction_entity_1 = require("./entities/transaction.entity");
|
||||
const tenant_entity_1 = require("../auth/entities/tenant.entity");
|
||||
const mail_service_1 = require("../common/mail.service");
|
||||
let BillingService = BillingService_1 = class BillingService {
|
||||
subscriptionRepository;
|
||||
transactionRepository;
|
||||
tenantRepository;
|
||||
configService;
|
||||
mailService;
|
||||
logger = new common_1.Logger(BillingService_1.name);
|
||||
constructor(subscriptionRepository, transactionRepository, tenantRepository, configService, mailService) {
|
||||
this.subscriptionRepository = subscriptionRepository;
|
||||
this.transactionRepository = transactionRepository;
|
||||
this.tenantRepository = tenantRepository;
|
||||
this.configService = configService;
|
||||
this.mailService = mailService;
|
||||
}
|
||||
getIframeId() {
|
||||
return this.configService.get('PAYMOB_IFRAME_ID', '837992');
|
||||
}
|
||||
async getSubscription(tenantId) {
|
||||
let sub = await this.subscriptionRepository.findOne({ where: { tenantId } });
|
||||
if (!sub) {
|
||||
sub = await this.subscriptionRepository.save({
|
||||
tenantId,
|
||||
plan: 'FREE',
|
||||
monthlyRequestLimit: 5000,
|
||||
status: subscription_entity_1.SubscriptionStatus.ACTIVE,
|
||||
});
|
||||
}
|
||||
return sub;
|
||||
}
|
||||
async processSuccessfulPayment(externalTxId, provider, amount, metadata) {
|
||||
let txn = await this.transactionRepository.findOne({ where: { externalTransactionId: externalTxId } });
|
||||
if (txn && txn.status === transaction_entity_1.PaymentStatus.SUCCESS) {
|
||||
this.logger.warn(`Transaction ${externalTxId} already processed.`);
|
||||
return;
|
||||
}
|
||||
if (!txn) {
|
||||
const tenantId = metadata.tenantId;
|
||||
if (!tenantId)
|
||||
throw new common_1.BadRequestException('No tenantId found in payment metadata');
|
||||
txn = await this.transactionRepository.save({
|
||||
tenantId,
|
||||
externalTransactionId: externalTxId,
|
||||
amount,
|
||||
provider,
|
||||
status: transaction_entity_1.PaymentStatus.SUCCESS,
|
||||
metadata,
|
||||
});
|
||||
}
|
||||
else {
|
||||
txn.status = transaction_entity_1.PaymentStatus.SUCCESS;
|
||||
txn.metadata = { ...txn.metadata, ...metadata };
|
||||
await this.transactionRepository.save(txn);
|
||||
}
|
||||
const tenantId = txn.tenantId;
|
||||
const plan = metadata.plan || 'PRO';
|
||||
await this.upgradeTenantPlan(tenantId, plan);
|
||||
try {
|
||||
const tenant = await this.tenantRepository.findOne({ where: { id: tenantId } });
|
||||
if (tenant && tenant.email) {
|
||||
await this.mailService.sendInvoiceEmail(tenant.email, {
|
||||
tenantName: tenant.name,
|
||||
plan: plan,
|
||||
amount: `${amount} EGP`,
|
||||
transactionId: externalTxId,
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error(`Failed to send invoice email for tx ${externalTxId}: ${err.message}`);
|
||||
}
|
||||
this.logger.log(`✅ Tenant ${tenantId} upgraded to ${plan} after payment ${externalTxId}`);
|
||||
}
|
||||
async upgradeTenantPlan(tenantId, plan) {
|
||||
await this.tenantRepository.update(tenantId, { plan });
|
||||
const limits = {
|
||||
[tenant_entity_1.TenantPlan.FREE]: 5000,
|
||||
[tenant_entity_1.TenantPlan.STARTER]: 25000,
|
||||
[tenant_entity_1.TenantPlan.PRO]: 100000,
|
||||
[tenant_entity_1.TenantPlan.ENTERPRISE]: 500000,
|
||||
};
|
||||
const sub = await this.getSubscription(tenantId);
|
||||
sub.plan = plan;
|
||||
sub.monthlyRequestLimit = limits[plan] || 8000;
|
||||
sub.status = subscription_entity_1.SubscriptionStatus.ACTIVE;
|
||||
sub.currentPeriodStart = new Date();
|
||||
const nextMonth = new Date();
|
||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
||||
sub.currentPeriodEnd = nextMonth;
|
||||
await this.subscriptionRepository.save(sub);
|
||||
}
|
||||
async getTransactionHistory(tenantId) {
|
||||
return this.transactionRepository.find({
|
||||
where: { tenantId },
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.BillingService = BillingService;
|
||||
exports.BillingService = BillingService = BillingService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(subscription_entity_1.Subscription)),
|
||||
__param(1, (0, typeorm_1.InjectRepository)(transaction_entity_1.Transaction)),
|
||||
__param(2, (0, typeorm_1.InjectRepository)(tenant_entity_1.Tenant)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _d : Object, mail_service_1.MailService])
|
||||
], BillingService);
|
||||
//# sourceMappingURL=billing.service.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"billing.service.js","sourceRoot":"","sources":["../../src/billing/billing.service.ts"],"names":[],"mappings":"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"}
|
||||
@@ -1,18 +0,0 @@
|
||||
export declare enum SubscriptionStatus {
|
||||
ACTIVE = "ACTIVE",
|
||||
PAST_DUE = "PAST_DUE",
|
||||
CANCELED = "CANCELED",
|
||||
TRIALING = "TRIALING"
|
||||
}
|
||||
export declare class Subscription {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
plan: string;
|
||||
status: SubscriptionStatus;
|
||||
monthlyRequestLimit: number;
|
||||
currentPeriodStart: Date;
|
||||
currentPeriodEnd: Date;
|
||||
canceledAt: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
"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.Subscription = exports.SubscriptionStatus = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
var SubscriptionStatus;
|
||||
(function (SubscriptionStatus) {
|
||||
SubscriptionStatus["ACTIVE"] = "ACTIVE";
|
||||
SubscriptionStatus["PAST_DUE"] = "PAST_DUE";
|
||||
SubscriptionStatus["CANCELED"] = "CANCELED";
|
||||
SubscriptionStatus["TRIALING"] = "TRIALING";
|
||||
})(SubscriptionStatus || (exports.SubscriptionStatus = SubscriptionStatus = {}));
|
||||
let Subscription = class Subscription {
|
||||
id;
|
||||
tenantId;
|
||||
plan;
|
||||
status;
|
||||
monthlyRequestLimit;
|
||||
currentPeriodStart;
|
||||
currentPeriodEnd;
|
||||
canceledAt;
|
||||
createdAt;
|
||||
updatedAt;
|
||||
};
|
||||
exports.Subscription = Subscription;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Subscription.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Index)(),
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], Subscription.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: 'FREE' }),
|
||||
__metadata("design:type", String)
|
||||
], Subscription.prototype, "plan", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
type: 'enum',
|
||||
enum: SubscriptionStatus,
|
||||
default: SubscriptionStatus.ACTIVE,
|
||||
}),
|
||||
__metadata("design:type", String)
|
||||
], Subscription.prototype, "status", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'int', default: 8000 }),
|
||||
__metadata("design:type", Number)
|
||||
], Subscription.prototype, "monthlyRequestLimit", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'timestamp', nullable: true }),
|
||||
__metadata("design:type", Date)
|
||||
], Subscription.prototype, "currentPeriodStart", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'timestamp', nullable: true }),
|
||||
__metadata("design:type", Date)
|
||||
], Subscription.prototype, "currentPeriodEnd", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'timestamp', nullable: true }),
|
||||
__metadata("design:type", Date)
|
||||
], Subscription.prototype, "canceledAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], Subscription.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], Subscription.prototype, "updatedAt", void 0);
|
||||
exports.Subscription = Subscription = __decorate([
|
||||
(0, typeorm_1.Entity)('subscriptions')
|
||||
], Subscription);
|
||||
//# sourceMappingURL=subscription.entity.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"subscription.entity.js","sourceRoot":"","sources":["../../../src/billing/entities/subscription.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAQiB;AAGjB,IAAY,kBAKX;AALD,WAAY,kBAAkB;IAC5B,uCAAiB,CAAA;IACjB,2CAAqB,CAAA;IACrB,2CAAqB,CAAA;IACrB,2CAAqB,CAAA;AACvB,CAAC,EALW,kBAAkB,kCAAlB,kBAAkB,QAK7B;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEvB,EAAE,CAAS;IAIX,QAAQ,CAAS;IAGjB,IAAI,CAAS;IAOb,MAAM,CAAqB;IAG3B,mBAAmB,CAAS;IAG5B,kBAAkB,CAAO;IAGzB,gBAAgB,CAAO;IAGvB,UAAU,CAAO;IAGjB,SAAS,CAAO;IAGhB,SAAS,CAAO;CACjB,CAAA;AAnCY,oCAAY;AAEvB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;wCACpB;AAIX;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,GAAE;;8CACQ;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;;0CACf;AAOb;IALC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,kBAAkB,CAAC,MAAM;KACnC,CAAC;;4CACyB;AAG3B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;yDACX;AAG5B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BAC1B,IAAI;wDAAC;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BAC5B,IAAI;sDAAC;AAGvB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;8BAClC,IAAI;gDAAC;AAGjB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;+CAAC;AAGhB;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;+CAAC;uBAlCL,YAAY;IADxB,IAAA,gBAAM,EAAC,eAAe,CAAC;GACX,YAAY,CAmCxB"}
|
||||
@@ -1,23 +0,0 @@
|
||||
export declare enum PaymentStatus {
|
||||
PENDING = "PENDING",
|
||||
SUCCESS = "SUCCESS",
|
||||
FAILED = "FAILED",
|
||||
REFUNDED = "REFUNDED"
|
||||
}
|
||||
export declare enum PaymentProvider {
|
||||
PAYMOB = "PAYMOB",
|
||||
BINANCE = "BINANCE",
|
||||
MANUAL = "MANUAL"
|
||||
}
|
||||
export declare class Transaction {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
subscriptionId: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
provider: PaymentProvider;
|
||||
externalTransactionId: string;
|
||||
status: PaymentStatus;
|
||||
metadata: Record<string, any>;
|
||||
createdAt: Date;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
"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.Transaction = exports.PaymentProvider = exports.PaymentStatus = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
var PaymentStatus;
|
||||
(function (PaymentStatus) {
|
||||
PaymentStatus["PENDING"] = "PENDING";
|
||||
PaymentStatus["SUCCESS"] = "SUCCESS";
|
||||
PaymentStatus["FAILED"] = "FAILED";
|
||||
PaymentStatus["REFUNDED"] = "REFUNDED";
|
||||
})(PaymentStatus || (exports.PaymentStatus = PaymentStatus = {}));
|
||||
var PaymentProvider;
|
||||
(function (PaymentProvider) {
|
||||
PaymentProvider["PAYMOB"] = "PAYMOB";
|
||||
PaymentProvider["BINANCE"] = "BINANCE";
|
||||
PaymentProvider["MANUAL"] = "MANUAL";
|
||||
})(PaymentProvider || (exports.PaymentProvider = PaymentProvider = {}));
|
||||
let Transaction = class Transaction {
|
||||
id;
|
||||
tenantId;
|
||||
subscriptionId;
|
||||
amount;
|
||||
currency;
|
||||
provider;
|
||||
externalTransactionId;
|
||||
status;
|
||||
metadata;
|
||||
createdAt;
|
||||
};
|
||||
exports.Transaction = Transaction;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Index)(),
|
||||
(0, typeorm_1.Column)(),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "subscriptionId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'decimal', precision: 10, scale: 2 }),
|
||||
__metadata("design:type", Number)
|
||||
], Transaction.prototype, "amount", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ default: 'USD' }),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "currency", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
type: 'enum',
|
||||
enum: PaymentProvider,
|
||||
}),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "provider", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Index)(),
|
||||
(0, typeorm_1.Column)({ nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "externalTransactionId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
type: 'enum',
|
||||
enum: PaymentStatus,
|
||||
default: PaymentStatus.PENDING,
|
||||
}),
|
||||
__metadata("design:type", String)
|
||||
], Transaction.prototype, "status", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'jsonb', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Transaction.prototype, "metadata", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)(),
|
||||
__metadata("design:type", Date)
|
||||
], Transaction.prototype, "createdAt", void 0);
|
||||
exports.Transaction = Transaction = __decorate([
|
||||
(0, typeorm_1.Entity)('transactions')
|
||||
], Transaction);
|
||||
//# sourceMappingURL=transaction.entity.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"transaction.entity.js","sourceRoot":"","sources":["../../../src/billing/entities/transaction.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAMiB;AAEjB,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,oCAAmB,CAAA;IACnB,oCAAmB,CAAA;IACnB,kCAAiB,CAAA;IACjB,sCAAqB,CAAA;AACvB,CAAC,EALW,aAAa,6BAAb,aAAa,QAKxB;AAED,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,sCAAmB,CAAA;IACnB,oCAAiB,CAAA;AACnB,CAAC,EAJW,eAAe,+BAAf,eAAe,QAI1B;AAGM,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEtB,EAAE,CAAS;IAIX,QAAQ,CAAS;IAGjB,cAAc,CAAS;IAGvB,MAAM,CAAS;IAGf,QAAQ,CAAS;IAMjB,QAAQ,CAAkB;IAI1B,qBAAqB,CAAS;IAO9B,MAAM,CAAgB;IAGtB,QAAQ,CAAsB;IAG9B,SAAS,CAAO;CACjB,CAAA;AAvCY,kCAAW;AAEtB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;uCACpB;AAIX;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,GAAE;;6CACQ;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDACJ;AAGvB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;;2CACtC;AAGf;IADC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;6CACV;AAMjB;IAJC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,eAAe;KACtB,CAAC;;6CACwB;AAI1B;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0DACG;AAO9B;IALC,IAAA,gBAAM,EAAC;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,aAAa,CAAC,OAAO;KAC/B,CAAC;;2CACoB;AAGtB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;6CACZ;AAG9B;IADC,IAAA,0BAAgB,GAAE;8BACR,IAAI;8CAAC;sBAtCL,WAAW;IADvB,IAAA,gBAAM,EAAC,cAAc,CAAC;GACV,WAAW,CAuCvB"}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class BinanceProvider {
|
||||
private configService;
|
||||
private readonly logger;
|
||||
private readonly apiUrl;
|
||||
constructor(configService: ConfigService);
|
||||
private get apiKey();
|
||||
private get secretKey();
|
||||
private generateSignature;
|
||||
createOrder(tenantId: string, amount: number, plan: string): Promise<{
|
||||
checkoutUrl: any;
|
||||
orderId: string;
|
||||
prepayId: any;
|
||||
}>;
|
||||
verifySignature(timestamp: string, nonce: string, signature: string, payloadBody: any): boolean;
|
||||
}
|
||||
-150
@@ -1,150 +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);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var BinanceProvider_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BinanceProvider = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
const crypto = __importStar(require("crypto"));
|
||||
let BinanceProvider = BinanceProvider_1 = class BinanceProvider {
|
||||
configService;
|
||||
logger = new common_1.Logger(BinanceProvider_1.name);
|
||||
apiUrl = 'https://bpay.binanceapi.com/binancepay/openapi/v2/order';
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
}
|
||||
get apiKey() {
|
||||
return this.configService.get('BINANCE_PAY_API_KEY') || '';
|
||||
}
|
||||
get secretKey() {
|
||||
return this.configService.get('BINANCE_PAY_SECRET_KEY') || '';
|
||||
}
|
||||
generateSignature(timestamp, nonce, body) {
|
||||
const payload = timestamp + '\n' + nonce + '\n' + JSON.stringify(body) + '\n';
|
||||
return crypto
|
||||
.createHmac('sha512', this.secretKey)
|
||||
.update(payload)
|
||||
.digest('hex')
|
||||
.toUpperCase();
|
||||
}
|
||||
async createOrder(tenantId, amount, plan) {
|
||||
this.logger.log(`Creating Binance Pay order for ${tenantId} - ${plan}`);
|
||||
if (!this.apiKey || !this.secretKey) {
|
||||
this.logger.error('Binance Pay API keys are not configured');
|
||||
throw new common_1.InternalServerErrorException('Payment provider is not configured properly');
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('hex');
|
||||
const timestamp = Date.now().toString();
|
||||
const merchantTradeNo = `txn_${Date.now()}_${Math.floor(Math.random() * 10000)}`;
|
||||
const body = {
|
||||
env: {
|
||||
terminalType: 'WEB',
|
||||
},
|
||||
merchantTradeNo: merchantTradeNo,
|
||||
orderAmount: amount,
|
||||
currency: 'USDT',
|
||||
goods: {
|
||||
goodsType: '01',
|
||||
goodsCategory: 'Z000',
|
||||
referenceGoodsId: plan,
|
||||
goodsName: `${plan} Plan Subscription`,
|
||||
goodsDetail: `Subscription to ${plan} plan for Maps SaaS`,
|
||||
},
|
||||
passThroughInfo: JSON.stringify({ tenantId, plan }),
|
||||
returnUrl: `https://map-dashboard.intaleqapp.com/dashboard.html#billing`,
|
||||
};
|
||||
const signature = this.generateSignature(timestamp, nonce, body);
|
||||
try {
|
||||
const response = await axios_1.default.post(this.apiUrl, body, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'BinancePay-Timestamp': timestamp,
|
||||
'BinancePay-Nonce': nonce,
|
||||
'BinancePay-Certificate-SN': this.apiKey,
|
||||
'BinancePay-Signature': signature,
|
||||
},
|
||||
});
|
||||
if (response.data && response.data.status === 'SUCCESS') {
|
||||
return {
|
||||
checkoutUrl: response.data.data.checkoutUrl,
|
||||
orderId: merchantTradeNo,
|
||||
prepayId: response.data.data.prepayId,
|
||||
};
|
||||
}
|
||||
else {
|
||||
this.logger.error(`Binance API Error: ${JSON.stringify(response.data)}`);
|
||||
throw new common_1.InternalServerErrorException('Failed to create Binance order');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Error communicating with Binance API: ${error.message}`);
|
||||
throw new common_1.InternalServerErrorException('Failed to communicate with payment provider');
|
||||
}
|
||||
}
|
||||
verifySignature(timestamp, nonce, signature, payloadBody) {
|
||||
const payload = timestamp + '\n' + nonce + '\n' + JSON.stringify(payloadBody) + '\n';
|
||||
const expectedSignature = crypto
|
||||
.createHmac('sha512', this.secretKey)
|
||||
.update(payload)
|
||||
.digest('hex')
|
||||
.toUpperCase();
|
||||
try {
|
||||
return crypto.timingSafeEqual(Buffer.from(signature || ''), Buffer.from(expectedSignature));
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.BinanceProvider = BinanceProvider;
|
||||
exports.BinanceProvider = BinanceProvider = BinanceProvider_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], BinanceProvider);
|
||||
//# sourceMappingURL=binance.provider.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"binance.provider.js","sourceRoot":"","sources":["../../../src/billing/providers/binance.provider.ts"],"names":[],"mappings":"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"}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class PayMobProvider {
|
||||
private configService;
|
||||
private readonly logger;
|
||||
private readonly baseUrl;
|
||||
constructor(configService: ConfigService);
|
||||
createPaymentKey(tenantId: string, amount: number, plan: string): Promise<{
|
||||
paymentKey: string;
|
||||
orderId: string;
|
||||
}>;
|
||||
getTransactionDetails(transactionId: string): Promise<any>;
|
||||
private getAuthToken;
|
||||
verifyHmac(payload: any, hmac: string): boolean;
|
||||
}
|
||||
-179
@@ -1,179 +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);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var PayMobProvider_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PayMobProvider = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
const crypto = __importStar(require("crypto"));
|
||||
let PayMobProvider = PayMobProvider_1 = class PayMobProvider {
|
||||
configService;
|
||||
logger = new common_1.Logger(PayMobProvider_1.name);
|
||||
baseUrl = 'https://accept.paymob.com/api';
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
}
|
||||
async createPaymentKey(tenantId, amount, plan) {
|
||||
try {
|
||||
const authToken = await this.getAuthToken();
|
||||
const orderRes = await axios_1.default.post(`${this.baseUrl}/ecommerce/orders`, {
|
||||
auth_token: authToken,
|
||||
delivery_needed: "false",
|
||||
amount_cents: amount * 50 * 100,
|
||||
currency: "EGP",
|
||||
items: [{
|
||||
name: `${plan} Subscription`,
|
||||
amount_cents: amount * 50 * 100,
|
||||
description: `Intaleq Maps ${plan} Plan`
|
||||
}],
|
||||
shipping_data: {
|
||||
first_name: "Intaleq",
|
||||
last_name: "User",
|
||||
email: "user@intaleq.com",
|
||||
phone_number: "+201000000000",
|
||||
extra_description: `${tenantId}|${plan}`
|
||||
}
|
||||
});
|
||||
const orderId = orderRes.data.id;
|
||||
const keyRes = await axios_1.default.post(`${this.baseUrl}/acceptance/payment_keys`, {
|
||||
auth_token: authToken,
|
||||
amount_cents: amount * 50 * 100,
|
||||
expiration: 3600,
|
||||
order_id: orderId,
|
||||
billing_data: {
|
||||
apartment: "NA",
|
||||
email: "user@intaleq.com",
|
||||
floor: "NA",
|
||||
first_name: "Intaleq",
|
||||
street: "NA",
|
||||
building: "NA",
|
||||
phone_number: "+201000000000",
|
||||
shipping_method: "NA",
|
||||
postal_code: "NA",
|
||||
city: "NA",
|
||||
country: "NA",
|
||||
last_name: "User",
|
||||
state: "NA"
|
||||
},
|
||||
currency: "EGP",
|
||||
integration_id: this.configService.get('PAYMOB_INTEGRATION_ID') || 4556055,
|
||||
lock_order_when_paid: "false"
|
||||
});
|
||||
return {
|
||||
paymentKey: keyRes.data.token,
|
||||
orderId: orderId.toString()
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`PayMob Payment Key failed: ${error.response?.data ? JSON.stringify(error.response.data) : error.message}`);
|
||||
throw new common_1.BadRequestException('Failed to initialize PayMob payment');
|
||||
}
|
||||
}
|
||||
async getTransactionDetails(transactionId) {
|
||||
try {
|
||||
const authToken = await this.getAuthToken();
|
||||
const res = await axios_1.default.get(`${this.baseUrl}/acceptance/transactions/${transactionId}`, {
|
||||
headers: { Authorization: `Bearer ${authToken}` }
|
||||
});
|
||||
return res.data;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Failed to fetch PayMob transaction ${transactionId}: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async getAuthToken() {
|
||||
const authRes = await axios_1.default.post(`${this.baseUrl}/auth/tokens`, {
|
||||
api_key: this.configService.get('PAYMOB_API_KEY'),
|
||||
});
|
||||
return authRes.data.token;
|
||||
}
|
||||
verifyHmac(payload, hmac) {
|
||||
const secret = this.configService.get('PAYMOB_HMAC_SECRET');
|
||||
if (!secret)
|
||||
return false;
|
||||
const { amount_cents, created_at, currency, error_occured, has_parent_transaction, id, integration_id, is_3d_secure, is_auth, is_capture, is_refunded, is_standalone_payment, is_voided, order, owner, pending, success } = payload;
|
||||
const source_pan = payload.source_data?.pan || "";
|
||||
const source_sub_type = payload.source_data?.sub_type || "";
|
||||
const source_type = payload.source_data?.type || "";
|
||||
const data = [
|
||||
amount_cents,
|
||||
created_at,
|
||||
currency,
|
||||
error_occured,
|
||||
has_parent_transaction,
|
||||
id,
|
||||
integration_id,
|
||||
is_3d_secure,
|
||||
is_auth,
|
||||
is_capture,
|
||||
is_refunded,
|
||||
is_standalone_payment,
|
||||
is_voided,
|
||||
order.id || order,
|
||||
owner,
|
||||
pending,
|
||||
source_pan,
|
||||
source_sub_type,
|
||||
source_type,
|
||||
success
|
||||
].join("");
|
||||
const hash = crypto
|
||||
.createHmac('sha512', secret)
|
||||
.update(data)
|
||||
.digest('hex');
|
||||
return hash === hmac;
|
||||
}
|
||||
};
|
||||
exports.PayMobProvider = PayMobProvider;
|
||||
exports.PayMobProvider = PayMobProvider = PayMobProvider_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], PayMobProvider);
|
||||
//# sourceMappingURL=paymob.provider.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"paymob.provider.js","sourceRoot":"","sources":["../../../src/billing/providers/paymob.provider.ts"],"names":[],"mappings":"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"}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class CacheService {
|
||||
private configService;
|
||||
private client;
|
||||
constructor(configService: ConfigService);
|
||||
set(key: string, value: any, ttlSeconds?: number): Promise<void>;
|
||||
get(key: string): Promise<any>;
|
||||
del(key: string): Promise<void>;
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
"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 _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CacheService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const redis_1 = require("redis");
|
||||
const config_1 = require("@nestjs/config");
|
||||
let CacheService = class CacheService {
|
||||
configService;
|
||||
client;
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
const redisUrl = this.configService.get('REDIS_URL', 'redis://redis:6379');
|
||||
this.client = (0, redis_1.createClient)({ url: redisUrl });
|
||||
this.client.connect().catch(console.error);
|
||||
}
|
||||
async set(key, value, ttlSeconds = 3600) {
|
||||
await this.client.set(key, JSON.stringify(value), {
|
||||
EX: ttlSeconds,
|
||||
});
|
||||
}
|
||||
async get(key) {
|
||||
const data = await this.client.get(key);
|
||||
return data ? JSON.parse(data) : null;
|
||||
}
|
||||
async del(key) {
|
||||
await this.client.del(key);
|
||||
}
|
||||
};
|
||||
exports.CacheService = CacheService;
|
||||
exports.CacheService = CacheService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], CacheService);
|
||||
//# sourceMappingURL=cache.service.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"cache.service.js","sourceRoot":"","sources":["../../src/common/cache.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,iCAAqC;AACrC,2CAA+C;AAGxC,IAAM,YAAY,GAAlB,MAAM,YAAY;IAGH;IAFZ,MAAM,CAAC;IAEf,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,IAAA,oBAAY,EAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,aAAqB,IAAI;QAG1D,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;YAChD,EAAE,EAAE,UAAU;SACf,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QAGnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF,CAAA;AA3BY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;yDAIwB,sBAAa,oBAAb,sBAAa;GAHrC,YAAY,CA2BxB"}
|
||||
Vendored
-8
@@ -1,8 +0,0 @@
|
||||
export declare const JORDAN_BOUNDS: {
|
||||
minLat: number;
|
||||
maxLat: number;
|
||||
minLng: number;
|
||||
maxLng: number;
|
||||
};
|
||||
export declare function isWithinJordan(lat: number, lng: number): boolean;
|
||||
export declare function mockMapMatch(lat: number, lng: number): string;
|
||||
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.JORDAN_BOUNDS = void 0;
|
||||
exports.isWithinJordan = isWithinJordan;
|
||||
exports.mockMapMatch = mockMapMatch;
|
||||
exports.JORDAN_BOUNDS = {
|
||||
minLat: 29.1,
|
||||
maxLat: 33.4,
|
||||
minLng: 34.9,
|
||||
maxLng: 39.3,
|
||||
};
|
||||
function isWithinJordan(lat, lng) {
|
||||
return (lat >= exports.JORDAN_BOUNDS.minLat &&
|
||||
lat <= exports.JORDAN_BOUNDS.maxLat &&
|
||||
lng >= exports.JORDAN_BOUNDS.minLng &&
|
||||
lng <= exports.JORDAN_BOUNDS.maxLng);
|
||||
}
|
||||
function mockMapMatch(lat, lng) {
|
||||
return `osm_way_${Math.floor(Math.random() * 1000000)}`;
|
||||
}
|
||||
//# sourceMappingURL=gis.utils.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"gis.utils.js","sourceRoot":"","sources":["../../src/common/gis.utils.ts"],"names":[],"mappings":";;;AAYA,wCAOC;AAMD,oCAGC;AAvBY,QAAA,aAAa,GAAG;IAC3B,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,SAAgB,cAAc,CAAC,GAAW,EAAE,GAAW;IACrD,OAAO,CACL,GAAG,IAAI,qBAAa,CAAC,MAAM;QAC3B,GAAG,IAAI,qBAAa,CAAC,MAAM;QAC3B,GAAG,IAAI,qBAAa,CAAC,MAAM;QAC3B,GAAG,IAAI,qBAAa,CAAC,MAAM,CAC5B,CAAC;AACJ,CAAC;AAMD,SAAgB,YAAY,CAAC,GAAW,EAAE,GAAW;IAEnD,OAAO,WAAW,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;AAC1D,CAAC"}
|
||||
@@ -1,4 +0,0 @@
|
||||
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
export declare class AdminGuard implements CanActivate {
|
||||
canActivate(context: ExecutionContext): boolean;
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
"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.AdminGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const tenant_entity_1 = require("../../auth/entities/tenant.entity");
|
||||
let AdminGuard = class AdminGuard {
|
||||
canActivate(context) {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const tenant = request['tenant'];
|
||||
if (!tenant) {
|
||||
throw new common_1.UnauthorizedException('Tenant not found in request');
|
||||
}
|
||||
if (tenant.plan !== tenant_entity_1.TenantPlan.ENTERPRISE) {
|
||||
throw new common_1.ForbiddenException('Admin access required. Your tenant plan must be ENTERPRISE.');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
exports.AdminGuard = AdminGuard;
|
||||
exports.AdminGuard = AdminGuard = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], AdminGuard);
|
||||
//# sourceMappingURL=admin.guard.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"admin.guard.js","sourceRoot":"","sources":["../../../src/common/guards/admin.guard.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAsH;AACtH,qEAA+D;AAGxD,IAAM,UAAU,GAAhB,MAAM,UAAU;IACrB,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,8BAAqB,CAAC,6BAA6B,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,0BAAU,CAAC,UAAU,EAAE,CAAC;YAC1C,MAAM,IAAI,2BAAkB,CAAC,6DAA6D,CAAC,CAAC;QAC9F,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAfY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;GACA,UAAU,CAetB"}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
import { AuthService } from '../../auth/auth.service';
|
||||
export declare class ApiKeyGuard implements CanActivate {
|
||||
private authService;
|
||||
constructor(authService: AuthService);
|
||||
canActivate(context: ExecutionContext): Promise<boolean>;
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
"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.ApiKeyGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const auth_service_1 = require("../../auth/auth.service");
|
||||
let ApiKeyGuard = class ApiKeyGuard {
|
||||
authService;
|
||||
constructor(authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
async canActivate(context) {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const apiKeyHeader = request.headers['x-api-key'] || request.query['api_key'];
|
||||
if (!apiKeyHeader) {
|
||||
throw new common_1.UnauthorizedException('API Key (x-api-key) is missing');
|
||||
}
|
||||
const origin = request.headers['origin'];
|
||||
const referer = request.headers['referer'];
|
||||
try {
|
||||
const { tenant, apiKey, rateLimit } = await this.authService.validateApiKey(apiKeyHeader, origin, referer);
|
||||
request['tenant'] = tenant;
|
||||
request['apiKey'] = apiKey;
|
||||
request['rateLimit'] = rateLimit;
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
throw new common_1.UnauthorizedException(error.message || 'Invalid API Key');
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.ApiKeyGuard = ApiKeyGuard;
|
||||
exports.ApiKeyGuard = ApiKeyGuard = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
||||
], ApiKeyGuard);
|
||||
//# sourceMappingURL=api-key.guard.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"api-key.guard.js","sourceRoot":"","sources":["../../../src/common/guards/api-key.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AACxB,0DAAsD;AAG/C,IAAM,WAAW,GAAjB,MAAM,WAAW;IACF;IAApB,YAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAEhD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAGpD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAE9E,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,8BAAqB,CAAC,gCAAgC,CAAC,CAAC;QACpE,CAAC;QAGD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE3C,IAAI,CAAC;YAEH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CACzE,YAAY,EACZ,MAAM,EACN,OAAO,CACR,CAAC;YAGF,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;YAC3B,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;YAEjC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,8BAAqB,CAAC,KAAK,CAAC,OAAO,IAAI,iBAAiB,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;CACF,CAAA;AAnCY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEsB,0BAAW;GADjC,WAAW,CAmCvB"}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { ThrottlerGuard, ThrottlerRequest } from '@nestjs/throttler';
|
||||
export declare class TenantThrottlerGuard extends ThrottlerGuard {
|
||||
private readonly logger;
|
||||
protected getTracker(req: Record<string, any>): Promise<string>;
|
||||
protected handleRequest(requestProps: ThrottlerRequest): Promise<boolean>;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
"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 TenantThrottlerGuard_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TenantThrottlerGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const throttler_1 = require("@nestjs/throttler");
|
||||
let TenantThrottlerGuard = TenantThrottlerGuard_1 = class TenantThrottlerGuard extends throttler_1.ThrottlerGuard {
|
||||
logger = new common_1.Logger(TenantThrottlerGuard_1.name);
|
||||
async getTracker(req) {
|
||||
const apiKeyId = req['apiKey']?.id || req.ip;
|
||||
return `throttler:key:${apiKeyId}`;
|
||||
}
|
||||
async handleRequest(requestProps) {
|
||||
const { context, limit, ttl } = requestProps;
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const dynamicLimit = request['rateLimit'];
|
||||
if (dynamicLimit) {
|
||||
this.logger.debug(`Applying dynamic rate limit: ${dynamicLimit} req/min for key ${request['apiKey']?.id}`);
|
||||
requestProps.limit = dynamicLimit;
|
||||
}
|
||||
else {
|
||||
this.logger.debug(`Applying default rate limit: ${limit} req/min`);
|
||||
}
|
||||
return super.handleRequest(requestProps);
|
||||
}
|
||||
};
|
||||
exports.TenantThrottlerGuard = TenantThrottlerGuard;
|
||||
exports.TenantThrottlerGuard = TenantThrottlerGuard = TenantThrottlerGuard_1 = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], TenantThrottlerGuard);
|
||||
//# sourceMappingURL=rate-limiter.guard.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"rate-limiter.guard.js","sourceRoot":"","sources":["../../../src/common/guards/rate-limiter.guard.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAsE;AACtE,iDAAqE;AAG9D,IAAM,oBAAoB,4BAA1B,MAAM,oBAAqB,SAAQ,0BAAc;IACrC,MAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAEtD,KAAK,CAAC,UAAU,CAAC,GAAwB;QACjD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,iBAAiB,QAAQ,EAAE,CAAC;IACrC,CAAC;IAES,KAAK,CAAC,aAAa,CAC3B,YAA8B;QAE9B,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC;QAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAGpD,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAE1C,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,YAAY,oBAAoB,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3G,YAAY,CAAC,KAAK,GAAG,YAAY,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,KAAK,UAAU,CAAC,CAAC;QACrE,CAAC;QAED,OAAO,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;CACF,CAAA;AA1BY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;GACA,oBAAoB,CA0BhC"}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export declare class MailModule {
|
||||
}
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
"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.MailModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const mail_service_1 = require("./mail.service");
|
||||
let MailModule = class MailModule {
|
||||
};
|
||||
exports.MailModule = MailModule;
|
||||
exports.MailModule = MailModule = __decorate([
|
||||
(0, common_1.Global)(),
|
||||
(0, common_1.Module)({
|
||||
providers: [mail_service_1.MailService],
|
||||
exports: [mail_service_1.MailService],
|
||||
})
|
||||
], MailModule);
|
||||
//# sourceMappingURL=mail.module.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"mail.module.js","sourceRoot":"","sources":["../../src/common/mail.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,iDAA6C;AAOtC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IALtB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,0BAAW,CAAC;QACxB,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class MailService {
|
||||
private configService;
|
||||
private readonly logger;
|
||||
private transporter;
|
||||
constructor(configService: ConfigService);
|
||||
sendInvoiceEmail(to: string, data: {
|
||||
tenantName: string;
|
||||
plan: string;
|
||||
amount: string;
|
||||
transactionId: string;
|
||||
}): Promise<boolean>;
|
||||
}
|
||||
Vendored
-122
@@ -1,122 +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);
|
||||
};
|
||||
var MailService_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MailService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const nodemailer = __importStar(require("nodemailer"));
|
||||
let MailService = MailService_1 = class MailService {
|
||||
configService;
|
||||
logger = new common_1.Logger(MailService_1.name);
|
||||
transporter;
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
const host = this.configService.get('SMTP_HOST');
|
||||
const port = this.configService.get('SMTP_PORT') || 587;
|
||||
const user = this.configService.get('SMTP_USER');
|
||||
const pass = this.configService.get('SMTP_PASS');
|
||||
if (host && user && pass) {
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host,
|
||||
port,
|
||||
secure: port === 465,
|
||||
auth: {
|
||||
user,
|
||||
pass,
|
||||
},
|
||||
});
|
||||
this.logger.log(`📧 MailService initialized with host: ${host}`);
|
||||
}
|
||||
else {
|
||||
this.logger.warn('⚠️ SMTP settings not fully configured. MailService will run in mock mode.');
|
||||
}
|
||||
}
|
||||
async sendInvoiceEmail(to, data) {
|
||||
const from = this.configService.get('SMTP_FROM') || 'support@intaleqapp.com';
|
||||
const htmlContent = `
|
||||
<div style="font-family: sans-serif; max-width: 600px; margin: auto; border: 1px solid #eee; padding: 20px; border-radius: 10px;">
|
||||
<h2 style="color: #2563eb;">Intaleq Maps - Payment Successful</h2>
|
||||
<p>Hello <b>${data.tenantName}</b>,</p>
|
||||
<p>Thank you for subscribing to our <b>${data.plan}</b> plan. Your payment has been processed successfully.</p>
|
||||
|
||||
<div style="background: #f8fafc; padding: 15px; border-radius: 8px; margin: 20px 0;">
|
||||
<p style="margin: 5px 0;"><b>Plan:</b> ${data.plan}</p>
|
||||
<p style="margin: 5px 0;"><b>Amount:</b> ${data.amount}</p>
|
||||
<p style="margin: 5px 0;"><b>Transaction ID:</b> ${data.transactionId}</p>
|
||||
<p style="margin: 5px 0;"><b>Date:</b> ${new Date().toLocaleDateString()}</p>
|
||||
</div>
|
||||
|
||||
<p>You can now access all your premium features from your dashboard.</p>
|
||||
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
|
||||
<p style="font-size: 12px; color: #64748b;">If you have any questions, contact us at ${from}</p>
|
||||
</div>
|
||||
`;
|
||||
if (!this.transporter) {
|
||||
this.logger.warn(`[Mock Email] To: ${to}, Plan: ${data.plan}, Amount: ${data.amount}`);
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
await this.transporter.sendMail({
|
||||
from: `"Intaleq Support" <${from}>`,
|
||||
to,
|
||||
subject: `Invoice: ${data.plan} Subscription - Intaleq Maps`,
|
||||
html: htmlContent,
|
||||
});
|
||||
this.logger.log(`✅ Invoice email sent to ${to}`);
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`❌ Failed to send email: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.MailService = MailService;
|
||||
exports.MailService = MailService = MailService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], MailService);
|
||||
//# sourceMappingURL=mail.service.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"mail.service.js","sourceRoot":"","sources":["../../src/common/mail.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA+C;AAC/C,uDAAyC;AAGlC,IAAM,WAAW,mBAAjB,MAAM,WAAW;IAIF;IAHH,MAAM,GAAG,IAAI,eAAM,CAAC,aAAW,CAAC,IAAI,CAAC,CAAC;IAC/C,WAAW,CAAyB;IAE5C,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,IAAI,GAAG,CAAC;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,CAAC;QAEzD,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC;gBAC5C,IAAI;gBACJ,IAAI;gBACJ,MAAM,EAAE,IAAI,KAAK,GAAG;gBACpB,IAAI,EAAE;oBACJ,IAAI;oBACJ,IAAI;iBACL;aACF,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAU,EAAE,IAKlC;QACC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,IAAI,wBAAwB,CAAC;QAErF,MAAM,WAAW,GAAG;;;sBAGF,IAAI,CAAC,UAAU;iDACY,IAAI,CAAC,IAAI;;;mDAGP,IAAI,CAAC,IAAI;qDACP,IAAI,CAAC,MAAM;6DACH,IAAI,CAAC,aAAa;mDAC5B,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE;;;;;+FAKa,IAAI;;KAE9F,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,WAAW,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACvF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;gBAC9B,IAAI,EAAE,sBAAsB,IAAI,GAAG;gBACnC,EAAE;gBACF,OAAO,EAAE,YAAY,IAAI,CAAC,IAAI,8BAA8B;gBAC5D,IAAI,EAAE,WAAW;aAClB,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9D,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF,CAAA;AAxEY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;yDAKwB,sBAAa,oBAAb,sBAAa;GAJrC,WAAW,CAwEvB"}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
export declare class RedisModule {
|
||||
}
|
||||
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
"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.RedisModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const redis_1 = require("redis");
|
||||
const redis_service_1 = require("./redis.service");
|
||||
let RedisModule = class RedisModule {
|
||||
};
|
||||
exports.RedisModule = RedisModule;
|
||||
exports.RedisModule = RedisModule = __decorate([
|
||||
(0, common_1.Global)(),
|
||||
(0, common_1.Module)({
|
||||
providers: [
|
||||
{
|
||||
provide: 'REDIS_CLIENT',
|
||||
useFactory: async (configService) => {
|
||||
const url = configService.get('REDIS_URL', 'redis://redis:6379');
|
||||
const client = (0, redis_1.createClient)({ url });
|
||||
await client.connect();
|
||||
return client;
|
||||
},
|
||||
inject: [config_1.ConfigService],
|
||||
},
|
||||
redis_service_1.RedisService,
|
||||
],
|
||||
exports: ['REDIS_CLIENT', redis_service_1.RedisService],
|
||||
})
|
||||
], RedisModule);
|
||||
//# sourceMappingURL=redis.module.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"redis.module.js","sourceRoot":"","sources":["../../src/common/redis.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,2CAA+C;AAC/C,iCAAqC;AACrC,mDAA+C;AAwBxC,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IAjBvB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAAE,EAAE;oBACjD,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAS,WAAW,EAAE,oBAAoB,CAAC,CAAC;oBACzE,MAAM,MAAM,GAAG,IAAA,oBAAY,EAAC,EAAE,GAAG,EAAE,CAAC,CAAC;oBACrC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO,MAAM,CAAC;gBAChB,CAAC;gBACD,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB;YACD,4BAAY;SACb;QACD,OAAO,EAAE,CAAC,cAAc,EAAE,4BAAY,CAAC;KACxC,CAAC;GACW,WAAW,CAAG"}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
import { OnModuleDestroy } from '@nestjs/common';
|
||||
import type { RedisClientType } from 'redis';
|
||||
export declare class RedisService implements OnModuleDestroy {
|
||||
private readonly redisClient;
|
||||
constructor(redisClient: RedisClientType);
|
||||
getClient(): RedisClientType;
|
||||
set(key: string, value: any, ttlSeconds?: number): Promise<void>;
|
||||
get<T>(key: string): Promise<T | null>;
|
||||
del(key: string): Promise<void>;
|
||||
onModuleDestroy(): Promise<void>;
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
"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.RedisService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
let RedisService = class RedisService {
|
||||
redisClient;
|
||||
constructor(redisClient) {
|
||||
this.redisClient = redisClient;
|
||||
}
|
||||
getClient() {
|
||||
return this.redisClient;
|
||||
}
|
||||
async set(key, value, ttlSeconds) {
|
||||
const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
|
||||
if (ttlSeconds) {
|
||||
await this.redisClient.set(key, stringValue, { EX: ttlSeconds });
|
||||
}
|
||||
else {
|
||||
await this.redisClient.set(key, stringValue);
|
||||
}
|
||||
}
|
||||
async get(key) {
|
||||
const value = await this.redisClient.get(key);
|
||||
if (!value)
|
||||
return null;
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
async del(key) {
|
||||
await this.redisClient.del(key);
|
||||
}
|
||||
async onModuleDestroy() {
|
||||
await this.redisClient.quit();
|
||||
}
|
||||
};
|
||||
exports.RedisService = RedisService;
|
||||
exports.RedisService = RedisService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, common_1.Inject)('REDIS_CLIENT')),
|
||||
__metadata("design:paramtypes", [Object])
|
||||
], RedisService);
|
||||
//# sourceMappingURL=redis.service.js.map
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"redis.service.js","sourceRoot":"","sources":["../../src/common/redis.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAqE;AAS9D,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEoB;IAD3C,YAC2C,WAA4B;QAA5B,gBAAW,GAAX,WAAW,CAAiB;IACpE,CAAC;IAKJ,SAAS;QACP,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAMD,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAU,EAAE,UAAmB;QACpD,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAMD,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAqB,CAAC;QAC/B,CAAC;IACH,CAAC;IAMD,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;CACF,CAAA;AAnDY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,cAAc,CAAC,CAAA;;GAFd,YAAY,CAmDxB"}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class TelegramService {
|
||||
private configService;
|
||||
private readonly logger;
|
||||
private readonly botToken;
|
||||
private readonly chatId;
|
||||
constructor(configService: ConfigService);
|
||||
sendMessage(text: string): Promise<boolean>;
|
||||
sendIntelligenceReport(stats: {
|
||||
syncResult: number;
|
||||
updatedSegments: number;
|
||||
discoveredRoads: number;
|
||||
totalPoints: number;
|
||||
days: number;
|
||||
timeProfiles?: number;
|
||||
}): Promise<boolean>;
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
"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 __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var TelegramService_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TelegramService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
let TelegramService = TelegramService_1 = class TelegramService {
|
||||
configService;
|
||||
logger = new common_1.Logger(TelegramService_1.name);
|
||||
botToken;
|
||||
chatId;
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
this.botToken = this.configService.get('TELEGRAM_BOT_TOKEN') || '';
|
||||
this.chatId = this.configService.get('TELEGRAM_CHAT_ID') || '';
|
||||
}
|
||||
async sendMessage(text) {
|
||||
if (!this.botToken || !this.chatId || this.botToken.includes('YOUR_BOT_TOKEN')) {
|
||||
this.logger.warn('Telegram Bot Token or Chat ID not configured. Skipping notification.');
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
this.logger.log('Sending report to Telegram...');
|
||||
const url = `https://api.telegram.org/bot${this.botToken}/sendMessage`;
|
||||
await axios_1.default.post(url, {
|
||||
chat_id: this.chatId,
|
||||
text: text,
|
||||
parse_mode: 'HTML',
|
||||
});
|
||||
this.logger.log('✅ Telegram notification sent successfully.');
|
||||
return true;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`❌ Failed to send Telegram message: ${error.message}`);
|
||||
if (error.response) {
|
||||
this.logger.error(`Status: ${error.response.status}, Data: ${JSON.stringify(error.response.data)}`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async sendIntelligenceReport(stats) {
|
||||
const message = `
|
||||
🚀 <b>Intaleq Map Intelligence Report</b>
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
📅 <b>Window:</b> Last ${stats.days} days
|
||||
📥 <b>Tracks Imported:</b> ${stats.syncResult} points
|
||||
🛣️ <b>Roads Updated:</b> ${stats.updatedSegments} segments
|
||||
✨ <b>New Roads Found:</b> ${stats.discoveredRoads} candidates
|
||||
🕒 <b>Time Profiles:</b> ${stats.timeProfiles || 0} buckets
|
||||
📍 <b>Database Total:</b> ${stats.totalPoints} points
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
✅ <i>Deep Sync and Analysis Complete.</i>
|
||||
`;
|
||||
return this.sendMessage(message);
|
||||
}
|
||||
};
|
||||
exports.TelegramService = TelegramService;
|
||||
exports.TelegramService = TelegramService = TelegramService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof config_1.ConfigService !== "undefined" && config_1.ConfigService) === "function" ? _a : Object])
|
||||
], TelegramService);
|
||||
//# sourceMappingURL=telegram.service.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"telegram.service.js","sourceRoot":"","sources":["../../src/common/telegram.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA+C;AAC/C,kDAA0B;AAGnB,IAAM,eAAe,uBAArB,MAAM,eAAe;IAKN;IAJH,MAAM,GAAG,IAAI,eAAM,CAAC,iBAAe,CAAC,IAAI,CAAC,CAAC;IAC1C,QAAQ,CAAS;IACjB,MAAM,CAAS;IAEhC,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,oBAAoB,CAAC,IAAI,EAAE,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,kBAAkB,CAAC,IAAI,EAAE,CAAC;IACzE,CAAC;IAMD,KAAK,CAAC,WAAW,CAAC,IAAY;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC/E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;YACzF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;YACjD,MAAM,GAAG,GAAG,+BAA+B,IAAI,CAAC,QAAQ,cAAc,CAAC;YACvE,MAAM,eAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACpB,OAAO,EAAE,IAAI,CAAC,MAAM;gBACpB,IAAI,EAAE,IAAI;gBACV,UAAU,EAAE,MAAM;aACnB,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACzE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC,QAAQ,CAAC,MAAM,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtG,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAKD,KAAK,CAAC,sBAAsB,CAAC,KAO5B;QACC,MAAM,OAAO,GAAG;;;yBAGK,KAAK,CAAC,IAAI;6BACN,KAAK,CAAC,UAAU;4BACjB,KAAK,CAAC,eAAe;4BACrB,KAAK,CAAC,eAAe;2BACtB,KAAK,CAAC,YAAY,IAAI,CAAC;4BACtB,KAAK,CAAC,WAAW;;;KAGxC,CAAC;QACF,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;CACF,CAAA;AAhEY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;yDAMwB,sBAAa,oBAAb,sBAAa;GALrC,eAAe,CAgE3B"}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Repository } from 'typeorm';
|
||||
import { AdminBoundary } from './entities/admin-boundary.entity';
|
||||
export declare class AdminBoundariesService {
|
||||
private adminBoundaryRepo;
|
||||
private readonly logger;
|
||||
constructor(adminBoundaryRepo: Repository<AdminBoundary>);
|
||||
importGeoJSON(targetCountryCode: string, geoJson: any): Promise<{
|
||||
success: boolean;
|
||||
imported: number;
|
||||
errors: number;
|
||||
skipped: number;
|
||||
}>;
|
||||
importFromFile(countryCode: string, filePath: string): Promise<{
|
||||
success: boolean;
|
||||
imported: number;
|
||||
errors: number;
|
||||
skipped: number;
|
||||
}>;
|
||||
}
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
"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); }
|
||||
};
|
||||
var AdminBoundariesService_1;
|
||||
var _a;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AdminBoundariesService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const admin_boundary_entity_1 = require("./entities/admin-boundary.entity");
|
||||
let AdminBoundariesService = AdminBoundariesService_1 = class AdminBoundariesService {
|
||||
adminBoundaryRepo;
|
||||
logger = new common_1.Logger(AdminBoundariesService_1.name);
|
||||
constructor(adminBoundaryRepo) {
|
||||
this.adminBoundaryRepo = adminBoundaryRepo;
|
||||
}
|
||||
async importGeoJSON(targetCountryCode, geoJson) {
|
||||
this.logger.log(`Importing admin boundaries for ${targetCountryCode}...`);
|
||||
let imported = 0;
|
||||
let errors = 0;
|
||||
let skipped = 0;
|
||||
if (!geoJson || !geoJson.features || !Array.isArray(geoJson.features)) {
|
||||
this.logger.error('Invalid GeoJSON format');
|
||||
return { success: false, imported: 0, errors: 1, skipped: 0 };
|
||||
}
|
||||
for (const feature of geoJson.features) {
|
||||
try {
|
||||
const props = feature.properties || {};
|
||||
const countryCode = props.country || props.iso_3166_1_alpha2;
|
||||
if (targetCountryCode && countryCode && countryCode.toUpperCase() !== targetCountryCode.toUpperCase()) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
const subtype = (props.subtype || '').toLowerCase();
|
||||
let adminLevel;
|
||||
switch (subtype) {
|
||||
case 'country':
|
||||
adminLevel = 2;
|
||||
break;
|
||||
case 'region':
|
||||
adminLevel = 4;
|
||||
break;
|
||||
case 'county':
|
||||
adminLevel = 6;
|
||||
break;
|
||||
case 'localadmin':
|
||||
adminLevel = 8;
|
||||
break;
|
||||
case 'locality':
|
||||
adminLevel = 8;
|
||||
break;
|
||||
case 'neighborhood':
|
||||
adminLevel = 10;
|
||||
break;
|
||||
case 'macrohood':
|
||||
adminLevel = 9;
|
||||
break;
|
||||
case 'microhood':
|
||||
adminLevel = 11;
|
||||
break;
|
||||
default:
|
||||
adminLevel = parseInt(props.admin_level || props.adminLevel, 10);
|
||||
}
|
||||
if (isNaN(adminLevel)) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
const nameAr = props['names']?.['primary'] || props['names']?.['common'] || props['name_ar'] || props['name'];
|
||||
const nameEn = props['names']?.['en'] || props['name_en'];
|
||||
const isArabic = (text) => /[\u0600-\u06FF]/.test(text);
|
||||
if (['JO', 'SY', 'EG'].includes(targetCountryCode.toUpperCase()) && nameAr && !isArabic(nameAr)) {
|
||||
const alternativeAr = Object.values(props['names'] || {}).find(v => typeof v === 'string' && isArabic(v));
|
||||
if (!alternativeAr) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let geom = feature.geometry;
|
||||
if (geom.type === 'Polygon') {
|
||||
geom = { type: 'MultiPolygon', coordinates: [geom.coordinates] };
|
||||
}
|
||||
else if (geom.type !== 'MultiPolygon') {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
const boundary = this.adminBoundaryRepo.create({
|
||||
country_code: targetCountryCode.toUpperCase(),
|
||||
admin_level: adminLevel,
|
||||
name_ar: nameAr,
|
||||
name_en: nameEn,
|
||||
geom: geom,
|
||||
});
|
||||
await this.adminBoundaryRepo.save(boundary);
|
||||
imported++;
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error(`Error importing feature: ${err.message}`);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
this.logger.log(`Import finished. Imported: ${imported}, Errors: ${errors}, Skipped: ${skipped}`);
|
||||
return { success: true, imported, errors, skipped };
|
||||
}
|
||||
async importFromFile(countryCode, filePath) {
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync(filePath)) {
|
||||
this.logger.error(`File not found: ${filePath}`);
|
||||
return { success: false, imported: 0, errors: 1, skipped: 0 };
|
||||
}
|
||||
try {
|
||||
const data = fs.readFileSync(filePath, 'utf8');
|
||||
const geoJson = JSON.parse(data);
|
||||
return this.importGeoJSON(countryCode, geoJson);
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error(`Failed to read or parse GeoJSON file: ${err.message}`);
|
||||
return { success: false, imported: 0, errors: 1, skipped: 0 };
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.AdminBoundariesService = AdminBoundariesService;
|
||||
exports.AdminBoundariesService = AdminBoundariesService = AdminBoundariesService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(0, (0, typeorm_1.InjectRepository)(admin_boundary_entity_1.AdminBoundary)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _a : Object])
|
||||
], AdminBoundariesService);
|
||||
//# sourceMappingURL=admin-boundaries.service.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"admin-boundaries.service.js","sourceRoot":"","sources":["../../src/geocoding/admin-boundaries.service.ts"],"names":[],"mappings":"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"}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Repository, DataSource } from 'typeorm';
|
||||
import { NeighborhoodPoint } from './entities/neighborhood-point.entity';
|
||||
import { NeighborhoodPolygon } from './entities/neighborhood-polygon.entity';
|
||||
import { AdminBoundary } from './entities/admin-boundary.entity';
|
||||
export declare class AdministrativeLinkingService {
|
||||
private dataSource;
|
||||
private readonly neighborhoodPointRepo;
|
||||
private readonly neighborhoodPolygonRepo;
|
||||
private readonly adminBoundaryRepo;
|
||||
private readonly logger;
|
||||
constructor(dataSource: DataSource, neighborhoodPointRepo: Repository<NeighborhoodPoint>, neighborhoodPolygonRepo: Repository<NeighborhoodPolygon>, adminBoundaryRepo: Repository<AdminBoundary>);
|
||||
private readonly overpassMirrors;
|
||||
private fetchWithRetry;
|
||||
syncOsmNeighborhoodPoints(bbox?: string, country?: string): Promise<{
|
||||
detected_country: string;
|
||||
osm_fetched: any;
|
||||
country_points: number;
|
||||
total_points_in_db: number;
|
||||
linked_to_district: number;
|
||||
}>;
|
||||
generateVoronoiNeighborhoods(country?: string): Promise<{
|
||||
status: string;
|
||||
country: string;
|
||||
total_polygons: number;
|
||||
districts_processed: any;
|
||||
}>;
|
||||
linkPlaces(country: 'jordan' | 'syria' | 'egypt'): Promise<{
|
||||
status: string;
|
||||
country: "syria" | "jordan" | "egypt";
|
||||
total_places: number;
|
||||
linked_neighborhood: number;
|
||||
linked_district: number;
|
||||
linked_governorate: number;
|
||||
sample_masoum: any;
|
||||
rows_affected: any;
|
||||
} | {
|
||||
status: string;
|
||||
error: string;
|
||||
polygons: number;
|
||||
places: number;
|
||||
}>;
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
"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); }
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var AdministrativeLinkingService_1;
|
||||
var _a, _b, _c, _d;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AdministrativeLinkingService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const typeorm_1 = require("@nestjs/typeorm");
|
||||
const typeorm_2 = require("typeorm");
|
||||
const neighborhood_point_entity_1 = require("./entities/neighborhood-point.entity");
|
||||
const neighborhood_polygon_entity_1 = require("./entities/neighborhood-polygon.entity");
|
||||
const admin_boundary_entity_1 = require("./entities/admin-boundary.entity");
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
let AdministrativeLinkingService = AdministrativeLinkingService_1 = class AdministrativeLinkingService {
|
||||
dataSource;
|
||||
neighborhoodPointRepo;
|
||||
neighborhoodPolygonRepo;
|
||||
adminBoundaryRepo;
|
||||
logger = new common_1.Logger(AdministrativeLinkingService_1.name);
|
||||
constructor(dataSource, neighborhoodPointRepo, neighborhoodPolygonRepo, adminBoundaryRepo) {
|
||||
this.dataSource = dataSource;
|
||||
this.neighborhoodPointRepo = neighborhoodPointRepo;
|
||||
this.neighborhoodPolygonRepo = neighborhoodPolygonRepo;
|
||||
this.adminBoundaryRepo = adminBoundaryRepo;
|
||||
}
|
||||
overpassMirrors = [
|
||||
'https://overpass-api.de/api/interpreter',
|
||||
'https://overpass.kumi.systems/api/interpreter',
|
||||
'https://z.overpass-api.de/api/interpreter'
|
||||
];
|
||||
async fetchWithRetry(data, retries = 3) {
|
||||
for (let i = 0; i <= retries; i++) {
|
||||
const url = this.overpassMirrors[i % this.overpassMirrors.length];
|
||||
try {
|
||||
const response = await axios_1.default.post(url, data, {
|
||||
timeout: 45000,
|
||||
headers: {
|
||||
'User-Agent': 'IntaleqMapBot/1.0',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.warn(`Mirror ${url} failed: ${error.message}. Trying next mirror...`);
|
||||
if (i === retries)
|
||||
throw error;
|
||||
await new Promise(res => setTimeout(res, 2000));
|
||||
}
|
||||
}
|
||||
}
|
||||
async syncOsmNeighborhoodPoints(bbox = '31.86,35.94,32.22,36.25', country) {
|
||||
this.logger.log(`Syncing neighborhood points for country: ${country || 'auto'}, bbox: ${bbox}`);
|
||||
const query = `[out:json][timeout:900];node["place"~"neighbourhood|suburb|town"](${bbox});out;`;
|
||||
try {
|
||||
const data = await this.fetchWithRetry(`data=${encodeURIComponent(query)}`);
|
||||
const elements = data.elements;
|
||||
this.logger.log(`Found ${elements.length} points in OSM.`);
|
||||
let detectedCountry = country;
|
||||
if (!detectedCountry) {
|
||||
const firstLat = parseFloat(bbox.split(',')[0]);
|
||||
if (firstLat > 32.3)
|
||||
detectedCountry = 'syria';
|
||||
else if (firstLat < 31.0)
|
||||
detectedCountry = 'egypt';
|
||||
else
|
||||
detectedCountry = 'jordan';
|
||||
}
|
||||
for (const e of elements) {
|
||||
const nameAr = e.tags['name:ar'] || e.tags['name'];
|
||||
const nameEn = e.tags['name:en'] || e.tags['name'];
|
||||
const geometry = { type: 'Point', coordinates: [e.lon, e.lat] };
|
||||
await this.dataSource.query(`
|
||||
INSERT INTO neighborhood_points (osm_id, name_ar, name_en, place_type, geometry, country)
|
||||
VALUES ($1, $2, $3, $4, ST_SetSRID(ST_GeomFromGeoJSON($5), 4326), $6)
|
||||
ON CONFLICT (osm_id) DO UPDATE SET
|
||||
name_ar = EXCLUDED.name_ar,
|
||||
name_en = EXCLUDED.name_en,
|
||||
place_type = EXCLUDED.place_type,
|
||||
geometry = EXCLUDED.geometry,
|
||||
country = COALESCE(EXCLUDED.country, neighborhood_points.country);
|
||||
`, [e.id, nameAr, nameEn, e.tags['place'], JSON.stringify(geometry), detectedCountry]);
|
||||
}
|
||||
await this.dataSource.query(`
|
||||
UPDATE neighborhood_points np
|
||||
SET district_id = COALESCE(
|
||||
(
|
||||
SELECT id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level IN (6, 8)
|
||||
AND ST_Contains(ab.geom::geometry, np.geometry::geometry)
|
||||
ORDER BY ab.admin_level DESC
|
||||
LIMIT 1
|
||||
),
|
||||
(
|
||||
SELECT id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level IN (6, 8)
|
||||
ORDER BY ab.geom::geometry <-> np.geometry::geometry
|
||||
LIMIT 1
|
||||
)
|
||||
)
|
||||
WHERE district_id IS NULL AND (country = $1 OR $1 IS NULL);
|
||||
`, [detectedCountry]);
|
||||
const totalPoints = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_points`);
|
||||
const linkedPoints = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_points WHERE district_id IS NOT NULL`);
|
||||
const countryPoints = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_points WHERE country = $1`, [detectedCountry]);
|
||||
const diagnostics = {
|
||||
detected_country: detectedCountry,
|
||||
osm_fetched: elements.length,
|
||||
country_points: parseInt(countryPoints[0].cnt),
|
||||
total_points_in_db: parseInt(totalPoints[0].cnt),
|
||||
linked_to_district: parseInt(linkedPoints[0].cnt),
|
||||
};
|
||||
this.logger.log(`Step 1 diagnostics: ${JSON.stringify(diagnostics)}`);
|
||||
return diagnostics;
|
||||
}
|
||||
catch (error) {
|
||||
this.logger.error(`Failed to sync OSM points: ${error.message}`, error.stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async generateVoronoiNeighborhoods(country) {
|
||||
this.logger.log(`Generating Voronoi polygons for ${country || 'all'} neighborhoods...`);
|
||||
const whereClause = country ? `WHERE district_id IS NOT NULL AND country = '${country}'` : `WHERE district_id IS NOT NULL`;
|
||||
const prePoints = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_points ${whereClause}`);
|
||||
const preDistricts = await this.dataSource.query(`SELECT district_id, count(*) as cnt FROM neighborhood_points ${whereClause} GROUP BY district_id`);
|
||||
const deleteWhere = country ? `WHERE method = 'voronoi' AND country = '${country}'` : `WHERE method = 'voronoi'`;
|
||||
await this.dataSource.query(`DELETE FROM neighborhood_polygons ${deleteWhere}`);
|
||||
this.logger.log(`Deleted old voronoi polygons for ${country || 'all'}.`);
|
||||
let totalInserted = 0;
|
||||
for (const row of preDistricts) {
|
||||
const districtId = row.district_id;
|
||||
const pointCount = parseInt(row.cnt);
|
||||
try {
|
||||
if (pointCount >= 2) {
|
||||
const result = await this.dataSource.query(`
|
||||
INSERT INTO neighborhood_polygons (osm_id, name_ar, name_en, place_type, parent_id, method, country, geometry)
|
||||
WITH voronoi_cells AS (
|
||||
SELECT (ST_Dump(ST_VoronoiPolygons(
|
||||
ST_Collect(np.geometry::geometry),
|
||||
0.00001,
|
||||
d.geom::geometry
|
||||
))).geom as cell
|
||||
FROM neighborhood_points np
|
||||
JOIN admin_boundaries d ON d.id = np.district_id
|
||||
WHERE np.district_id = $1
|
||||
GROUP BY d.geom
|
||||
),
|
||||
matched AS (
|
||||
SELECT
|
||||
np.osm_id, np.name_ar, np.name_en, np.place_type, np.district_id, np.country,
|
||||
ST_Multi(ST_Intersection(vc.cell::geometry, d.geom::geometry)) as geometry
|
||||
FROM voronoi_cells vc
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT np2.*
|
||||
FROM neighborhood_points np2
|
||||
WHERE np2.district_id = $1
|
||||
ORDER BY np2.geometry::geometry <-> vc.cell::geometry
|
||||
LIMIT 1
|
||||
) np
|
||||
JOIN admin_boundaries d ON d.id = $1
|
||||
)
|
||||
SELECT osm_id, name_ar, name_en, place_type, district_id, 'voronoi', country, geometry
|
||||
FROM matched
|
||||
WHERE ST_IsValid(geometry) AND NOT ST_IsEmpty(geometry)
|
||||
`, [districtId]);
|
||||
totalInserted += (result?.length || result?.[1] || 0);
|
||||
}
|
||||
else if (pointCount === 1) {
|
||||
await this.dataSource.query(`
|
||||
INSERT INTO neighborhood_polygons (osm_id, name_ar, name_en, place_type, parent_id, method, country, geometry)
|
||||
SELECT np.osm_id, np.name_ar, np.name_en, np.place_type, np.district_id, 'voronoi', np.country, ST_Multi(d.geom::geometry)
|
||||
FROM neighborhood_points np
|
||||
JOIN admin_boundaries d ON d.id = np.district_id
|
||||
WHERE np.district_id = $1
|
||||
`, [districtId]);
|
||||
totalInserted++;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
this.logger.error(`Voronoi FAILED for district ${districtId}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
const postCount = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_polygons ${country ? `WHERE country = '${country}'` : ''}`);
|
||||
return {
|
||||
status: 'success',
|
||||
country: country || 'all',
|
||||
total_polygons: parseInt(postCount[0].cnt),
|
||||
districts_processed: preDistricts.length
|
||||
};
|
||||
}
|
||||
async linkPlaces(country) {
|
||||
const tableName = `places_${country}`;
|
||||
const polyCount = await this.dataSource.query(`SELECT count(*) as cnt FROM neighborhood_polygons`);
|
||||
const placeCount = await this.dataSource.query(`SELECT count(*) as cnt FROM ${tableName} WHERE location IS NOT NULL`);
|
||||
this.logger.log(`linkPlaces pre-flight: ${polyCount[0].cnt} polygons, ${placeCount[0].cnt} places with location in ${tableName}`);
|
||||
if (parseInt(polyCount[0].cnt) === 0) {
|
||||
this.logger.error('ABORT: neighborhood_polygons is EMPTY. Run generate-voronoi first!');
|
||||
return {
|
||||
status: 'FAILED',
|
||||
error: 'neighborhood_polygons table is empty. Run generate-voronoi first.',
|
||||
polygons: 0,
|
||||
places: parseInt(placeCount[0].cnt)
|
||||
};
|
||||
}
|
||||
this.logger.log(`Linking administrative hierarchy for ${tableName} using KNN...`);
|
||||
const updateResult = await this.dataSource.query(`
|
||||
UPDATE ${tableName} p
|
||||
SET
|
||||
neighborhood_id = (
|
||||
SELECT np.id FROM neighborhood_polygons np
|
||||
WHERE (np.country = $1 OR np.country IS NULL)
|
||||
ORDER BY p.location::geometry <-> np.geometry::geometry
|
||||
LIMIT 1
|
||||
),
|
||||
sub_district_id = (
|
||||
SELECT ab.id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level = 8
|
||||
AND ST_Within(p.location::geometry, ab.geom::geometry)
|
||||
LIMIT 1
|
||||
),
|
||||
district_id = (
|
||||
SELECT ab.id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level = 6
|
||||
AND ST_Within(p.location::geometry, ab.geom::geometry)
|
||||
LIMIT 1
|
||||
),
|
||||
governorate_id = (
|
||||
SELECT ab.id FROM admin_boundaries ab
|
||||
WHERE ab.admin_level = 4
|
||||
AND ST_Within(p.location::geometry, ab.geom::geometry)
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE p.location IS NOT NULL;
|
||||
`, [country]);
|
||||
const linkedNeighborhood = await this.dataSource.query(`SELECT count(*) as cnt FROM ${tableName} WHERE neighborhood_id IS NOT NULL`);
|
||||
const linkedDistrict = await this.dataSource.query(`SELECT count(*) as cnt FROM ${tableName} WHERE district_id IS NOT NULL`);
|
||||
const linkedGov = await this.dataSource.query(`SELECT count(*) as cnt FROM ${tableName} WHERE governorate_id IS NOT NULL`);
|
||||
const totalPlaces = await this.dataSource.query(`SELECT count(*) as cnt FROM ${tableName}`);
|
||||
const samplePlace = await this.dataSource.query(`
|
||||
SELECT p.id, p.name_ar, p.neighborhood_id, p.district_id, p.governorate_id,
|
||||
n.name_ar as neighborhood_name
|
||||
FROM ${tableName} p
|
||||
LEFT JOIN neighborhood_polygons n ON p.neighborhood_id = n.id
|
||||
WHERE p.name_ar LIKE '%معصوم%'
|
||||
LIMIT 3
|
||||
`);
|
||||
const diagnostics = {
|
||||
status: 'completed',
|
||||
country,
|
||||
total_places: parseInt(totalPlaces[0].cnt),
|
||||
linked_neighborhood: parseInt(linkedNeighborhood[0].cnt),
|
||||
linked_district: parseInt(linkedDistrict[0].cnt),
|
||||
linked_governorate: parseInt(linkedGov[0].cnt),
|
||||
sample_masoum: samplePlace,
|
||||
rows_affected: updateResult?.[1] || 'unknown'
|
||||
};
|
||||
this.logger.log(`Step 3 diagnostics: ${JSON.stringify(diagnostics)}`);
|
||||
return diagnostics;
|
||||
}
|
||||
};
|
||||
exports.AdministrativeLinkingService = AdministrativeLinkingService;
|
||||
exports.AdministrativeLinkingService = AdministrativeLinkingService = AdministrativeLinkingService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(1, (0, typeorm_1.InjectRepository)(neighborhood_point_entity_1.NeighborhoodPoint)),
|
||||
__param(2, (0, typeorm_1.InjectRepository)(neighborhood_polygon_entity_1.NeighborhoodPolygon)),
|
||||
__param(3, (0, typeorm_1.InjectRepository)(admin_boundary_entity_1.AdminBoundary)),
|
||||
__metadata("design:paramtypes", [typeof (_a = typeof typeorm_2.DataSource !== "undefined" && typeorm_2.DataSource) === "function" ? _a : Object, typeof (_b = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _b : Object, typeof (_c = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _c : Object, typeof (_d = typeof typeorm_2.Repository !== "undefined" && typeorm_2.Repository) === "function" ? _d : Object])
|
||||
], AdministrativeLinkingService);
|
||||
//# sourceMappingURL=administrative-linking.service.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,4 +0,0 @@
|
||||
export declare class ReverseGeocodeDto {
|
||||
lat: number;
|
||||
lng: number;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
"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.ReverseGeocodeDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
const class_transformer_1 = require("class-transformer");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
class ReverseGeocodeDto {
|
||||
lat;
|
||||
lng;
|
||||
}
|
||||
exports.ReverseGeocodeDto = ReverseGeocodeDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsNotEmpty)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(-90),
|
||||
(0, class_validator_1.Max)(90),
|
||||
(0, class_transformer_1.Type)(() => Number),
|
||||
(0, swagger_1.ApiProperty)({ description: 'Latitude' }),
|
||||
__metadata("design:type", Number)
|
||||
], ReverseGeocodeDto.prototype, "lat", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsNotEmpty)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(-180),
|
||||
(0, class_validator_1.Max)(180),
|
||||
(0, class_transformer_1.Type)(() => Number),
|
||||
(0, swagger_1.ApiProperty)({ description: 'Longitude' }),
|
||||
__metadata("design:type", Number)
|
||||
], ReverseGeocodeDto.prototype, "lng", void 0);
|
||||
//# sourceMappingURL=reverse-geocode.dto.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"reverse-geocode.dto.js","sourceRoot":"","sources":["../../../src/geocoding/dto/reverse-geocode.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAiE;AACjE,yDAAyC;AACzC,6CAA8C;AAE9C,MAAa,iBAAiB;IAO5B,GAAG,CAAS;IAQZ,GAAG,CAAS;CACb;AAhBD,8CAgBC;AATC;IANC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,EAAE,CAAC;IACR,IAAA,qBAAG,EAAC,EAAE,CAAC;IACP,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;;8CAC7B;AAQZ;IANC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,GAAG,CAAC;IACT,IAAA,qBAAG,EAAC,GAAG,CAAC;IACR,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,qBAAW,EAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;;8CAC9B"}
|
||||
@@ -1,7 +0,0 @@
|
||||
export declare class SearchQueryDto {
|
||||
q: string;
|
||||
lat?: number;
|
||||
lng?: number;
|
||||
radius?: number;
|
||||
country?: string;
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
"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.SearchQueryDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
const class_transformer_1 = require("class-transformer");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
class SearchQueryDto {
|
||||
q;
|
||||
lat;
|
||||
lng;
|
||||
radius = 20000;
|
||||
country;
|
||||
}
|
||||
exports.SearchQueryDto = SearchQueryDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Search query string' }),
|
||||
__metadata("design:type", String)
|
||||
], SearchQueryDto.prototype, "q", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_transformer_1.Type)(() => Number),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Latitude for proximity search' }),
|
||||
__metadata("design:type", Number)
|
||||
], SearchQueryDto.prototype, "lat", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_transformer_1.Type)(() => Number),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Longitude for proximity search' }),
|
||||
__metadata("design:type", Number)
|
||||
], SearchQueryDto.prototype, "lng", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
(0, class_validator_1.Max)(50000),
|
||||
(0, class_transformer_1.Type)(() => Number),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Proximity radius in meters', default: 20000 }),
|
||||
__metadata("design:type", Number)
|
||||
], SearchQueryDto.prototype, "radius", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsEnum)(['jordan', 'syria', 'egypt']),
|
||||
(0, swagger_1.ApiPropertyOptional)({ description: 'Country filter', enum: ['jordan', 'syria', 'egypt'] }),
|
||||
__metadata("design:type", String)
|
||||
], SearchQueryDto.prototype, "country", void 0);
|
||||
//# sourceMappingURL=search-query.dto.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"search-query.dto.js","sourceRoot":"","sources":["../../../src/geocoding/dto/search-query.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAmF;AACnF,yDAAyC;AACzC,6CAAsD;AAEtD,MAAa,cAAc;IAGzB,CAAC,CAAS;IAMV,GAAG,CAAU;IAMb,GAAG,CAAU;IAQb,MAAM,GAAY,KAAK,CAAC;IAKxB,OAAO,CAAU;CAClB;AA7BD,wCA6BC;AA1BC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;;yCAClD;AAMV;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;2CACzD;AAMb;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;2CAC1D;AAQb;IANC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;IACN,IAAA,qBAAG,EAAC,KAAK,CAAC;IACV,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;IAClB,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;8CAC3D;AAKxB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAM,EAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,IAAA,6BAAmB,EAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;;+CAC1E"}
|
||||
@@ -1,8 +0,0 @@
|
||||
export declare class AdminBoundary {
|
||||
id: number;
|
||||
country_code: string;
|
||||
admin_level: number;
|
||||
name_ar: string;
|
||||
name_en: string;
|
||||
geom: any;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user