Skip to content

Commit

Permalink
Merge branch 'next' into add-workflow-actions-section
Browse files Browse the repository at this point in the history
  • Loading branch information
scopsy authored Jan 23, 2025
2 parents f4a0a62 + 6fea706 commit 77b4ac1
Show file tree
Hide file tree
Showing 172 changed files with 4,796 additions and 2,556 deletions.
5 changes: 3 additions & 2 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,8 @@
"navigatable",
"facated",
"dotenvcreate",
"querybuilder"
"querybuilder",
"liquified"
],
"flagWords": [],
"patterns": [
Expand Down Expand Up @@ -827,7 +828,7 @@
"tsconfig.json",
"unreadRead",
"websockets",
"apps/dashboard/src/components/header-navigation/customer-support-button.tsx",
"apps/dashboard/src/hooks/use-plain-chat.ts",
"apps/dashboard/src/components/primitives/control-input/variable-popover/constants.ts"
]
}
1 change: 1 addition & 0 deletions .github/workflows/prepare-self-hosted-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ jobs:
--platform=linux/amd64,linux/arm64 --provenance=false
--output=type=image,name=ghcr.io/${{ env.REGISTRY_OWNER }}/${{ env.SERVICE_NAME }},push-by-digest=true,name-canonical=true
run: |
cp scripts/dotenvcreate.mjs apps/$SERVICE_COMMON_NAME/src/dotenvcreate.mjs
cd apps/$SERVICE_COMMON_NAME
if [ "${{ env.SERVICE_NAME }}" == "worker" ]; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-api-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
# This workflow contains a single job called "build"
e2e_api:
name: Test E2E
runs-on: ubuntu-latest
runs-on: blacksmith-2vcpu-ubuntu-2204
timeout-minutes: 80
permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .source
6 changes: 2 additions & 4 deletions apps/api/src/app/bridge/bridge.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import { SharedModule } from '../shared/shared.module';
import { BridgeController } from './bridge.controller';
import { USECASES } from './usecases';
import { BuildVariableSchemaUsecase } from '../workflows-v2/usecases/build-variable-schema';
import { HydrateEmailSchemaUseCase } from '../environments-v1/usecases/output-renderers/hydrate-email-schema.usecase';
import { BuildPayloadSchema } from '../workflows-v2/usecases/build-payload-schema/build-payload-schema.usecase';
import { ExtractVariables } from '../workflows-v2/usecases/extract-variables/extract-variables.usecase';
import { BuildStepIssuesUsecase } from '../workflows-v2/usecases/build-step-issues/build-step-issues.usecase';

const PROVIDERS = [
Expand All @@ -42,9 +41,8 @@ const PROVIDERS = [
UpsertControlValuesUseCase,
BuildVariableSchemaUsecase,
TierRestrictionsValidateUsecase,
HydrateEmailSchemaUseCase,
CommunityOrganizationRepository,
BuildPayloadSchema,
ExtractVariables,
BuildStepIssuesUsecase,
];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsDefined, IsMongoId, IsOptional, IsString } from 'class-validator';
import { IsDefined, IsHexColor, IsMongoId, IsOptional, IsString } from 'class-validator';

