Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added deleted metadata function and table #763

Merged
merged 5 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/agent-service/src/agent-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,8 @@ export class AgentServiceController {
}

@MessagePattern({ cmd: 'delete-wallet' })
async deleteWallet(payload: { orgId }): Promise<object> {
return this.agentServiceService.deleteWallet(payload.orgId);
async deleteWallet(payload: { orgId, user }): Promise<object> {
return this.agentServiceService.deleteWallet(payload.orgId, payload.user);
}

@MessagePattern({ cmd: 'agent-receive-invitation-url' })
Expand Down
4 changes: 3 additions & 1 deletion apps/agent-service/src/agent-service.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ConnectionService } from 'apps/connection/src/connection.service';
import { ConnectionRepository } from 'apps/connection/src/connection.repository';
import { CacheModule } from '@nestjs/cache-manager';
import { getNatsOptions } from '@credebl/common/nats.config';
import { UserActivityRepository } from 'libs/user-activity/repositories';

@Module({
imports: [
Expand All @@ -31,7 +32,8 @@ import { getNatsOptions } from '@credebl/common/nats.config';
PrismaService,
Logger,
ConnectionService,
ConnectionRepository
ConnectionRepository,
UserActivityRepository
],
exports: [AgentServiceService, AgentServiceRepository, AgentServiceModule]
})
Expand Down
105 changes: 66 additions & 39 deletions apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
BadRequestException,
ConflictException,
HttpException,
HttpStatus,
Inject,
Injectable,
InternalServerErrorException,
Expand Down Expand Up @@ -56,7 +57,7 @@ import {
} from './interface/agent-service.interface';
import { AgentSpinUpStatus, AgentType, DidMethod, Ledgers, OrgAgentType } from '@credebl/enum/enum';
import { AgentServiceRepository } from './repositories/agent-service.repository';
import { Prisma, ledgers, org_agents, organisation, platform_config } from '@prisma/client';
import { Prisma, RecordType, ledgers, org_agents, organisation, platform_config, user } from '@prisma/client';
import { CommonConstants } from '@credebl/common/common.constant';
import { CommonService } from '@credebl/common';
import { GetSchemaAgentRedirection } from 'apps/ledger/src/schema/schema.interface';
Expand All @@ -72,6 +73,7 @@ import { IConnectionDetailsById } from 'apps/api-gateway/src/interfaces/IConnect
import { ledgerName } from '@credebl/common/cast.helper';
import { InvitationMessage } from '@credebl/common/interfaces/agent-service.interface';
import * as CryptoJS from 'crypto-js';
import { UserActivityRepository } from 'libs/user-activity/repositories';

@Injectable()
@WebSocketGateway()
Expand All @@ -83,7 +85,8 @@ export class AgentServiceService {
private readonly commonService: CommonService,
private readonly connectionService: ConnectionService,
@Inject('NATS_CLIENT') private readonly agentServiceProxy: ClientProxy,
@Inject(CACHE_MANAGER) private cacheService: Cache
@Inject(CACHE_MANAGER) private cacheService: Cache,
private readonly userActivityRepository: UserActivityRepository
) {}

