Skip to content

Commit

Permalink
feat(tenant-management): add keycloak idp configuration
Browse files Browse the repository at this point in the history
add keycloak idp configuration

BREAKING CHANGE:
yes

43
  • Loading branch information
Tyagi-Sunny committed Sep 26, 2024
1 parent 5e03dcb commit a895365
Show file tree
Hide file tree
Showing 21 changed files with 1,186 additions and 601 deletions.
1,120 changes: 530 additions & 590 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

var dbm;
var type;
var seed;
var fs = require('fs');
var path = require('path');
var Promise;

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function(options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
Promise = options.Promise;
};

exports.up = function(db) {
var filePath = path.join(__dirname, 'sqls', '20240925102459-add-table-tenant-configs-up.sql');
return new Promise( function( resolve, reject ) {
fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
if (err) return reject(err);
console.log('received data: ' + data);

resolve(data);
});
})
.then(function(data) {
return db.runSql(data);
});
};

exports.down = function(db) {
var filePath = path.join(__dirname, 'sqls', '20240925102459-add-table-tenant-configs-down.sql');
return new Promise( function( resolve, reject ) {
fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
if (err) return reject(err);
console.log('received data: ' + data);

resolve(data);
});
})
.then(function(data) {
return db.runSql(data);
});
};

exports._meta = {
"version": 1
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
drop table main.tenant_configs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS main.tenant_configs
(
id uuid NOT NULL DEFAULT (md5(((random())::text || (clock_timestamp())::text)))::uuid,
config_key varchar(100) NOT NULL,
config_value jsonb NOT NULL,
created_on timestamptz DEFAULT CURRENT_TIMESTAMP,
modified_on timestamptz,
created_by uuid,
modified_by uuid,
deleted boolean DEFAULT FALSE NOT NULL,
deleted_by uuid,
deleted_on timestamptz,
tenant_id uuid NOT NULL,
CONSTRAINT pk_tenant_configs_id PRIMARY KEY (id),
CONSTRAINT fk_tenant_configs_tenants FOREIGN KEY (tenant_id)
REFERENCES main.tenants(id)
)
8 changes: 7 additions & 1 deletion services/tenant-management-service/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
TenantOnboardDTO,
VerifyLeadResponseDTO,
WebhookDTO,
TenantConfig,
} from './models';
import {
AddressRepository,
Expand All @@ -70,6 +71,7 @@ import {
ResourceRepository,
TenantRepository,
WebhookSecretRepository,
TenantConfigRepository,
} from './repositories';
import {LeadTokenVerifierProvider, SystemUserProvider} from './providers';
import {
Expand All @@ -81,6 +83,8 @@ import {
OnboardingService,
ProvisioningService,
} from './services';
import { IdpController } from './controllers/idp.controller';

Check failure on line 86 in services/tenant-management-service/src/component.ts

View workflow job for this annotation

GitHub Actions / npm_test

'IdpController' is defined but never used
import { KeycloakIdpProvider } from './providers/idp/idp-keycloak.provider';

Check failure on line 87 in services/tenant-management-service/src/component.ts

View workflow job for this annotation

GitHub Actions / npm_test

'KeycloakIdpProvider' is defined but never used
export class TenantManagementServiceComponent implements Component {
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE)
Expand Down Expand Up @@ -120,6 +124,7 @@ export class TenantManagementServiceComponent implements Component {
ResourceRepository,
TenantRepository,
WebhookSecretRepository,
TenantConfigRepository
];

this.models = [
Expand All @@ -136,6 +141,7 @@ export class TenantManagementServiceComponent implements Component {
TenantOnboardDTO,
VerifyLeadResponseDTO,
WebhookDTO,
TenantConfig
];

this.controllers = [
Expand All @@ -145,7 +151,7 @@ export class TenantManagementServiceComponent implements Component {
LeadTenantController,
LeadController,
PingController,
TenantController,
TenantController
];

this.bindings = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { extensions, Getter, inject, intercept } from '@loopback/core';

Check failure on line 1 in services/tenant-management-service/src/controllers/idp.controller.ts

View workflow job for this annotation

GitHub Actions / npm_test

'extensions' is defined but never used

Check failure on line 1 in services/tenant-management-service/src/controllers/idp.controller.ts

View workflow job for this annotation

GitHub Actions / npm_test

'Getter' is defined but never used
import { getModelSchemaRef, post, requestBody } from '@loopback/rest';
import {
CONTENT_TYPE,
OPERATION_SECURITY_SPEC,
rateLimitKeyGenPublic,
STATUS_CODE,
} from '@sourceloop/core';
import { authorize } from 'loopback4-authorization';
import { ratelimit } from 'loopback4-ratelimiter';
import { TenantManagementServiceBindings, WEBHOOK_VERIFIER } from '../keys';
import { IdpDetailsDTO } from '../models/dtos/idp-details-dto.model';
import { ConfigureIdpFunc, IdPKey, IWebhookHandler } from '../types';

Check failure on line 13 in services/tenant-management-service/src/controllers/idp.controller.ts

View workflow job for this annotation

GitHub Actions / npm_test

'IWebhookHandler' is defined but never used
import { KeycloakIdpProvider } from '../providers/idp/idp-keycloak.provider';

Check failure on line 14 in services/tenant-management-service/src/controllers/idp.controller.ts

View workflow job for this annotation

GitHub Actions / npm_test

'KeycloakIdpProvider' is defined but never used

const basePath = '/manage/users';
export class IdpController {
constructor(
@inject(TenantManagementServiceBindings.IDP_KEYCLOAK)
private readonly idpKeycloakProvider:ConfigureIdpFunc<IdpDetailsDTO>
) { }
@intercept(WEBHOOK_VERIFIER)
@ratelimit(true, {
max: parseInt(process.env.WEBHOOK_API_MAX_ATTEMPTS ?? '10'),
keyGenerator: rateLimitKeyGenPublic,
})
@authorize({
permissions: ['*'],
})
@post(`${basePath}`, {
security: OPERATION_SECURITY_SPEC,
responses: {
[STATUS_CODE.NO_CONTENT]: {
description: 'Webhook success',
},
},
})
async idpConfigure(
@requestBody({
content: {
[CONTENT_TYPE.JSON]: {
schema: getModelSchemaRef(IdpDetailsDTO, {
title: 'IdpDetailsDTO',
}),
},
},
})
payload: IdpDetailsDTO,
): Promise<void> {
switch (payload.identityProvider) {
case IdPKey.AUTH0:

break;
case IdPKey.COGNITO:

break;
case IdPKey.KEYCLOAK:
await this.idpKeycloakProvider(payload);
break;

default:
break;
}

}
}
2 changes: 2 additions & 0 deletions services/tenant-management-service/src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export * from './lead-tenant.controller';
export * from './tenant.controller';
export * from './webhook.controller';
export * from './invoice.controller';
export * from './tenant-config.controller';
export * from './tenant-config-tenant.controller';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
repository,
} from '@loopback/repository';
import {
param,
get,
getModelSchemaRef,
} from '@loopback/rest';
import {
TenantConfig,
Tenant,
} from '../models';
import {TenantConfigRepository} from '../repositories';

export class TenantConfigTenantController {
constructor(
@repository(TenantConfigRepository)
public tenantConfigRepository: TenantConfigRepository,
) { }

@get('/tenant-configs/{id}/tenant', {
responses: {
'200': {
description: 'Tenant belonging to TenantConfig',
content: {
'application/json': {
schema: getModelSchemaRef(Tenant),
},
},
},
},
})
async getTenant(
@param.path.string('id') id: typeof TenantConfig.prototype.id,
): Promise<Tenant> {
return this.tenantConfigRepository.tenant(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
Count,
CountSchema,
Filter,
FilterExcludingWhere,
repository,
Where,
} from '@loopback/repository';
import {
post,
param,
get,
getModelSchemaRef,
patch,
put,
del,
requestBody,
response,
} from '@loopback/rest';
import {TenantConfig} from '../models';
import {TenantConfigRepository} from '../repositories';

export class TenantConfigController {
constructor(
@repository(TenantConfigRepository)
public tenantConfigRepository : TenantConfigRepository,
) {}

@post('/tenant-configs')
@response(200, {
description: 'TenantConfig model instance',
content: {'application/json': {schema: getModelSchemaRef(TenantConfig)}},
})
async create(
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(TenantConfig, {
title: 'NewTenantConfig',
exclude: ['id'],
}),
},
},
})
tenantConfig: Omit<TenantConfig, 'id'>,
): Promise<TenantConfig> {
return this.tenantConfigRepository.create(tenantConfig);
}

@get('/tenant-configs/count')
@response(200, {
description: 'TenantConfig model count',
content: {'application/json': {schema: CountSchema}},
})
async count(
@param.where(TenantConfig) where?: Where<TenantConfig>,
): Promise<Count> {
return this.tenantConfigRepository.count(where);
}

@get('/tenant-configs')
@response(200, {
description: 'Array of TenantConfig model instances',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(TenantConfig, {includeRelations: true}),
},
},
},
})
async find(
@param.filter(TenantConfig) filter?: Filter<TenantConfig>,
): Promise<TenantConfig[]> {
return this.tenantConfigRepository.find(filter);
}