export class CreateEnvironmentRequestDto {
@ApiProperty()
Expand All @@ -11,4 +11,9 @@ export class CreateEnvironmentRequestDto {
@IsOptional()
@IsMongoId()
parentId?: string;

@ApiProperty()
@IsDefined()
@IsHexColor()
color: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsMongoId, IsOptional, IsString } from 'class-validator';
import { IsHexColor, IsMongoId, IsOptional, IsString } from 'class-validator';

export class InBoundParseDomainDto {
@ApiPropertyOptional({ type: String })
Expand Down Expand Up @@ -27,6 +27,11 @@ export class UpdateEnvironmentRequestDto {
@IsMongoId()
parentId?: string;

@ApiPropertyOptional()
@IsOptional()
@IsHexColor()
color?: string;

@ApiPropertyOptional({
type: InBoundParseDomainDto,
})
Expand Down
7 changes: 1 addition & 6 deletions apps/api/src/app/environments-v1/e2e/get-api-keys.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NOVU_ENCRYPTION_SUB_MASK } from '@novu/shared';
import { UserSession } from '@novu/testing';
import { expect } from 'chai';
import { NOVU_ENCRYPTION_SUB_MASK } from '@novu/shared';

describe('Get Environment API Keys - /environments/api-keys (GET) #novu-v2', async () => {
let session: UserSession;
Expand All @@ -10,11 +10,6 @@ describe('Get Environment API Keys - /environments/api-keys (GET) #novu-v2', asy
});

it('should get environment api keys correctly', async () => {
const demoEnvironment = {
name: 'Hello App',
};
await session.testAgent.post('/v1/environments').send(demoEnvironment).expect(201);

const { body } = await session.testAgent.get('/v1/environments/api-keys').send();

expect(body.data[0].key).to.not.contains(NOVU_ENCRYPTION_SUB_MASK);
Expand Down
55 changes: 42 additions & 13 deletions apps/api/src/app/environments-v1/environments-v1.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,39 @@ import {
Body,
ClassSerializerInterceptor,
Controller,
Delete,
Get,
Param,
Post,
Put,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { ApiAuthSchemeEnum, MemberRoleEnum, UserSessionData } from '@novu/shared';
import { ApiExcludeController, ApiExcludeEndpoint, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiExcludeController, ApiExcludeEndpoint, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
import { Roles, RolesGuard } from '@novu/application-generic';
import { ApiAuthSchemeEnum, MemberRoleEnum, ProductFeatureKeyEnum, UserSessionData } from '@novu/shared';
import { ExternalApiAccessible } from '../auth/framework/external-api.decorator';
import { ProductFeature } from '../shared/decorators/product-feature.decorator';
import { ApiKey } from '../shared/dtos/api-key';
import { ApiCommonResponses, ApiResponse } from '../shared/framework/response.decorator';
import { UserAuthentication } from '../shared/framework/swagger/api.key.security';
import { SdkGroupName } from '../shared/framework/swagger/sdk.decorators';
import { UserSession } from '../shared/framework/user.decorator';
import { CreateEnvironment } from './usecases/create-environment/create-environment.usecase';
import { CreateEnvironmentCommand } from './usecases/create-environment/create-environment.command';
import { CreateEnvironmentRequestDto } from './dtos/create-environment-request.dto';
import { EnvironmentResponseDto } from './dtos/environment-response.dto';
import { UpdateEnvironmentRequestDto } from './dtos/update-environment-request.dto';
import { CreateEnvironmentCommand } from './usecases/create-environment/create-environment.command';
import { CreateEnvironment } from './usecases/create-environment/create-environment.usecase';
import { DeleteEnvironmentCommand } from './usecases/delete-environment/delete-environment.command';
import { DeleteEnvironment } from './usecases/delete-environment/delete-environment.usecase';
import { GetApiKeysCommand } from './usecases/get-api-keys/get-api-keys.command';
import { GetApiKeys } from './usecases/get-api-keys/get-api-keys.usecase';
import { GetEnvironment, GetEnvironmentCommand } from './usecases/get-environment';
import { GetMyEnvironments } from './usecases/get-my-environments/get-my-environments.usecase';
import { GetMyEnvironmentsCommand } from './usecases/get-my-environments/get-my-environments.command';
import { ApiKey } from '../shared/dtos/api-key';
import { EnvironmentResponseDto } from './dtos/environment-response.dto';
import { ExternalApiAccessible } from '../auth/framework/external-api.decorator';
import { GetMyEnvironments } from './usecases/get-my-environments/get-my-environments.usecase';
import { RegenerateApiKeys } from './usecases/regenerate-api-keys/regenerate-api-keys.usecase';
import { UpdateEnvironmentCommand } from './usecases/update-environment/update-environment.command';
import { UpdateEnvironment } from './usecases/update-environment/update-environment.usecase';
import { UpdateEnvironmentRequestDto } from './dtos/update-environment-request.dto';
import { ApiCommonResponses, ApiResponse } from '../shared/framework/response.decorator';
import { UserAuthentication } from '../shared/framework/swagger/api.key.security';
import { SdkGroupName } from '../shared/framework/swagger/sdk.decorators';

/**
* @deprecated use EnvironmentsControllerV2
Expand All @@ -48,7 +52,8 @@ export class EnvironmentsControllerV1 {
private getApiKeysUsecase: GetApiKeys,
private regenerateApiKeysUsecase: RegenerateApiKeys,
private getEnvironmentUsecase: GetEnvironment,
private getMyEnvironmentsUsecase: GetMyEnvironments
private getMyEnvironmentsUsecase: GetMyEnvironments,
private deleteEnvironmentUsecase: DeleteEnvironment
) {}

@Get('/me')
Expand All @@ -73,6 +78,9 @@ export class EnvironmentsControllerV1 {
})
@ApiExcludeEndpoint()
@ApiResponse(EnvironmentResponseDto, 201)
@ProductFeature(ProductFeatureKeyEnum.MANAGE_ENVIRONMENTS)
@UseGuards(RolesGuard)
@Roles(MemberRoleEnum.ADMIN)
async createEnvironment(
@UserSession() user: UserSessionData,
@Body() body: CreateEnvironmentRequestDto
Expand All @@ -82,6 +90,8 @@ export class EnvironmentsControllerV1 {
name: body.name,
userId: user._id,
organizationId: user.organizationId,
color: body.color,
system: false,
})
);
}
Expand Down Expand Up @@ -121,6 +131,7 @@ export class EnvironmentsControllerV1 {
name: payload.name,
identifier: payload.identifier,
_parentId: payload.parentId,
color: payload.color,
dns: payload.dns,
bridge: payload.bridge,
})
Expand Down Expand Up @@ -157,4 +168,22 @@ export class EnvironmentsControllerV1 {

return await this.regenerateApiKeysUsecase.execute(command);
}

@Delete('/:environmentId')
@ApiOperation({
summary: 'Delete environment',
})
@ApiParam({ name: 'environmentId', type: String, required: true })
@ProductFeature(ProductFeatureKeyEnum.MANAGE_ENVIRONMENTS)
@UseGuards(RolesGuard)
@Roles(MemberRoleEnum.ADMIN)
async deleteEnvironment(@UserSession() user: UserSessionData, @Param('environmentId') environmentId: string) {
return await this.deleteEnvironmentUsecase.execute(
DeleteEnvironmentCommand.create({
userId: user._id,
organizationId: user.organizationId,
environmentId,
})
);
}
}
10 changes: 6 additions & 4 deletions apps/api/src/app/environments-v1/environments-v1.module.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { forwardRef, Module } from '@nestjs/common';

import { SharedModule } from '../shared/shared.module';
import { USE_CASES } from './usecases';
import { EnvironmentsControllerV1 } from './environments-v1.controller';
import { NotificationGroupsModule } from '../notification-groups/notification-groups.module';
import { AuthModule } from '../auth/auth.module';
import { IntegrationModule } from '../integrations/integrations.module';
import { LayoutsModule } from '../layouts/layouts.module';
import { NotificationGroupsModule } from '../notification-groups/notification-groups.module';
import { SharedModule } from '../shared/shared.module';
import { EnvironmentsControllerV1 } from './environments-v1.controller';
import { NovuBridgeModule } from './novu-bridge.module';
import { USE_CASES } from './usecases';

@Module({
imports: [
SharedModule,
NotificationGroupsModule,
forwardRef(() => AuthModule),
forwardRef(() => LayoutsModule),
forwardRef(() => IntegrationModule),
NovuBridgeModule,
],
controllers: [EnvironmentsControllerV1],
Expand Down
6 changes: 2 additions & 4 deletions apps/api/src/app/environments-v1/novu-bridge.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import { ConstructFrameworkWorkflow } from './usecases/construct-framework-workf
import { NovuBridgeController } from './novu-bridge.controller';
import {
ChatOutputRendererUsecase,
ExpandEmailEditorSchemaUsecase,
HydrateEmailSchemaUseCase,
InAppOutputRendererUsecase,
PushOutputRendererUsecase,
EmailOutputRendererUsecase,
SmsOutputRendererUsecase,
} from './usecases/output-renderers';
import { DelayOutputRendererUsecase } from './usecases/output-renderers/delay-output-renderer.usecase';
import { DigestOutputRendererUsecase } from './usecases/output-renderers/digest-output-renderer.usecase';
import { WrapMailyInLiquidUseCase } from './usecases/output-renderers/maily-to-liquid/wrap-maily-in-liquid.usecase';

@Module({
controllers: [NovuBridgeController],
Expand All @@ -36,8 +35,7 @@ import { DigestOutputRendererUsecase } from './usecases/output-renderers/digest-
ChatOutputRendererUsecase,
PushOutputRendererUsecase,
EmailOutputRendererUsecase,
ExpandEmailEditorSchemaUsecase,
HydrateEmailSchemaUseCase,
WrapMailyInLiquidUseCase,
DelayOutputRendererUsecase,
DigestOutputRendererUsecase,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,10 @@ export class ConstructFrameworkWorkflow {
return foundWorkflow;
}

private processSkipOption(controlValues: { [x: string]: unknown }, variables: FullPayloadForRender) {
private async processSkipOption(
controlValues: { [x: string]: unknown },
variables: FullPayloadForRender
): Promise<boolean> {
const skipRules = controlValues.skip as RulesLogic<AdditionalOperation>;

if (_.isEmpty(skipRules)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IsDefined, IsMongoId, IsOptional, IsString } from 'class-validator';
import { IsBoolean, IsDefined, IsHexColor, IsMongoId, IsOptional, IsString } from 'class-validator';
import { OrganizationCommand } from '../../../shared/commands/organization.command';

export class CreateEnvironmentCommand extends OrganizationCommand {
Expand All @@ -9,4 +9,12 @@ export class CreateEnvironmentCommand extends OrganizationCommand {
@IsOptional()
@IsMongoId()
parentEnvironmentId?: string;

@IsOptional()
@IsHexColor()
color?: string;

@IsBoolean()
@IsDefined()
system: boolean;
}
Loading

0 comments on commit 77b4ac1

Please sign in to comment.