Skip to content

Commit

Permalink
Signup page backend (#2832)
Browse files Browse the repository at this point in the history
* feat: signup page backend

* feat: small changes to enable token creation without enduser

* feat: pr comments fixes

* feat: added integration test for collection-flow.signup.controller

* feat: remove console.log

* feat: small cr comment fix

* feat: pr comments fix
  • Loading branch information
tomer-shvadron authored Nov 13, 2024
1 parent 64ba366 commit d01f56b
Show file tree
Hide file tree
Showing 24 changed files with 465 additions and 77 deletions.
2 changes: 1 addition & 1 deletion services/workflows-service/prisma/data-migrations
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- DropForeignKey
ALTER TABLE "WorkflowRuntimeDataToken" DROP CONSTRAINT "WorkflowRuntimeDataToken_endUserId_fkey";

-- AlterTable
ALTER TABLE "WorkflowRuntimeDataToken" ALTER COLUMN "endUserId" DROP NOT NULL;

-- AddForeignKey
ALTER TABLE "WorkflowRuntimeDataToken" ADD CONSTRAINT "WorkflowRuntimeDataToken_endUserId_fkey" FOREIGN KEY ("endUserId") REFERENCES "EndUser"("id") ON DELETE SET NULL ON UPDATE CASCADE;
6 changes: 3 additions & 3 deletions services/workflows-service/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,8 @@ model WorkflowRuntimeDataToken {
token String @unique @default(dbgenerated("gen_random_uuid()")) @db.Uuid
workflowRuntimeDataId String
workflowRuntimeData WorkflowRuntimeData @relation(fields: [workflowRuntimeDataId], references: [id])
endUserId String
endUser EndUser @relation(fields: [endUserId], references: [id])
endUserId String?
endUser EndUser? @relation(fields: [endUserId], references: [id])
projectId String
project Project @relation(fields: [projectId], references: [id])
createdAt DateTime @default(now())
Expand Down Expand Up @@ -815,7 +815,7 @@ model Alert {
status AlertStatus
tags String[]
severity AlertSeverity?
state AlertState
decisionAt DateTime?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Prisma } from '@prisma/client';
import { Prisma, PrismaClient } from '@prisma/client';
import { Injectable } from '@nestjs/common';
import type { PrismaTransaction, TProjectId } from '@/types';
import { PrismaService } from '@/prisma/prisma.service';

@Injectable()
export class WorkflowTokenRepository {
constructor(private readonly prisma: PrismaService) {}
constructor(private readonly prismaService: PrismaService) {}

async create(
projectId: TProjectId,
data: Pick<
Prisma.WorkflowRuntimeDataTokenUncheckedCreateInput,
'workflowRuntimeDataId' | 'endUserId' | 'expiresAt'
>,
transaction: PrismaTransaction | PrismaService = this.prisma,
transaction: PrismaTransaction | PrismaService = this.prismaService,
) {
return await transaction.workflowRuntimeDataToken.create({
data: {
Expand All @@ -24,16 +24,25 @@ export class WorkflowTokenRepository {
}

async findByTokenUnscoped(token: string) {
return await this.prisma.workflowRuntimeDataToken.findFirst({
return await this.prismaService.workflowRuntimeDataToken.findFirst({
where: {
token,
AND: [{ expiresAt: { gt: new Date() } }, { deletedAt: null }],
},
});
}

async findByTokenWithExpiredUnscoped(token: string) {
return await this.prismaService.workflowRuntimeDataToken.findFirst({
where: {
token,
deletedAt: null,
},
});
}

async deleteByTokenUnscoped(token: string) {
return await this.prisma.workflowRuntimeDataToken.updateMany({
return await this.prismaService.workflowRuntimeDataToken.updateMany({
data: {
deletedAt: new Date(),
},
Expand All @@ -43,4 +52,17 @@ export class WorkflowTokenRepository {
},
});
}

async updateByToken(
token: string,
data: Prisma.WorkflowRuntimeDataTokenUpdateInput,
transaction: PrismaTransaction | PrismaClient = this.prismaService,
) {
return await transaction.workflowRuntimeDataToken.update({
where: {
token,
},
data,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,19 @@ export class WorkflowTokenService {
return await this.workflowTokenRepository.findByTokenUnscoped(token);
}

async findByTokenWithExpiredUnscoped(token: string) {
return await this.workflowTokenRepository.findByTokenWithExpiredUnscoped(token);
}

async deleteByToken(token: string) {
return await this.workflowTokenRepository.deleteByTokenUnscoped(token);
}

async updateByToken(
token: string,
data: Parameters<typeof this.workflowTokenRepository.updateByToken>[1],
transaction?: PrismaTransaction,
) {
return await this.workflowTokenRepository.updateByToken(token, data, transaction);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { WorkflowRuntimeDataRepository } from '@/workflow/workflow-runtime-data.
import { WorkflowModule } from '@/workflow/workflow.module';
import { HttpModule } from '@nestjs/axios';
import { Module } from '@nestjs/common';
import { CollectionFlowSignupController } from '@/collection-flow/controllers/collection-flow.signup.controller';

@Module({
imports: [
Expand All @@ -57,6 +58,7 @@ import { Module } from '@nestjs/common';
controllers: [
CollectionFlowController,
CollectionFlowFilesController,
CollectionFlowSignupController,
CollectionFlowBusinessController,
CollectionFlowEndUserController,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
} from '@/providers/translation/translation.service';
import type { TProjectId, TProjectIds } from '@/types';
import { UiDefinitionService } from '@/ui-definition/ui-definition.service';
import { WorkflowDefinitionRepository } from '@/workflow-defintion/workflow-definition.repository';
import { WorkflowRuntimeDataRepository } from '@/workflow/workflow-runtime-data.repository';
import { WorkflowService } from '@/workflow/workflow.service';
import { AnyRecord, DefaultContextSchema, TCollectionFlowConfig } from '@ballerine/common';
Expand All @@ -31,7 +30,6 @@ export class CollectionFlowService {
protected readonly logger: AppLoggerService,
protected readonly endUserService: EndUserService,
protected readonly workflowRuntimeDataRepository: WorkflowRuntimeDataRepository,
protected readonly workflowDefinitionRepository: WorkflowDefinitionRepository,
protected readonly workflowService: WorkflowService,
protected readonly businessService: BusinessService,
protected readonly uiDefinitionService: UiDefinitionService,
Expand Down Expand Up @@ -126,12 +124,10 @@ export class CollectionFlowService {
): ITranslationServiceResource[] | undefined {
if (!uiDefinition.locales) return undefined;

const resources = Object.entries(uiDefinition.locales).map(([language, resource]) => ({
return Object.entries(uiDefinition.locales).map(([language, resource]) => ({
language,
resource,
}));

return resources;
}

// async updateFlowConfiguration(
Expand Down Expand Up @@ -228,7 +224,7 @@ export class CollectionFlowService {
}

async syncWorkflow(payload: UpdateFlowDto, tokenScope: ITokenScope) {
if (payload.data.endUser) {
if (payload.data.endUser && tokenScope.endUserId) {
const { ballerineEntityId: _, ...endUserData } = payload.data.endUser;
await this.endUserService.updateById(tokenScope.endUserId, { data: endUserData });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { UnsupportedFlowTypeException } from '@/collection-flow/exceptions/unsup
import { FlowConfigurationModel } from '@/collection-flow/models/flow-configuration.model';
import { WorkflowAdapterManager } from '@/collection-flow/workflow-adapter.manager';
import { AppLoggerService } from '@/common/app-logger/app-logger.service';
import { type ITokenScope, TokenScope } from '@/common/decorators/token-scope.decorator';
import {
type ITokenScope,
type ITokenScopeWithEndUserId,
TokenScope,
} from '@/common/decorators/token-scope.decorator';
import { UseTokenAuthGuard } from '@/common/guards/token-guard/use-token-auth.decorator';
import { WorkflowService } from '@/workflow/workflow.service';
import { CollectionFlowStatusesEnum, getCollectionFlowState } from '@ballerine/common';
Expand All @@ -22,26 +26,27 @@ import { CollectionFlowMissingException } from '../exceptions/collection-flow-mi
export class CollectionFlowController {
constructor(
protected readonly appLogger: AppLoggerService,
protected readonly service: CollectionFlowService,
protected readonly adapterManager: WorkflowAdapterManager,
protected readonly workflowService: WorkflowService,
protected readonly adapterManager: WorkflowAdapterManager,
protected readonly collectionFlowService: CollectionFlowService,
) {}

@common.Get('/customer')
async getCustomer(@TokenScope() tokenScope: ITokenScope) {
return this.service.getCustomerDetails(tokenScope.projectId);
return this.collectionFlowService.getCustomerDetails(tokenScope.projectId);
}

@common.Get('/user')
async getUser(@TokenScope() tokenScope: ITokenScope) {
return this.service.getUser(tokenScope.endUserId, tokenScope.projectId);
async getUser(@TokenScope() tokenScope: ITokenScopeWithEndUserId) {
return this.collectionFlowService.getUser(tokenScope.endUserId, tokenScope.projectId);
}

@common.Get('/active-flow')
async getActiveFlow(@TokenScope() tokenScope: ITokenScope) {
const activeWorkflow = await this.service.getActiveFlow(tokenScope.workflowRuntimeDataId, [
tokenScope.projectId,
]);
const activeWorkflow = await this.collectionFlowService.getActiveFlow(
tokenScope.workflowRuntimeDataId,
[tokenScope.projectId],
);

if (!activeWorkflow) throw new common.InternalServerErrorException('Workflow not found.');

Expand All @@ -64,23 +69,24 @@ export class CollectionFlowController {

@common.Get('/context')
async getContext(@TokenScope() tokenScope: ITokenScope) {
return this.service.getCollectionFlowContext(tokenScope);
return this.collectionFlowService.getCollectionFlowContext(tokenScope);
}

@common.Get('/configuration/:language')
async getFlowConfiguration(
@TokenScope() tokenScope: ITokenScope,
@common.Param() params: GetFlowConfigurationInputDto,
): Promise<FlowConfigurationModel> {
const workflow = await this.service.getActiveFlow(tokenScope.workflowRuntimeDataId, [
tokenScope.projectId,
]);
const workflow = await this.collectionFlowService.getActiveFlow(
tokenScope.workflowRuntimeDataId,
[tokenScope.projectId],
);

if (!workflow) {
throw new common.InternalServerErrorException('Workflow not found.');
}

return this.service.getFlowConfiguration(
return this.collectionFlowService.getFlowConfiguration(
workflow.workflowDefinitionId,
workflow.context,
params.language,
Expand All @@ -94,12 +100,12 @@ export class CollectionFlowController {
@common.Body() { language }: UpdateFlowLanguageDto,
@TokenScope() tokenScope: ITokenScope,
) {
return await this.service.updateWorkflowRuntimeLanguage(language, tokenScope);
return await this.collectionFlowService.updateWorkflowRuntimeLanguage(language, tokenScope);
}

@common.Put('/sync')
async syncWorkflow(@common.Body() payload: UpdateFlowDto, @TokenScope() tokenScope: ITokenScope) {
return await this.service.syncWorkflow(payload, tokenScope);
return await this.collectionFlowService.syncWorkflow(payload, tokenScope);
}

@common.Patch('/sync/context')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { CollectionFlowService } from '@/collection-flow/collection-flow.service';
import { TokenScope, type ITokenScope } from '@/common/decorators/token-scope.decorator';
import {
TokenScope,
type ITokenScopeWithEndUserId,
} from '@/common/decorators/token-scope.decorator';
import { UseTokenAuthGuard } from '@/common/guards/token-guard/use-token-auth.decorator';
import { EndUserUpdateDto } from '@/end-user/dtos/end-user-update';
import { EndUserModel } from '@/end-user/end-user.model';
Expand All @@ -19,7 +22,10 @@ export class CollectionFlowEndUserController {

@common.Post()
@swagger.ApiCreatedResponse({ type: [EndUserModel] })
getCompanyInfo(@TokenScope() tokenScope: ITokenScope, @common.Body() data: EndUserUpdateDto) {
getCompanyInfo(
@TokenScope() tokenScope: ITokenScopeWithEndUserId,
@common.Body() data: EndUserUpdateDto,
) {
return this.endUserService.updateById(tokenScope.endUserId, { data: data });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { StorageService } from '@/storage/storage.service';
import {
Controller,
Get,
Logger,
Param,
ParseFilePipeBuilder,
Post,
Expand All @@ -23,14 +22,10 @@ import { ApiExcludeController } from '@nestjs/swagger';
import type { Response } from 'express';
import * as errors from '../../errors';

export const COLLECTION_FLOW_FILES_API_PATH = 'collection-flow/files';

@UseTokenAuthGuard()
@ApiExcludeController()
@Controller('collection-flow/files')
export class CollectionFlowFilesController {
private readonly logger = new Logger(CollectionFlowFilesController.name);

constructor(
protected readonly storageService: StorageService,
protected readonly collectionFlowService: CollectionFlowService,
Expand Down
Loading

0 comments on commit d01f56b

Please sign in to comment.