@patch('/tenant-configs')
@response(200, {
description: 'TenantConfig PATCH success count',
content: {'application/json': {schema: CountSchema}},
})
async updateAll(
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(TenantConfig, {partial: true}),
},
},
})
tenantConfig: TenantConfig,
@param.where(TenantConfig) where?: Where<TenantConfig>,
): Promise<Count> {
return this.tenantConfigRepository.updateAll(tenantConfig, where);
}

@get('/tenant-configs/{id}')
@response(200, {
description: 'TenantConfig model instance',
content: {
'application/json': {
schema: getModelSchemaRef(TenantConfig, {includeRelations: true}),
},
},
})
async findById(
@param.path.string('id') id: string,
@param.filter(TenantConfig, {exclude: 'where'}) filter?: FilterExcludingWhere<TenantConfig>
): Promise<TenantConfig> {
return this.tenantConfigRepository.findById(id, filter);
}

@patch('/tenant-configs/{id}')
@response(204, {
description: 'TenantConfig PATCH success',
})
async updateById(
@param.path.string('id') id: string,
@requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(TenantConfig, {partial: true}),
},
},
})
tenantConfig: TenantConfig,
): Promise<void> {
await this.tenantConfigRepository.updateById(id, tenantConfig);
}

@put('/tenant-configs/{id}')
@response(204, {
description: 'TenantConfig PUT success',
})
async replaceById(
@param.path.string('id') id: string,
@requestBody() tenantConfig: TenantConfig,
): Promise<void> {
await this.tenantConfigRepository.replaceById(id, tenantConfig);
}

@del('/tenant-configs/{id}')
@response(204, {
description: 'TenantConfig DELETE success',
})
async deleteById(@param.path.string('id') id: string): Promise<void> {
await this.tenantConfigRepository.deleteById(id);
}
}
Loading

0 comments on commit a895365

Please sign in to comment.