Skip to content

Commit d7c0a3a

Browse files
committed
Merge branch 'topics-page' of https://github.com/novuhq/novu into topics-page
2 parents 1e77b9c + b236711 commit d7c0a3a

File tree

14 files changed

+123
-99
lines changed

14 files changed

+123
-99
lines changed

apps/api/src/app/environments-v1/usecases/create-environment/create-environment.usecase.ts

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export class CreateEnvironment {
108108
environmentId: environment._id,
109109
organizationId: environment._organizationId,
110110
userId: command.userId,
111+
name: environment.name,
111112
})
112113
);
113114

apps/api/src/app/events/events.module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { TerminusModule } from '@nestjs/terminus';
33

44
import { GetNovuProviderCredentials, StorageHelperService } from '@novu/application-generic';
55

6-
import { CommunityOrganizationRepository } from '@novu/dal';
6+
import { CommunityOrganizationRepository, CommunityUserRepository } from '@novu/dal';
77
import { EventsController } from './events.controller';
88
import { USE_CASES } from './usecases';
99

@@ -35,6 +35,6 @@ const PROVIDERS = [GetNovuProviderCredentials, StorageHelperService, CommunityOr
3535
BridgeModule,
3636
],
3737
controllers: [EventsController],
38-
providers: [...PROVIDERS, ...USE_CASES],
38+
providers: [...PROVIDERS, ...USE_CASES, CommunityUserRepository],
3939
})
4040
export class EventsModule {}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { EnvironmentEnum } from '@novu/shared';
12
import { EnvironmentWithUserCommand } from '../../../shared/commands/project.command';
23

3-
export class CreateNovuIntegrationsCommand extends EnvironmentWithUserCommand {}
4+
export class CreateNovuIntegrationsCommand extends EnvironmentWithUserCommand {
5+
name: string | EnvironmentEnum;
6+
}

apps/api/src/app/integrations/usecases/create-novu-integrations/create-novu-integrations.usecase.ts

+6-43
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { Injectable } from '@nestjs/common';
2+
import { areNovuEmailCredentialsSet, FeatureFlagsService } from '@novu/application-generic';
23
import { EnvironmentEntity, IntegrationRepository, OrganizationEntity, UserEntity } from '@novu/dal';
3-
import { areNovuEmailCredentialsSet, areNovuSmsCredentialsSet, FeatureFlagsService } from '@novu/application-generic';
44

55
import {
66
ChannelTypeEnum,
77
EmailProviderIdEnum,
8+
EnvironmentEnum,
89
FeatureFlagsKeysEnum,
910
InAppProviderIdEnum,
10-
SmsProviderIdEnum,
1111
} from '@novu/shared';
12-
import { CreateNovuIntegrationsCommand } from './create-novu-integrations.command';
13-
import { CreateIntegration } from '../create-integration/create-integration.usecase';
1412
import { CreateIntegrationCommand } from '../create-integration/create-integration.command';
15-
import { SetIntegrationAsPrimary } from '../set-integration-as-primary/set-integration-as-primary.usecase';
13+
import { CreateIntegration } from '../create-integration/create-integration.usecase';
1614
import { SetIntegrationAsPrimaryCommand } from '../set-integration-as-primary/set-integration-as-primary.command';
15+
import { SetIntegrationAsPrimary } from '../set-integration-as-primary/set-integration-as-primary.usecase';
16+
import { CreateNovuIntegrationsCommand } from './create-novu-integrations.command';
1717