async ReplaceAt(input, search, replace, start, end): Promise<string> {
Expand Down Expand Up @@ -953,8 +956,8 @@ export class AgentServiceService {

const createdDidDetails = {
orgId,
did: didDetails?.['did'] ?? didDetails?.["didState"]?.["did"],
didDocument: didDetails?.['didDocument'] ?? didDetails?.['didDoc'] ?? didDetails?.["didState"]?.["didDocument"],
did: didDetails?.['did'] ?? didDetails?.['didState']?.['did'],
didDocument: didDetails?.['didDocument'] ?? didDetails?.['didDoc'] ?? didDetails?.['didState']?.['didDocument'],
isPrimaryDid,
orgAgentId: agentDetails.id,
userId: user.id
Expand Down Expand Up @@ -1021,9 +1024,7 @@ export class AgentServiceService {
);
}

private async storeDid(createdDidDetails): Promise<
OrgDid
> {
private async storeDid(createdDidDetails): Promise<OrgDid> {
const storeDidDetails = await this.agentServiceRepository.storeDidDetails(createdDidDetails);

if (!storeDidDetails) {
Expand Down Expand Up @@ -1632,53 +1633,79 @@ export class AgentServiceService {
}
}

async deleteWallet(orgId: string): Promise<object> {
async deleteWallet(orgId: string, user: user): Promise<object> {
try {
// Retrieve the API key and agent information
const [getApiKeyResult, orgAgentResult] = await Promise.allSettled([
this.getOrgAgentApiKey(orgId),
this.agentServiceRepository.getAgentApiKey(orgId)
]);

if (getApiKeyResult.status === 'rejected') {
throw new InternalServerErrorException(`Failed to get API key: ${getApiKeyResult.reason}`);
}
// Retrieve the API key and agent information
const [getApiKeyResult, orgAgentResult] = await Promise.allSettled([
this.getOrgAgentApiKey(orgId),
this.agentServiceRepository.getAgentApiKey(orgId)
]);

if (orgAgentResult.status === 'rejected') {
throw new InternalServerErrorException(`Failed to get agent information: ${orgAgentResult.reason}`);
}
if (getApiKeyResult.status === 'rejected') {
throw new InternalServerErrorException(`Failed to get API key: ${getApiKeyResult.reason}`);
}

const getApiKey = getApiKeyResult?.value;
const orgAgent = orgAgentResult?.value;
if (orgAgentResult.status === 'rejected') {
throw new InternalServerErrorException(`Failed to get agent information: ${orgAgentResult.reason}`);
}

const orgAgentTypeResult = await this.agentServiceRepository.getOrgAgentType(orgAgent.orgAgentTypeId);
const getApiKey = getApiKeyResult?.value;
const orgAgent = orgAgentResult?.value;

if (!orgAgentTypeResult) {
throw new NotFoundException(ResponseMessages.agent.error.orgAgentNotFound);
}
const orgAgentTypeResult = await this.agentServiceRepository.getOrgAgentType(orgAgent.orgAgentTypeId);

if (!orgAgentTypeResult) {
throw new NotFoundException(ResponseMessages.agent.error.orgAgentNotFound);
}

// Determine the URL based on the agent type
const url = orgAgentTypeResult.agent === OrgAgentType.SHARED
? `${orgAgent.agentEndPoint}${CommonConstants.URL_SHAGENT_DELETE_SUB_WALLET}`.replace('#', orgAgent?.tenantId)
: `${orgAgent.agentEndPoint}${CommonConstants.URL_DELETE_WALLET}`;
// Determine the URL based on the agent type
const url =
orgAgentTypeResult.agent === OrgAgentType.SHARED
? `${orgAgent.agentEndPoint}${CommonConstants.URL_SHAGENT_DELETE_SUB_WALLET}`.replace('#', orgAgent?.tenantId)
: `${orgAgent.agentEndPoint}${CommonConstants.URL_DELETE_WALLET}`;

// Make the HTTP DELETE request
const deleteWallet = await this.commonService.httpDelete(url, {
headers: { authorization: getApiKey }
// Make the HTTP DELETE request
const deleteWallet = await this.commonService
.httpDelete(url, {
headers: { authorization: getApiKey }
})
.then(async (response) => response);

if (deleteWallet.status === 204) {
const deleteOrgAgent = await this.agentServiceRepository.deleteOrgAgentByOrg(orgId);
return deleteOrgAgent;
if (deleteWallet.status === HttpStatus.NO_CONTENT) {
const {orgDid, agentInvitation, deleteOrgAgent} = await this.agentServiceRepository.deleteOrgAgentByOrg(orgId);

this.logger.log(`orgDid :::: ${JSON.stringify(orgDid)}`);
this.logger.log(`agentInvitation :::: ${JSON.stringify(agentInvitation)}`);
this.logger.log(`deleteOrgAgent :::: ${JSON.stringify(deleteOrgAgent)}`);

const deletions = [
{ records: orgDid.count, tableName: 'org_dids' },
{ records: agentInvitation.count, tableName: 'agent_invitations' },
{ records: deleteOrgAgent ? 1 : 0, tableName: 'org_agents' }
];

const logDeletionActivity = async (records, tableName): Promise<void> => {
if (records) {
const txnMetadata = {
deletedRecordsCount: records,
deletedRecordInTable: tableName
};
const recordType = RecordType.WALLET;
await this.userActivityRepository._orgDeletedActivity(orgId, user, txnMetadata, recordType);
}
};

for (const { records, tableName } of deletions) {
await logDeletionActivity(records, tableName);
}
return deleteOrgAgent;
}
} catch (error) {
this.logger.error(`Error in delete wallet in agent service: ${JSON.stringify(error.message)}`);
throw new RpcException(error.response ? error.response : error);
this.logger.error(`Error in delete wallet in agent service: ${JSON.stringify(error.message)}`);
throw new RpcException(error.response ? error.response : error);
}
}


async receiveInvitationUrl(receiveInvitationUrl: IReceiveInvitationUrl, url: string, orgId: string): Promise<string> {
try {
const getApiKey = await this.getOrgAgentApiKey(orgId);
Expand Down
11 changes: 7 additions & 4 deletions apps/agent-service/src/repositories/agent-service.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,20 +485,23 @@ export class AgentServiceRepository {
}
}

// eslint-disable-next-line camelcase
async deleteOrgAgentByOrg(orgId: string): Promise<org_agents> {
async deleteOrgAgentByOrg(orgId: string): Promise<{orgDid: Prisma.BatchPayload;
agentInvitation: Prisma.BatchPayload;
// eslint-disable-next-line camelcase
deleteOrgAgent: org_agents;
}> {
try {
return await this.prisma.$transaction(async (prisma) => {
// Concurrently delete related records
await Promise.all([
const [orgDid, agentInvitation] = await Promise.all([
prisma.org_dids.deleteMany({ where: { orgId } }),
prisma.agent_invitations.deleteMany({ where: { orgId } })
]);

// Delete the organization agent
const deleteOrgAgent = await prisma.org_agents.delete({ where: { orgId } });

return deleteOrgAgent;
return {orgDid, agentInvitation, deleteOrgAgent};
});
} catch (error) {
this.logger.error(`[deleteOrgAgentByOrg] - Error deleting org agent record: ${error.message}`);
Expand Down
3 changes: 2 additions & 1 deletion apps/api-gateway/src/organization/organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,11 @@ export class OrganizationController {
@Roles(OrgRoles.OWNER)
async deleteOrganization(
@Param('orgId') orgId: string,
@User() user: user,
@Res() res: Response
): Promise<Response> {

await this.organizationService.deleteOrganization(orgId);
await this.organizationService.deleteOrganization(orgId, user);

const finalResponse: IResponse = {
statusCode: HttpStatus.OK,
Expand Down
7 changes: 4 additions & 3 deletions apps/api-gateway/src/organization/organization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CreateOrganizationDto } from './dtos/create-organization-dto';
import { BulkSendInvitationDto } from './dtos/send-invitation.dto';
import { UpdateUserRolesDto } from './dtos/update-user-roles.dto';
import { UpdateOrganizationDto } from './dtos/update-organization-dto';
import { organisation } from '@prisma/client';
import { organisation, user } from '@prisma/client';
import { IDidList, IGetOrgById, IGetOrganization } from 'apps/organization/interfaces/organization.interface';
import { IOrgUsers } from 'apps/user/interfaces/user.interface';
import { IOrgCredentials, IOrganization, IOrganizationInvitations, IOrganizationDashboard, IDeleteOrganization } from '@credebl/common/interfaces/organization.interface';
Expand Down Expand Up @@ -203,9 +203,10 @@ export class OrganizationService extends BaseService {
}

async deleteOrganization(
orgId: string
orgId: string,
user: user
): Promise<IDeleteOrganization> {
const payload = { orgId };
const payload = { orgId, user };

return this.sendNatsMessage(this.serviceProxy, 'delete-organization', payload);
}
Expand Down
12 changes: 8 additions & 4 deletions apps/organization/repositories/organization.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,11 @@ export class OrganizationRepository {
}
}

async deleteOrg(id: string): Promise<IDeleteOrganization> {
async deleteOrg(id: string):Promise<{
deletedUserActivity: Prisma.BatchPayload;
deletedUserOrgRole: Prisma.BatchPayload;
deleteOrg: IDeleteOrganization
}> {
const tablesToCheck = [
'org_invitations',
'org_agents',
Expand Down Expand Up @@ -772,15 +776,15 @@ export class OrganizationRepository {
}

// User activity delete by orgId
await prisma.user_activity.deleteMany({ where: { orgId: id } });
const deletedUserActivity = await prisma.user_activity.deleteMany({ where: { orgId: id } });

// User org role delete by orgId
await prisma.user_org_roles.deleteMany({ where: { orgId: id } });
const deletedUserOrgRole = await prisma.user_org_roles.deleteMany({ where: { orgId: id } });

// If no references are found, delete the organization
const deleteOrg = await prisma.organisation.delete({ where: { id } });

return deleteOrg;
return {deletedUserActivity, deletedUserOrgRole, deleteOrg};
});
} catch (error) {
this.logger.error(`Error in deleteOrg: ${error}`);
Expand Down
6 changes: 3 additions & 3 deletions apps/organization/src/organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CreateOrganizationDto } from '../dtos/create-organization.dto';
import { BulkSendInvitationDto } from '../dtos/send-invitation.dto';
import { UpdateInvitationDto } from '../dtos/update-invitation.dt';
import { IDidList, IGetOrgById, IGetOrganization, IUpdateOrganization, Payload } from '../interfaces/organization.interface';
import { organisation } from '@prisma/client';
import { organisation, user } from '@prisma/client';
import { IOrgCredentials, IOrganizationInvitations, IOrganization, IOrganizationDashboard, IDeleteOrganization } from '@credebl/common/interfaces/organization.interface';
import { IAccessTokenData } from '@credebl/common/interfaces/interface';
import { IClientRoles } from '@credebl/client-registration/interfaces/client.interface';
Expand Down Expand Up @@ -227,8 +227,8 @@ export class OrganizationController {
}

@MessagePattern({ cmd: 'delete-organization' })
async deleteOrganization(payload: { orgId: string }): Promise<IDeleteOrganization> {
return this.organizationService.deleteOrganization(payload.orgId);
async deleteOrganization(payload: { orgId: string, user: user }): Promise<IDeleteOrganization> {
return this.organizationService.deleteOrganization(payload.orgId, payload.user);
}

@MessagePattern({ cmd: 'delete-org-client-credentials' })
Expand Down
2 changes: 1 addition & 1 deletion apps/organization/src/organization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { AwsService } from '@credebl/aws';
providers: [
OrganizationService, OrganizationRepository, PrismaService,
Logger, OrgRolesService, UserOrgRolesService, OrgRolesRepository, UserActivityRepository,
UserOrgRolesRepository, UserRepository, UserActivityService,
UserActivityRepository, UserOrgRolesRepository, UserRepository, UserActivityService,
ClientRegistrationService,
KeycloakUrlService,
AwsService
Expand Down
45 changes: 37 additions & 8 deletions apps/organization/src/organization.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable prefer-destructuring */
// eslint-disable-next-line camelcase
import { org_invitations, organisation, user } from '@prisma/client';
import { RecordType, org_invitations, organisation, user } from '@prisma/client';
import {
Injectable,
Logger,
Expand Down Expand Up @@ -46,6 +46,7 @@ import { ClientCredentialTokenPayloadDto } from '@credebl/client-registration/dt
import { IAccessTokenData } from '@credebl/common/interfaces/interface';
import { IClientRoles } from '@credebl/client-registration/interfaces/client.interface';
import { toNumber } from '@credebl/common/cast.helper';
import { UserActivityRepository } from 'libs/user-activity/repositories';
@Injectable()
export class OrganizationService {
constructor(
Expand All @@ -59,8 +60,10 @@ export class OrganizationService {
private readonly userActivityService: UserActivityService,
private readonly logger: Logger,
@Inject(CACHE_MANAGER) private cacheService: Cache,
private readonly clientRegistrationService: ClientRegistrationService
private readonly clientRegistrationService: ClientRegistrationService,
private readonly userActivityRepository: UserActivityRepository
) {}


/**
*
Expand Down Expand Up @@ -1298,14 +1301,40 @@ export class OrganizationService {
}
}

async deleteOrganization(orgId: string): Promise<IDeleteOrganization> {
async deleteOrganization(orgId: string, user: user): Promise<IDeleteOrganization> {
try {
const deleteOrg = await this.organizationRepository.deleteOrg(orgId);
return deleteOrg;

const { deletedUserActivity, deletedUserOrgRole, deleteOrg } = await this.organizationRepository.deleteOrg(orgId);

this.logger.log(`deletedUserActivity ::: ${JSON.stringify(deletedUserActivity)}`);
this.logger.log(`deletedUserOrgRole ::: ${JSON.stringify(deletedUserOrgRole)}`);
this.logger.log(`deleteOrg ::: ${JSON.stringify(deleteOrg)}`);

const deletions = [
{ records: deletedUserActivity.count, tableName: 'user_activity' },
{ records: deletedUserOrgRole.count, tableName: 'user_org_roles' },
{ records: deleteOrg ? 1 : 0, tableName: 'organization' }
];

const logDeletionActivity = async (records, tableName): Promise<void> => {
if (records) {
const txnMetadata = {
deletedRecordsCount: records,
deletedRecordInTable: tableName
};
const recordType = RecordType.ORGANIZATION;
await this.userActivityRepository._orgDeletedActivity(orgId, user, txnMetadata, recordType);
}
};

for (const { records, tableName } of deletions) {
await logDeletionActivity(records, tableName);
}

return deleteOrg;

} catch (error) {
this.logger.error(`delete organization: ${JSON.stringify(error)}`);
throw new RpcException(error.response ? error.response : error);
this.logger.error(`delete organization: ${JSON.stringify(error)}`);
throw new RpcException(error.response ? error.response : error);
}
}

Expand Down
Loading