diff --git a/env/env.development b/env/env.development index dd1debc..4fb5ad3 100644 --- a/env/env.development +++ b/env/env.development @@ -39,4 +39,8 @@ EXPORT_LIMIT_PARTITION=200 ASSETS="https://asset.sky.eigen.co.id/" GOOGLE_CALENDAR_KEY="AIzaSyCSg4P3uC9Z7kD1P4f3rf1BbBaz4Q-M55o" -GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com" \ No newline at end of file +GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com" + +SUPERSET_URL=https://dashboard.weplayground.eigen.co.id +SUPERSET_ADMIN_USERNAME=admin +SUPERSET_ADMIN_PASSWORD=admin \ No newline at end of file diff --git a/env/env.production b/env/env.production index e9c9e82..5557402 100644 --- a/env/env.production +++ b/env/env.production @@ -36,4 +36,8 @@ EXPORT_LIMIT_PARTITION=200 ASSETS="https://asset.sky.eigen.co.id/" GOOGLE_CALENDAR_KEY="AIzaSyCSg4P3uC9Z7kD1P4f3rf1BbBaz4Q-M55o" -GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com" \ No newline at end of file +GOOGLE_CALENDAR_ID="326464ac296874c7121825f5ef2e2799baa90b51da240f0045aae22beec10bd5@group.calendar.google.com" + +SUPERSET_URL=https://dashboard.weplayground.eigen.co.id +SUPERSET_ADMIN_USERNAME=admin +SUPERSET_ADMIN_PASSWORD=admin \ No newline at end of file diff --git a/package.json b/package.json index b20c84e..9ae87fc 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@faker-js/faker": "^8.4.1", + "@nestjs/axios": "^3.0.3", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.2", "@nestjs/core": "^10.0.0", @@ -39,6 +40,7 @@ "@nestjs/typeorm": "^10.0.2", "@types/multer": "^1.4.11", "algebra.js": "^0.2.6", + "axios": "^1.7.5", "bcrypt": "^5.1.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", diff --git a/src/app.module.ts b/src/app.module.ts index c21e956..2c9e87e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -75,6 +75,7 @@ import { MailModule } from './modules/configuration/mail/mail.module'; import { PosLogModel } from './modules/configuration/log/data/models/pos-log.model'; import { ExportModule } from './modules/configuration/export/export.module'; import { TransactionDemographyModel } from './modules/transaction/transaction/data/models/transaction-demography.model'; +import { SupersetModule } from './modules/configuration/superset/superset.module'; @Module({ imports: [ @@ -174,6 +175,9 @@ import { TransactionDemographyModel } from './modules/transaction/transaction/da ReportModule, ReportBookmarkModule, ReportExportModule, + + // superset + SupersetModule, ], controllers: [], providers: [ diff --git a/src/modules/configuration/superset/superset.controller.ts b/src/modules/configuration/superset/superset.controller.ts new file mode 100644 index 0000000..ebca593 --- /dev/null +++ b/src/modules/configuration/superset/superset.controller.ts @@ -0,0 +1,17 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ExcludePrivilege, Public } from 'src/core/guards'; +import { SupersetService } from './superset.service'; + +@ApiTags(`Superset`) +@Controller(`v1/superset`) +@Public(false) +@ApiBearerAuth('JWT') +export class SupersetController { + constructor(private service: SupersetService) {} + @Get('token/:id') + @ExcludePrivilege() + async getGuestToken(@Param('id') id: string) { + return this.service.getGuestToken(id); + } +} diff --git a/src/modules/configuration/superset/superset.module.ts b/src/modules/configuration/superset/superset.module.ts new file mode 100644 index 0000000..ecf4c76 --- /dev/null +++ b/src/modules/configuration/superset/superset.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { SupersetController } from './superset.controller'; +import { SupersetService } from './superset.service'; +import { HttpModule } from '@nestjs/axios'; + +@Module({ + imports: [HttpModule], + controllers: [SupersetController], + providers: [SupersetService], +}) +export class SupersetModule {} diff --git a/src/modules/configuration/superset/superset.service.ts b/src/modules/configuration/superset/superset.service.ts new file mode 100644 index 0000000..b79d590 --- /dev/null +++ b/src/modules/configuration/superset/superset.service.ts @@ -0,0 +1,77 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable, Logger } from '@nestjs/common'; +import { firstValueFrom } from 'rxjs'; + +@Injectable() +export class SupersetService { + private readonly logger = new Logger(SupersetService.name); + private supersetURL = process.env.SUPERSET_URL + '/api'; + private adminUsername = process.env.SUPERSET_ADMIN_USERNAME; + private adminPassword = process.env.SUPERSET_ADMIN_PASSWORD; + + constructor(private readonly httpService: HttpService) {} + + async getLoginToken() { + const data = { + username: this.adminUsername, + password: this.adminPassword, + provider: 'db', + refresh: true, + }; + + const response = await firstValueFrom( + this.httpService.request({ + method: 'POST', + url: `${this.supersetURL}/v1/security/login`, + data: data, + }), + ); + + return response.data.access_token; + } + + async getCSRFToken() { + const loginToken = await this.getLoginToken(); + const response = await firstValueFrom( + this.httpService.request({ + method: 'GET', + url: `${this.supersetURL}/v1/security/csrf_token/`, + headers: { Authorization: `Bearer ${loginToken}` }, + }), + ); + + return { loginToken, csrfToken: response.data.result }; + } + + async getGuestToken(uuid: string) { + const { loginToken, csrfToken } = await this.getCSRFToken(); + + const data = { + resources: [{ type: 'dashboard', id: uuid }], + rls: [], + user: { username: 'pos_embed', first_name: 'pos', last_name: 'embed' }, + }; + + const headers = { + 'Content-Type': 'application/json', + Authorization: `Bearer ${loginToken}`, + 'X-CSRFToken': `${csrfToken}`, + Referer: `${this.supersetURL}/v1/security/guest_token/`, + }; + + const response = await firstValueFrom( + this.httpService.request({ + method: 'POST', + url: `${this.supersetURL}/v1/security/guest_token/`, + data: data, + headers: headers, + }), + ).catch((err) => { + this.logger.verbose({ loginToken, csrfToken }); + this.logger.error(err.response.data); + throw err; + }); + + return response.data.token; + } +} diff --git a/src/modules/transaction/payment-method/domain/usecases/managers/create-payment-method.manager.ts b/src/modules/transaction/payment-method/domain/usecases/managers/create-payment-method.manager.ts index 3823263..e5bc606 100644 --- a/src/modules/transaction/payment-method/domain/usecases/managers/create-payment-method.manager.ts +++ b/src/modules/transaction/payment-method/domain/usecases/managers/create-payment-method.manager.ts @@ -24,7 +24,13 @@ export class CreatePaymentMethodManager extends BaseCreateManager { @@ -47,11 +46,18 @@ export class UpdateUserPrivilegeConfigurationManager extends BaseCustomManager