1818
@Injectable()
1919
export class CreateNovuIntegrations {
@@ -25,7 +25,7 @@ export class CreateNovuIntegrations {
2525
) {}
2626

2727
private async createEmailIntegration(command: CreateNovuIntegrationsCommand) {
28-
if (!areNovuEmailCredentialsSet()) {
28+
if (!areNovuEmailCredentialsSet() || command.name !== EnvironmentEnum.DEVELOPMENT) {
2929
return;
3030
}
3131

@@ -60,42 +60,6 @@ export class CreateNovuIntegrations {
6060
}
6161
}
6262

63-
private async createSmsIntegration(command: CreateNovuIntegrationsCommand) {
64-
if (!areNovuSmsCredentialsSet()) {
65-
return;
66-
}
67-
68-
const smsIntegrationCount = await this.integrationRepository.count({
69-
providerId: SmsProviderIdEnum.Novu,
70-
channel: ChannelTypeEnum.SMS,
71-
_organizationId: command.organizationId,
72-
_environmentId: command.environmentId,
73-
});
74-
75-
if (smsIntegrationCount === 0) {
76-
const novuSmsIntegration = await this.createIntegration.execute(
77-
CreateIntegrationCommand.create({
78-
providerId: SmsProviderIdEnum.Novu,
79-
channel: ChannelTypeEnum.SMS,
80-
name: 'Novu SMS',
81-
active: true,
82-
check: false,
83-
userId: command.userId,
84-
environmentId: command.environmentId,
85-
organizationId: command.organizationId,
86-
})
87-
);
88-
await this.setIntegrationAsPrimary.execute(
89-
SetIntegrationAsPrimaryCommand.create({
90-
organizationId: command.organizationId,
91-
environmentId: command.environmentId,
92-
integrationId: novuSmsIntegration._id,
93-
userId: command.userId,
94-
})
95-
);
96-
}
97-
}
98-
9963
private async createInAppIntegration(command: CreateNovuIntegrationsCommand) {
10064
const inAppIntegrationCount = await this.integrationRepository.count({
10165
providerId: InAppProviderIdEnum.Novu,
@@ -131,7 +95,6 @@ export class CreateNovuIntegrations {
13195

13296
async execute(command: CreateNovuIntegrationsCommand): Promise<void> {
13397
await this.createEmailIntegration(command);
134-
await this.createSmsIntegration(command);
13598
await this.createInAppIntegration(command);
13699
}
137100
}

apps/api/src/app/organization/usecases/create-organization/sync-external-organization/sync-external-organization.usecase.ts

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export class SyncExternalOrganization {
6060
environmentId: devEnv._id,
6161
organizationId: devEnv._organizationId,
6262
userId: user._id,
63+
name: devEnv.name,
6364
})
6465
);
6566

@@ -78,6 +79,7 @@ export class SyncExternalOrganization {
7879
environmentId: prodEnv._id,
7980
organizationId: prodEnv._organizationId,
8081
userId: user._id,
82+
name: prodEnv.name,
8183
})
8284
);
8385

apps/dashboard/src/components/integrations/components/integration-configuration.tsx

+9-3
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,15 @@ export function IntegrationConfiguration({
143143
<InlineToast
144144
variant={'warning'}
145145
title="Demo Integration"
146-
description={`This is a demo integration intended for testing purposes only. It is limited to 300 ${
147-
provider?.channel === 'email' ? 'emails' : 'sms'
148-
} per month.`}
146+
description={`This is a demo ${
147+
provider?.channel === 'email' ? 'email' : 'SMS'
148+
} integration intended for testing purposes only. It is limited to 300 ${
149+
provider?.channel === 'email' ? 'messages' : 'SMS'
150+
} per month.${
151+
provider?.channel === 'email'
152+
? ' You can only send emails from it to the email address you are logged in with.'
153+
: ''
154+
}`}
149155
/>
150156
</div>
151157
) : (

apps/worker/src/app/workflow/usecases/send-message/send-message-email.usecase.ts

+32-26
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
11
import { Injectable, Logger } from '@nestjs/common';
22
import { ModuleRef } from '@nestjs/core';
3-
import inlineCss from 'inline-css';
43
import { addBreadcrumb } from '@sentry/node';
4+
import inlineCss from 'inline-css';
55

66
import {
7-
MessageRepository,
8-
SubscriberRepository,
7+
CompileEmailTemplate,
8+
CompileEmailTemplateCommand,
9+
CreateExecutionDetails,
10+
CreateExecutionDetailsCommand,
11+
DetailEnum,
12+
FeatureFlagsService,
13+
GetNovuProviderCredentials,
14+
InstrumentUsecase,
15+
MailFactory,
16+
SelectIntegration,
17+
SelectVariant,
18+
} from '@novu/application-generic';
19+
import {
20+
EnvironmentEntity,
921
EnvironmentRepository,
1022
IntegrationEntity,
11-
MessageEntity,
1223
LayoutRepository,
13-
EnvironmentEntity,
24+
MessageEntity,
25+
MessageRepository,
1426
OrganizationEntity,
27+
SubscriberRepository,
1528
UserEntity,
1629
} from '@novu/dal';
30+
import { EmailOutput } from '@novu/framework/internal';
1731
import {
1832
ChannelTypeEnum,
1933
EmailProviderIdEnum,
2034
ExecutionDetailsSourceEnum,
2135
ExecutionDetailsStatusEnum,
36+
FeatureFlagsKeysEnum,
2237
IAttachmentOptions,
2338
IEmailOptions,
24-
FeatureFlagsKeysEnum,
2539
} from '@novu/shared';
26-
import {
27-
InstrumentUsecase,
28-
DetailEnum,
29-
SelectIntegration,
30-
CompileEmailTemplate,
31-
CompileEmailTemplateCommand,
32-
MailFactory,
33-
GetNovuProviderCredentials,
34-
SelectVariant,
35-
CreateExecutionDetails,
36-
CreateExecutionDetailsCommand,
37-
FeatureFlagsService,
38-
} from '@novu/application-generic';
39-
import { EmailOutput } from '@novu/framework/internal';
4040

41-
import { SendMessageCommand } from './send-message.command';
42-
import { SendMessageBase } from './send-message.base';
4341
import { PlatformException } from '../../../shared/utils';
4442
import { SendMessageResult } from './send-message-type.usecase';
43+
import { SendMessageBase } from './send-message.base';
44+
import { SendMessageCommand } from './send-message.command';
4545

4646
const LOG_CONTEXT = 'SendMessageEmail';
4747

@@ -76,6 +76,8 @@ export class SendMessageEmail extends SendMessageBase {
7676
@InstrumentUsecase()
7777
public async execute(command: SendMessageCommand): Promise<SendMessageResult> {
7878
let integration: IntegrationEntity | undefined;
79+
const { subscriber } = command.compileContext;
80+
const email = command.overrides?.email?.toRecipient || subscriber.email;
7981

8082
const overrideSelectedIntegration = command.overrides?.email?.integrationIdentifier;
8183
try {
@@ -84,16 +86,23 @@ export class SendMessageEmail extends SendMessageBase {
8486
environmentId: command.environmentId,
8587
channelType: ChannelTypeEnum.EMAIL,
8688
userId: command.userId,
89+
recipientEmail: email,
8790
identifier: overrideSelectedIntegration as string,
8891
filterData: {
8992
tenant: command.job.tenant,
9093
},
9194
});
9295
} catch (e) {
96+
let detailEnum = DetailEnum.LIMIT_PASSED_NOVU_INTEGRATION;
97+
98+
if (e.message.includes('does not match the current logged-in user')) {
99+
detailEnum = DetailEnum.SUBSCRIBER_NOT_MEMBER_OF_ORGANIZATION;
100+
}
101+
93102
await this.createExecutionDetails.execute(
94103
CreateExecutionDetailsCommand.create({
95104
...CreateExecutionDetailsCommand.getDetailsFromJob(command.job),
96-
detail: DetailEnum.LIMIT_PASSED_NOVU_INTEGRATION,
105+
detail: detailEnum,
97106
source: ExecutionDetailsSourceEnum.INTERNAL,
98107
status: ExecutionDetailsStatusEnum.FAILED,
99108
raw: JSON.stringify({ message: e.message }),
@@ -113,9 +122,6 @@ export class SendMessageEmail extends SendMessageBase {
113122
if (!step) throw new PlatformException('Email channel step not found');
114123
if (!step.template) throw new PlatformException('Email channel template not found');
115124

116-
const { subscriber } = command.compileContext;
117-
const email = command.overrides?.email?.toRecipient || subscriber.email;
118-
119125
addBreadcrumb({
120126
message: 'Sending Email',
121127
});

apps/worker/src/app/workflow/usecases/send-message/send-message.base.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
/* eslint-disable global-require */
2-
import i18next from 'i18next';
3-
import { ModuleRef } from '@nestjs/core';
42
import { Logger } from '@nestjs/common';
5-
import { format } from 'date-fns';
3+
import { ModuleRef } from '@nestjs/core';
64
import {
75
IntegrationEntity,
86
JobEntity,
@@ -19,6 +17,8 @@ import {
1917
ProvidersIdEnum,
2018
SmsProviderIdEnum,
2119
} from '@novu/shared';
20+
import { format } from 'date-fns';
21+
import i18next from 'i18next';
2222

2323
import {
2424
CreateExecutionDetails,
@@ -30,8 +30,8 @@ import {
3030
SelectVariant,
3131
SelectVariantCommand,
3232
} from '@novu/application-generic';
33-
import { SendMessageResult, SendMessageType } from './send-message-type.usecase';
3433
import { PlatformException } from '../../../shared/utils';
34+
import { SendMessageResult, SendMessageType } from './send-message-type.usecase';
3535
import { SendMessageCommand } from './send-message.command';
3636

3737
export abstract class SendMessageBase extends SendMessageType {
@@ -56,6 +56,7 @@ export abstract class SendMessageBase extends SendMessageType {
5656
environmentId: string;
5757
channelType: ChannelTypeEnum;
5858
userId: string;
59+
recipientEmail?: string;
5960
filterData: {
6061
tenant: ITenantDefine | undefined;
6162
};
@@ -73,6 +74,7 @@ export abstract class SendMessageBase extends SendMessageType {
7374
environmentId: integration._environmentId,
7475
organizationId: integration._organizationId,
7576
userId: params.userId,
77+
recipientEmail: params.recipientEmail,
7678
});
7779
}
7880

apps/worker/src/app/workflow/workflow.module.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable global-require */
2-
import { DynamicModule, Logger, Module, OnApplicationShutdown, Provider } from '@nestjs/common';
2+
import { DynamicModule, Logger, Module, OnApplicationShutdown, Provider, Type } from '@nestjs/common';
33
import {
44
BulkCreateExecutionDetails,
55
CalculateLimitNovuIntegration,
@@ -25,9 +25,16 @@ import {
2525
TriggerMulticast,
2626
WorkflowInMemoryProviderService,
2727
} from '@novu/application-generic';
28-
import { CommunityOrganizationRepository, JobRepository, PreferencesRepository } from '@novu/dal';
28+
import {
29+
CommunityMemberRepository,
30+
CommunityOrganizationRepository,
31+
CommunityUserRepository,
32+
JobRepository,
33+
MemberRepository,
34+
PreferencesRepository,
35+
UserRepository,
36+
} from '@novu/dal';
2937

30-
import { Type } from '@nestjs/common/interfaces/type.interface';
3138
import { ForwardReference } from '@nestjs/common/interfaces/modules/forward-reference.interface';
3239
import { JobTopicNameEnum } from '@novu/shared';
3340
import {
@@ -36,6 +43,7 @@ import {
3643
GetDigestEventsBackoff,
3744
GetDigestEventsRegular,
3845
HandleLastFailedJob,
46+
ProcessUnsnoozeJob,
3947
QueueNextJob,
4048
RunJob,
4149
SendMessage,
@@ -48,15 +56,14 @@ import {
4856
SetJobAsCompleted,
4957
SetJobAsFailed,
5058
UpdateJobStatus,
51-
ProcessUnsnoozeJob,
5259
WebhookFilterBackoffStrategy,
5360
} from './usecases';
5461

55-
import { SharedModule } from '../shared/shared.module';
5662
import { ACTIVE_WORKERS, workersToProcess } from '../../config/worker-init.config';
63+
import { SharedModule } from '../shared/shared.module';
64+
import { AddDelayJob, AddJob, MergeOrCreateDigest } from './usecases/add-job';
5765
import { InboundEmailParse } from './usecases/inbound-email-parse/inbound-email-parse.usecase';
5866
import { ExecuteStepCustom } from './usecases/send-message/execute-step-custom.usecase';
59-
import { AddDelayJob, AddJob, MergeOrCreateDigest } from './usecases/add-job';
6067
import { StoreSubscriberJobs } from './usecases/store-subscriber-jobs';
6168
import { SubscriberJobBound } from './usecases/subscriber-job-bound/subscriber-job-bound.usecase';
6269

@@ -82,7 +89,8 @@ const enterpriseImports = (): Array<Type | DynamicModule | Promise<DynamicModule
8289

8390
return modules;
8491
};
85-
const REPOSITORIES = [JobRepository, CommunityOrganizationRepository, PreferencesRepository];
92+
93+
const REPOSITORIES = [JobRepository, CommunityOrganizationRepository, PreferencesRepository, CommunityUserRepository];
8694

8795
const USE_CASES = [
8896
AddDelayJob,

libs/application-generic/src/usecases/create-execution-details/types/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export enum DetailEnum {
2424
TENANT_CONTEXT_SELECTED = 'Tenant context selected',
2525
TENANT_NOT_FOUND = 'Tenant identifier not found',
2626
LIMIT_PASSED_NOVU_INTEGRATION = "Novu's provider limit has been reached",
27+
SUBSCRIBER_NOT_MEMBER_OF_ORGANIZATION = 'Test provider can only be used to send emails to current logged in user',
2728
SUBSCRIBER_NO_CHANNEL_DETAILS = 'Subscriber missing recipient details',
2829
SUBSCRIBER_NO_ACTIVE_CHANNEL = 'Subscriber does not have a configured channel',
2930
MESSAGE_SENT = 'Message sent',

libs/application-generic/src/usecases/get-novu-provider-credentials/get-novu-provider-credentials.command.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { IsEnum, IsString } from 'class-validator';
21
import { ChannelTypeEnum } from '@novu/shared';
2+
import { IsEnum, IsOptional, IsString } from 'class-validator';
33

44
import { EnvironmentWithUserCommand } from '../../commands/project.command';
55

@@ -9,4 +9,8 @@ export class GetNovuProviderCredentialsCommand extends EnvironmentWithUserComman
99

1010
@IsString()
1111
providerId: string;
12+
13+
@IsOptional()
14+
@IsString()
15+
recipientEmail?: string;
1216
}

0 commit comments

Comments
 (0)