diff --git a/apps/api-gateway/src/app.module.ts b/apps/api-gateway/src/app.module.ts index 784704ce9..7e2ac5f08 100644 --- a/apps/api-gateway/src/app.module.ts +++ b/apps/api-gateway/src/app.module.ts @@ -15,6 +15,7 @@ import { ConnectionModule } from './connection/connection.module'; import { ContextModule } from '@credebl/context/contextModule'; import { CredentialDefinitionModule } from './credential-definition/credential-definition.module'; import { EcosystemModule } from './ecosystem/ecosystem.module'; +import { EcosystemSwaggerFilter } from './authz/guards/ecosystem-swagger.filter'; import { FidoModule } from './fido/fido.module'; import { GeoLocationModule } from './geo-location/geo-location.module'; import { GlobalConfigModule } from '@credebl/config/global-config.module'; @@ -77,6 +78,7 @@ import { shouldLoadOidcModules } from '@credebl/common/common.utils'; controllers: [AppController], providers: [ AppService, + EcosystemSwaggerFilter, { provide: MICRO_SERVICE_NAME, useValue: 'APIGATEWAY' diff --git a/apps/api-gateway/src/authz/guards/ecosystem-feature-guard.ts b/apps/api-gateway/src/authz/guards/ecosystem-feature-guard.ts new file mode 100644 index 000000000..d70744700 --- /dev/null +++ b/apps/api-gateway/src/authz/guards/ecosystem-feature-guard.ts @@ -0,0 +1,20 @@ +import { CanActivate, ForbiddenException, Injectable, Scope } from '@nestjs/common'; + +import { EcosystemRepository } from 'apps/ecosystem/repositories/ecosystem.repository'; +import { ResponseMessages } from '@credebl/common/response-messages'; + +@Injectable({ scope: Scope.REQUEST }) +export class EcosystemFeatureGuard implements CanActivate { + constructor(private readonly ecosystemRepository: EcosystemRepository) {} + + async canActivate(): Promise { + const config = await this.ecosystemRepository.getPlatformConfig(); + const enabled = Boolean(config?.isEcosystemEnabled); + + if (!enabled) { + throw new ForbiddenException(ResponseMessages.ecosystem.error.featureIsDisabled); + } + + return true; + } +} diff --git a/apps/api-gateway/src/authz/guards/ecosystem-swagger.filter.ts b/apps/api-gateway/src/authz/guards/ecosystem-swagger.filter.ts new file mode 100644 index 000000000..1c4d62d4b --- /dev/null +++ b/apps/api-gateway/src/authz/guards/ecosystem-swagger.filter.ts @@ -0,0 +1,34 @@ +import { EcosystemRepository } from 'apps/ecosystem/repositories/ecosystem.repository'; +import { Injectable } from '@nestjs/common'; +import { OpenAPIObject } from '@nestjs/swagger'; + +@Injectable() +export class EcosystemSwaggerFilter { + constructor(private readonly ecosystemRepository: EcosystemRepository) {} + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async filterDocument(document: OpenAPIObject): Promise { + const config = await this.ecosystemRepository.getPlatformConfig(); + const enabled = Boolean(config?.isEcosystemEnabled); + + if (!enabled) { + if (!document.paths) { + return document; + } + Object.keys(document.paths).forEach((path) => { + Object.keys(document.paths[path]).forEach((method) => { + const operation = document.paths[path][method]; + + if (operation.tags?.includes('ecosystem')) { + delete document.paths[path][method]; + } + }); + + if (0 === Object.keys(document.paths[path]).length) { + delete document.paths[path]; + } + }); + } + + return document; + } +} diff --git a/apps/api-gateway/src/ecosystem/dtos/enable-ecosystem.ts b/apps/api-gateway/src/ecosystem/dtos/enable-ecosystem.ts new file mode 100644 index 000000000..9d6043a54 --- /dev/null +++ b/apps/api-gateway/src/ecosystem/dtos/enable-ecosystem.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsBoolean } from 'class-validator'; + +export class EnableEcosystemDto { + @ApiProperty({ + example: true, + description: 'Enable or disable ecosystem creation' + }) + @IsBoolean() + isEcosystemEnabled: boolean; +} diff --git a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts index f3b4fec08..2f7bea8bc 100644 --- a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts @@ -37,7 +37,6 @@ import { ResponseMessages } from '@credebl/common/response-messages'; import { Roles } from '../authz/decorators/roles.decorator'; import { UnauthorizedErrorDto } from '../dtos/unauthorized-error.dto'; import { InviteMemberToEcosystemDto, UpdateEcosystemInvitationDto } from './dtos/send-ecosystem-invitation'; -import { OrgRolesGuard } from '../authz/guards/org-roles.guard'; import { EcosystemRolesGuard } from '../authz/guards/ecosystem-roles.guard'; import { user } from '@prisma/client'; import { User } from '../authz/decorators/user.decorator'; @@ -52,10 +51,12 @@ import { GetAllIntentTemplatesResponseDto } from '../utilities/dtos/get-all-inte import { GetAllIntentTemplatesDto } from '../utilities/dtos/get-all-intent-templates.dto'; import { GetIntentTemplateByIntentAndOrgDto } from '../utilities/dtos/get-intent-template-by-intent-and-org.dto'; import { CreateIntentTemplateDto, UpdateIntentTemplateDto } from '../utilities/dtos/intent-template.dto'; +import { EcosystemFeatureGuard } from '../authz/guards/ecosystem-feature-guard'; @UseFilters(CustomExceptionFilter) @Controller('ecosystem') @ApiTags('ecosystem') +@UseGuards(EcosystemFeatureGuard) @ApiUnauthorizedResponse({ description: 'Unauthorized', type: UnauthorizedErrorDto @@ -198,20 +199,16 @@ export class EcosystemController { * Get all ecosystems (platform admin) * @returns All ecosystems from platform */ - @Get() + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard) + @ApiBearerAuth() + @Get('/all-ecosystem') @ApiOperation({ - summary: 'Get all ecosystems (platform admin)', - description: 'Fetch all ecosystems available on the platform' - }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Ecosystems fetched successfully' + summary: 'Get ecosystems', + description: 'Fetch ecosystems for Platform Admin or Ecosystem Lead' }) - @Roles(OrgRoles.PLATFORM_ADMIN) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) - @ApiBearerAuth() - async getAllEcosystems(@User() reqUser: user, @Res() res: Response): Promise { - const ecosystems = await this.ecosystemService.getAllEcosystems(); + @Roles(OrgRoles.PLATFORM_ADMIN, OrgRoles.ECOSYSTEM_LEAD) + async getEcosystems(@User() reqUser: user, @Res() res: Response): Promise { + const ecosystems = await this.ecosystemService.getEcosystems(reqUser.id); return res.status(HttpStatus.OK).json({ statusCode: HttpStatus.OK, @@ -800,7 +797,6 @@ export class EcosystemController { return res.status(HttpStatus.OK).json(finalResponse); } - /** * Delete intent * @param id Intent ID @@ -820,12 +816,29 @@ export class EcosystemController { type: ApiResponseDto }) async deleteIntent( - @Param('ecosystemId') ecosystemId: string, - @Param('intentId') intentId: string, - @User() user: IUserRequest, + @Param( + 'ecosystemId', + new ParseUUIDPipe({ + exceptionFactory: (): Error => { + throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfEcosystemId); + } + }) + ) + ecosystemId: string, + @Param( + 'intentId', + new ParseUUIDPipe({ + exceptionFactory: (): Error => { + throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfIntentId); + } + }) + ) + intentId: string, + + @User() user: user, @Res() res: Response ): Promise { - const intent = await this.ecosystemService.deleteIntent(ecosystemId, intentId, user); + const intent = await this.ecosystemService.deleteIntent(ecosystemId, intentId, user.id); return res.status(HttpStatus.OK).json({ statusCode: HttpStatus.OK, diff --git a/apps/api-gateway/src/ecosystem/ecosystem.module.ts b/apps/api-gateway/src/ecosystem/ecosystem.module.ts index eb6a1a4e7..1b42d9028 100644 --- a/apps/api-gateway/src/ecosystem/ecosystem.module.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.module.ts @@ -21,6 +21,6 @@ import { getNatsOptions } from '@credebl/common/nats.config'; ], controllers: [EcosystemController], providers: [EcosystemService, NATSClient], - exports: [EcosystemService] + exports: [EcosystemService, EcosystemServiceModule] }) export class EcosystemModule {} diff --git a/apps/api-gateway/src/ecosystem/ecosystem.service.ts b/apps/api-gateway/src/ecosystem/ecosystem.service.ts index 28dbd5403..69e61aadb 100644 --- a/apps/api-gateway/src/ecosystem/ecosystem.service.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.service.ts @@ -39,9 +39,10 @@ export class EcosystemService { * @param userId * @returns All ecosystems from platform */ - async getAllEcosystems(): Promise { - return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-all-ecosystems', {}); + async getEcosystems(userId: string): Promise { + return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-ecosystems', { userId }); } + /** * * @param ecosystemId @@ -199,11 +200,11 @@ export class EcosystemService { * @param id Intent ID * @returns Deleted intent */ - async deleteIntent(ecosystemId: string, intentId: string, user: IUserRequest): Promise { + async deleteIntent(ecosystemId: string, intentId: string, userId: string): Promise { return this.natsClient.sendNatsMessage(this.serviceProxy, 'delete-intent', { ecosystemId, intentId, - user: { id: user.userId } + userId }); } } diff --git a/apps/api-gateway/src/main.ts b/apps/api-gateway/src/main.ts index b0021fe5f..8fb86c465 100644 --- a/apps/api-gateway/src/main.ts +++ b/apps/api-gateway/src/main.ts @@ -16,6 +16,7 @@ import { CommonConstants } from '@credebl/common/common.constant'; import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; import { UpdatableValidationPipe } from '@credebl/common/custom-overrideable-validation-pipe'; import * as useragent from 'express-useragent'; +import { EcosystemSwaggerFilter } from './authz/guards/ecosystem-swagger.filter'; dotenv.config(); @@ -81,7 +82,15 @@ async function bootstrap(): Promise { defaultVersion: ['1'] }); - const document = SwaggerModule.createDocument(app, options); + // Create Swagger document + let document = SwaggerModule.createDocument(app, options); + try { + const ecosystemFilter = app.get(EcosystemSwaggerFilter); + document = await ecosystemFilter.filterDocument(document); + } catch (err) { + Logger.warn('Skipping EcosystemSwaggerFilter due to error', err as Error); + } + SwaggerModule.setup('api', app, document); const httpAdapter: HttpAdapterHost = app.get(HttpAdapterHost) as HttpAdapterHost; app.useGlobalFilters(new AllExceptionsFilter(httpAdapter)); @@ -122,7 +131,7 @@ async function bootstrap(): Promise { if ('true' === process.env.DB_ALERT_ENABLE?.trim()?.toLowerCase()) { // in case it is enabled, log that Logger.log( - 'We have enabled DB alert for \'ledger_null\' instances. This would send email in case the \'ledger_id\' column in \'org_agents\' table is set to null', + "We have enabled DB alert for 'ledger_null' instances. This would send email in case the 'ledger_id' column in 'org_agents' table is set to null", 'DB alert enabled' ); } @@ -130,9 +139,8 @@ async function bootstrap(): Promise { if ('true' === (process.env.HIDE_EXPERIMENTAL_OIDC_CONTROLLERS || 'true').trim().toLowerCase()) { Logger.warn('Hiding experimental OIDC Controllers: OID4VC, OID4VP, x509 in OpenAPI docs'); Logger.verbose( - 'To enable the use of experimental OIDC controllers. Set, \'HIDE_EXPERIMENTAL_OIDC_CONTROLLERS\' env variable to false' + "To enable the use of experimental OIDC controllers. Set, 'HIDE_EXPERIMENTAL_OIDC_CONTROLLERS' env variable to false" ); } - } bootstrap(); diff --git a/apps/api-gateway/src/platform/platform.controller.ts b/apps/api-gateway/src/platform/platform.controller.ts index cfd77a1a0..a1b860b68 100644 --- a/apps/api-gateway/src/platform/platform.controller.ts +++ b/apps/api-gateway/src/platform/platform.controller.ts @@ -7,6 +7,7 @@ import { Logger, Param, Post, + Put, Query, Res, UseFilters, @@ -33,6 +34,8 @@ import { OrgRoles } from 'libs/org-roles/enums'; import { Roles } from '../authz/decorators/roles.decorator'; import { OrgRolesGuard } from '../authz/guards/org-roles.guard'; import { CreateEcosystemInvitationDto } from '../ecosystem/dtos/send-ecosystem-invitation'; +import { EnableEcosystemDto } from '../ecosystem/dtos/enable-ecosystem'; +import { EcosystemFeatureGuard } from '../authz/guards/ecosystem-feature-guard'; @Controller('') @UseFilters(CustomExceptionFilter) @@ -234,7 +237,7 @@ export class PlatformController { description: 'Success', type: ApiResponseDto }) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @UseGuards(AuthGuard('jwt'), OrgRolesGuard, EcosystemFeatureGuard) @ApiBearerAuth() async createInvitation( @Body() createEcosystemInvitationDto: CreateEcosystemInvitationDto, @@ -264,7 +267,7 @@ export class PlatformController { description: 'Invitations fetched successfully' }) @Roles(OrgRoles.PLATFORM_ADMIN) - @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @UseGuards(AuthGuard('jwt'), OrgRolesGuard, EcosystemFeatureGuard) @ApiBearerAuth() async getInvitations(@User() reqUser: user, @Res() res: Response): Promise { const invitations = await this.platformService.getInvitationsByUserId(reqUser.id); @@ -275,4 +278,34 @@ export class PlatformController { data: invitations }); } + + /** + * Update ecosystem enable/disable flag + */ + @Put('/config/ecosystem') + @Roles(OrgRoles.PLATFORM_ADMIN) + @ApiOperation({ + summary: 'Enable or disable ecosystem feature', + description: 'Platform admin can enable or disable ecosystem feature on the platform' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Ecosystem configuration updated successfully', + type: ApiResponseDto + }) + @UseGuards(AuthGuard('jwt'), OrgRolesGuard) + @ApiBearerAuth() + async updateEcosystemConfig( + @Body() platformConfigDto: EnableEcosystemDto, + @User() reqUser: user, + @Res() res: Response + ): Promise { + await this.platformService.updateEcosystemConfig(platformConfigDto.isEcosystemEnabled, reqUser.id); + + const finalResponse: IResponse = { + statusCode: HttpStatus.OK, + message: ResponseMessages.ecosystem.success.updateEcosystemConfig + }; + return res.status(HttpStatus.OK).json(finalResponse); + } } diff --git a/apps/api-gateway/src/platform/platform.module.ts b/apps/api-gateway/src/platform/platform.module.ts index d169ee4cf..bfffd4fb0 100644 --- a/apps/api-gateway/src/platform/platform.module.ts +++ b/apps/api-gateway/src/platform/platform.module.ts @@ -1,13 +1,17 @@ +import { ClientsModule, Transport } from '@nestjs/microservices'; + +import { CommonConstants } from '@credebl/common/common.constant'; +import { ConfigModule } from '@nestjs/config'; +import { EcosystemModule as EcosystemServiceModule } from 'apps/ecosystem/src/ecosystem.module'; import { Module } from '@nestjs/common'; +import { NATSClient } from '@credebl/common/NATSClient'; import { PlatformController } from './platform.controller'; import { PlatformService } from './platform.service'; -import { ClientsModule, Transport } from '@nestjs/microservices'; -import { ConfigModule } from '@nestjs/config'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { CommonConstants } from '@credebl/common/common.constant'; -import { NATSClient } from '@credebl/common/NATSClient'; + @Module({ imports: [ + EcosystemServiceModule, ConfigModule.forRoot(), ClientsModule.register([ { @@ -18,6 +22,7 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]) ], controllers: [PlatformController], - providers: [PlatformService, NATSClient] + providers: [PlatformService, NATSClient], + exports: [EcosystemServiceModule] }) export class PlatformModule {} diff --git a/apps/api-gateway/src/platform/platform.service.ts b/apps/api-gateway/src/platform/platform.service.ts index d44ab3166..1c6a084c4 100644 --- a/apps/api-gateway/src/platform/platform.service.ts +++ b/apps/api-gateway/src/platform/platform.service.ts @@ -65,4 +65,14 @@ export class PlatformService extends BaseService { async getInvitationsByUserId(userId: string): Promise { return this.natsClient.sendNatsMessage(this.platformServiceProxy, 'get-ecosystem-invitations-by-user', { userId }); } + + /** + * Update ecosystem enable/disable flag + */ + async updateEcosystemConfig(isEcosystemEnabled: boolean, platformAdminId: string): Promise<{ message: string }> { + return this.natsClient.sendNatsMessage(this.platformServiceProxy, 'update-ecosystem-config', { + isEcosystemEnabled, + platformAdminId + }); + } } diff --git a/apps/ecosystem/repositories/ecosystem.repository.ts b/apps/ecosystem/repositories/ecosystem.repository.ts index dff5c228c..11d53d526 100644 --- a/apps/ecosystem/repositories/ecosystem.repository.ts +++ b/apps/ecosystem/repositories/ecosystem.repository.ts @@ -1146,7 +1146,7 @@ export class EcosystemRepository { } } - async deleteIntent(data: { ecosystemId: string; intentId: string }): Promise { + async deleteIntent(data: { ecosystemId: string; intentId: string; userId: string }): Promise { const intent = await this.prisma.intents.findFirst({ where: { id: data.intentId, @@ -1167,4 +1167,78 @@ export class EcosystemRepository { return intent; } + + /** + * Update ecosystem enable/disable flag + */ + async updateEcosystemConfig(payload: { isEcosystemEnabled: boolean; userId: string }): Promise { + const { isEcosystemEnabled } = payload; + + const existingConfig = await this.prisma.platform_config.findFirst(); + + if (!existingConfig) { + throw new RpcException({ + statusCode: HttpStatus.NOT_FOUND, + message: ResponseMessages.ecosystem.error.platformConfigNotFound + }); + } + + await this.prisma.platform_config.update({ + where: { id: existingConfig.id }, + data: { + isEcosystemEnabled, + lastChangedBy: payload.userId, + lastChangedDateTime: new Date() + } + }); + } + + /** + * Fetches the global platform configuration + */ + async getPlatformConfig(): Promise<{ isEcosystemEnabled: boolean } | null> { + return this.prisma.platform_config.findFirst({ + select: { + isEcosystemEnabled: true + } + }); + } + async getEcosystemsForEcosystemLead(userId: string): Promise { + return this.prisma.ecosystem.findMany({ + where: { + deletedAt: null, + ecosystemOrgs: { + some: { + userId, + deletedAt: null, + ecosystemRole: { + name: OrgRoles.ECOSYSTEM_LEAD + } + } + } + }, + orderBy: { + createDateTime: 'desc' + }, + include: { + ecosystemOrgs: { + where: { + userId, + deletedAt: null + }, + include: { + ecosystemRole: true, + organisation: { + select: { + id: true, + name: true, + orgSlug: true, + logoUrl: true + } + } + } + } + } + }); + } } diff --git a/apps/ecosystem/src/ecosystem.controller.ts b/apps/ecosystem/src/ecosystem.controller.ts index 8a0b88bc0..33d0017aa 100644 --- a/apps/ecosystem/src/ecosystem.controller.ts +++ b/apps/ecosystem/src/ecosystem.controller.ts @@ -67,9 +67,9 @@ export class EcosystemController { * Used by Platform Admin * @returns List of ecosystems */ - @MessagePattern({ cmd: 'get-all-ecosystems' }) - async getAllEcosystems(): Promise { - return this.ecosystemService.getAllEcosystems(); + @MessagePattern({ cmd: 'get-ecosystems' }) + async getEcosystems(payload: { userId: string }): Promise { + return this.ecosystemService.getEcosystems(payload.userId); } /** @@ -288,7 +288,18 @@ export class EcosystemController { * @returns Deleted intent */ @MessagePattern({ cmd: 'delete-intent' }) - async deleteIntent(payload: { ecosystemId: string; intentId: string; user: { id: string } }): Promise { - return this.ecosystemService.deleteIntent(payload.ecosystemId, payload.intentId, payload.user); + async deleteIntent(payload: { ecosystemId: string; intentId: string; userId: string }): Promise { + return this.ecosystemService.deleteIntent(payload); + } + + /** + * Update ecosystem platform configuration + */ + @MessagePattern({ cmd: 'update-ecosystem-config' }) + async updateEcosystemConfig(payload: { + isEcosystemEnabled: boolean; + platformAdminId: string; + }): Promise<{ message: string }> { + return this.ecosystemService.updateEcosystemConfig(payload); } } diff --git a/apps/ecosystem/src/ecosystem.service.ts b/apps/ecosystem/src/ecosystem.service.ts index 8cfb487c1..728b3f89e 100644 --- a/apps/ecosystem/src/ecosystem.service.ts +++ b/apps/ecosystem/src/ecosystem.service.ts @@ -280,11 +280,19 @@ export class EcosystemService { } } - async getAllEcosystems(): Promise { + async getEcosystems(userId: string): Promise { + if (!userId) { + throw new BadRequestException(ResponseMessages.ecosystem.error.userIdMissing); + } try { - return await this.ecosystemRepository.getAllEcosystems(); + const leadEcosystems = await this.ecosystemRepository.getEcosystemsForEcosystemLead(userId); + + if (0 < leadEcosystems.length) { + return leadEcosystems; + } + return this.ecosystemRepository.getAllEcosystems(); } catch (error) { - this.logger.error('getAllEcosystems error', error); + this.logger.error('getEcosystems error', error); throw new InternalServerErrorException(ResponseMessages.ecosystem.error.fetch); } } @@ -666,14 +674,38 @@ export class EcosystemService { /** * Delete an intent */ - async deleteIntent(ecosystemId: string, intentId: string, user: { id: string }): Promise { - if (!ecosystemId || !intentId || !user?.id) { - throw new BadRequestException('ecosystemId, intentId and user are required'); - } + async deleteIntent(data: { ecosystemId: string; intentId: string; userId: string }): Promise { + const { ecosystemId, intentId, userId } = data; return this.ecosystemRepository.deleteIntent({ ecosystemId, - intentId + intentId, + userId }); } + + /** + * Update ecosystem enable/disable flag + */ + async updateEcosystemConfig(payload: { + isEcosystemEnabled: boolean; + platformAdminId: string; + }): Promise<{ message: string }> { + const { isEcosystemEnabled, platformAdminId } = payload; + if (!platformAdminId) { + throw new BadRequestException(ResponseMessages.ecosystem.error.platformIdRequired); + } + if ('boolean' !== typeof isEcosystemEnabled) { + throw new BadRequestException(ResponseMessages.ecosystem.error.invalidEcosystemEnabledFlag); + } + + await this.ecosystemRepository.updateEcosystemConfig({ + isEcosystemEnabled, + userId: platformAdminId + }); + + return { + message: ResponseMessages.ecosystem.success.updateEcosystemConfig + }; + } } diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index afa96cfa8..fbcde1508 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -197,9 +197,11 @@ export const ResponseMessages = { deleteIntent: 'Ecosystem intent deleted successfully', fetchIntents: 'Ecosystem intents fetched successfully', fetchIntentTemplates: 'Ecosystem intent templates fetched successfully', - fetchVerificationTemplates: 'Verification templates fetched successfully' + fetchVerificationTemplates: 'Verification templates fetched successfully', + updateEcosystemConfig: 'Ecosystem configuration updated successfully' }, error: { + featureIsDisabled: `You don't have access to this feature`, memberInviteFailed: 'Failed to send invitation for the member', failInvitationUpdate: 'Failed to update Ecosystem Invitation', ecosystemIdIsRequired: 'ecosystemId is required', @@ -264,6 +266,7 @@ export const ResponseMessages = { invalidFormatOfEcosystemId: 'Invalid format of ecosystemId', invalidFormatOfIntentId: 'Invalid format of ecosystemId', emailOrPlatformAdminIdMissing: 'Email or platformAdminId missing', + platformIdRequired: 'PlatformId is required', userIdMissing: 'UserId is required', fetch: 'Error while fetching ecosystems', invitationRequired: 'Accepted invitation is required to create ecosystem', @@ -279,7 +282,8 @@ export const ResponseMessages = { ecosystemOrgsFetchFailed: 'Failed to fetch ecosystem orgs', ecosystemMemberStatusFail: 'Failed to update ecosystem member status', failedEcosystemOrgUpdate: 'Failed to update ecosystem org', - invitationMemberfail: 'Failed to fetch invitation members' + invitationMemberfail: 'Failed to fetch invitation members', + invalidEcosystemEnabledFlag: 'Invalid ecosystem enabled flag' } }, schema: { diff --git a/libs/prisma-service/prisma/data/credebl-master-table.json b/libs/prisma-service/prisma/data/credebl-master-table.json index c4167aa18..d040514ad 100644 --- a/libs/prisma-service/prisma/data/credebl-master-table.json +++ b/libs/prisma-service/prisma/data/credebl-master-table.json @@ -5,6 +5,7 @@ "username": "credebl", "sgApiKey": "###Sendgrid Key###", "emailFrom": "##Senders Mail ID##", + "isEcosystemEnabled": false, "apiEndpoint": "## Platform API Ip Address##", "tailsFileServer": "##Machine Ip Address for agent setup##" }, diff --git a/libs/prisma-service/prisma/migrations/20260127123306_added_is_ecosystem_enabled_column_in_platform_config/migration.sql b/libs/prisma-service/prisma/migrations/20260127123306_added_is_ecosystem_enabled_column_in_platform_config/migration.sql new file mode 100644 index 000000000..d279c04e9 --- /dev/null +++ b/libs/prisma-service/prisma/migrations/20260127123306_added_is_ecosystem_enabled_column_in_platform_config/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "platform_config" ADD COLUMN "isEcosystemEnabled" BOOLEAN NOT NULL DEFAULT false; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index cdce0028e..dfbc42f8f 100644 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -198,6 +198,7 @@ model platform_config { username String @db.VarChar sgApiKey String @db.VarChar emailFrom String @db.VarChar + isEcosystemEnabled Boolean @default(false) apiEndpoint String @db.VarChar tailsFileServer String @db.VarChar createDateTime DateTime @default(now()) @db.Timestamptz(6)