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

add project ownership changed email #116

Open
wants to merge 4 commits into
base: staging
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import {
NOTIFICATION_CATEGORY,
NOTIFICATION_TYPE_NAMES,
} from '../src/types/general';
import { MICRO_SERVICES } from '../src/utils/utils';
import {
NotificationType,
SCHEMA_VALIDATORS_NAMES,
} from '../src/entities/notificationType';

const notificationTypes = [
{
name: NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_TO,
description: NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_TO,
microService: MICRO_SERVICES.givethio,
category: NOTIFICATION_CATEGORY.ORTTO,
schemaValidator: SCHEMA_VALIDATORS_NAMES.PROJECT_OWNERSHIP_CHANGED,
title: 'Notify Project Owner Changed To',
},
{
name: NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM,
description: NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM,
microService: MICRO_SERVICES.givethio,
category: NOTIFICATION_CATEGORY.ORTTO,
schemaValidator: SCHEMA_VALIDATORS_NAMES.PROJECT_OWNERSHIP_CHANGED,
title: 'Notify Project Owner Changed From',
},
];

export class SeedNotificationTypeForProjectOwnershipChanged1722907373955
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.manager.save(NotificationType, notificationTypes);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`DELETE FROM notification_type WHERE "name" IN
(${NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_TO},
${NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM});`,
);
}
}
1 change: 1 addition & 0 deletions src/entities/notificationType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const SCHEMA_VALIDATORS_NAMES = {
YOUR_PROJECT_GOT_A_RANK: 'yourProjectGotARank',

NOTIFY_REWARD_AMOUNT: 'notifyRewardAmount',
PROJECT_OWNERSHIP_CHANGED: 'ProjectOwnershipChanged',
};
export type HtmlTemplate = { type: string; content: string; href?: string }[];

Expand Down
124 changes: 124 additions & 0 deletions src/routes/v1/notificationRouter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,130 @@ function sendNotificationTestCases() {
);
}
});

it('should create *Project Ownership Changed To* notification, success', async () => {
const data = {
eventName: 'Project ownership changed to',
sendEmail: true,
sendSegment: true,
creationTime: 1667992708000,
segment: {
payload: {
email: '[email protected]',
userId: 1234,
ownerName: 'Ali',
projectName: 'Test Project',
},
},
};

const result = await axios.post(sendNotificationUrl, data, {
headers: {
authorization: getGivethIoBasicAuth(),
},
});

assert.equal(result.status, 200);
assert.isOk(result.data);
assert.isTrue(result.data.success);
});
it('should create *Project Ownership Changed To* notification, failed invalid payload', async () => {
try {
const data = {
eventName: 'Project ownership changed to',
sendEmail: true,
sendSegment: true,
creationTime: 1667992708000,
segment: {
payload: {
email: '[email protected]',
userId: 1234,
ownerName: 'Ali',
projectName: 'Test Project',
invalidField: 'invalid data',
},
},
};
await axios.post(sendNotificationUrl, data, {
headers: {
authorization: getGivethIoBasicAuth(),
},
});
// If request doesn't fail, it means this test failed
assert.isTrue(false);
} catch (e: any) {
assert.equal(
e.response.data.message,
errorMessagesEnum.IMPACT_GRAPH_VALIDATION_ERROR.message,
);
assert.equal(
e.response.data.description,
'"segment.payload.invalidField" is not allowed',
);
}
});

it('should create *Project Ownership Changed From* notification, success', async () => {
const data = {
eventName: 'Project ownership changed from',
sendEmail: true,
sendSegment: true,
creationTime: 1667992708000,
segment: {
payload: {
email: '[email protected]',
userId: 1234,
ownerName: 'Ali',
projectName: 'Test Project',
},
},
};

const result = await axios.post(sendNotificationUrl, data, {
headers: {
authorization: getGivethIoBasicAuth(),
},
});

assert.equal(result.status, 200);
assert.isOk(result.data);
assert.isTrue(result.data.success);
});
it('should create *Project Ownership Changed From* notification, failed invalid payload', async () => {
try {
const data = {
eventName: 'Project ownership changed from',
sendEmail: true,
sendSegment: true,
creationTime: 1667992708000,
segment: {
payload: {
email: '[email protected]',
ownerName: 'Ali',
userId: 1234,
projectName: 'Test Project',
invalidField: 'invalid data',
},
},
};
await axios.post(sendNotificationUrl, data, {
headers: {
authorization: getGivethIoBasicAuth(),
},
});
// If request doesn't fail, it means this test failed
assert.isTrue(false);
} catch (e: any) {
assert.equal(
e.response.data.message,
errorMessagesEnum.IMPACT_GRAPH_VALIDATION_ERROR.message,
);
assert.equal(
e.response.data.description,
'"segment.payload.invalidField" is not allowed',
);
}
});
}

function sendBulkNotificationsTestCases() {
Expand Down
58 changes: 58 additions & 0 deletions src/services/notificationService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,62 @@ describe('activityCreator', () => {
}),
);
});

it('should create attributes for PROJECT_OWNER_CHANGED_TO', () => {
const payload = {
email: '[email protected]',
ownerName: 'Test Owner',
projectName: 'Test Project',
};
const result = activityCreator(
payload,
NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO,
);
expect(JSON.stringify(result)).equal(
JSON.stringify({
activities: [
{
activity_id: 'act:cm:ownership-changed-to',
attributes: {
'str:cm:ownername': payload.ownerName,
'str:cm:projectname': payload.projectName,
},
fields: {
'str::email': payload.email,
},
},
],
merge_by: ['str::email'],
}),
);
});

it('should create attributes for PROJECT_OWNER_CHANGED_FROM', () => {
const payload = {
email: '[email protected]',
ownerName: 'Test Owner',
projectName: 'Test Project',
};
const result = activityCreator(
payload,
NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM,
);
expect(JSON.stringify(result)).equal(
JSON.stringify({
activities: [
{
activity_id: 'act:cm:ownership-changed-from',
attributes: {
'str:cm:ownername': payload.ownerName,
'str:cm:projectname': payload.projectName,
},
fields: {
'str::email': payload.email,
},
},
],
merge_by: ['str::email'],
}),
);
});
});
12 changes: 12 additions & 0 deletions src/services/notificationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@ export const activityCreator = (
'str:cm:transactionhash': payload.transactionHash,
};
break;
case NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO:
attributes = {
'str:cm:ownername': payload.ownerName,
'str:cm:projectname': payload.projectName,
};
break;
case NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM:
attributes = {
'str:cm:ownername': payload.ownerName,
'str:cm:projectname': payload.projectName,
};
break;
default:
logger.debug('activityCreator() invalid event name', orttoEventName);
return;
Expand Down
2 changes: 2 additions & 0 deletions src/types/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ export enum NOTIFICATION_TYPE_NAMES {
CREATE_ORTTO_PROFILE = 'Create Ortto profile',

NOTIFY_REWARD_AMOUNT = 'Notify reward amount',
PROJECT_OWNERSHIP_CHANGED_TO = 'Project ownership changed to',
PROJECT_OWNERSHIP_CHANGED_FROM = 'Project ownership changed from',
}
6 changes: 6 additions & 0 deletions src/types/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export enum NOTIFICATIONS_EVENT_NAMES {
SEND_EMAIL_CONFIRMATION = 'Send email confirmation',
SUBSCRIBE_ONBOARDING = 'Subscribe onboarding',
NOTIFY_REWARD_AMOUNT = 'Notify reward amount',
PROJECT_OWNERSHIP_CHANGED_TO = 'Project ownership changed to',
PROJECT_OWNERSHIP_CHANGED_FROM = 'Project ownership changed from',
}

export const ORTTO_EVENT_NAMES = {
Expand Down Expand Up @@ -81,4 +83,8 @@ export const ORTTO_EVENT_NAMES = {
'verification-form-email-verification',
[NOTIFICATIONS_EVENT_NAMES.NOTIFY_REWARD_AMOUNT]: 'notify-reward',
[NOTIFICATIONS_EVENT_NAMES.SUBSCRIBE_ONBOARDING]: 'onboarding-form',
[NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO]:
'ownership-changed-to',
[NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM]:
'ownership-changed-from',
};
11 changes: 11 additions & 0 deletions src/utils/validators/segmentAndMetadataValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ const notifyRewardAmountSegmentSchema = Joi.object({
email: Joi.string().required(),
});

const projectOwnershipChangedSegmentSchema = Joi.object({
email: Joi.string().required(),
userId: Joi.number().required(),
ownerName: Joi.string().required(),
projectName: Joi.string().required(),
});

export const SEGMENT_METADATA_SCHEMA_VALIDATOR: {
[key: string]: {
segment: ObjectSchema | null;
Expand Down Expand Up @@ -352,4 +359,8 @@ export const SEGMENT_METADATA_SCHEMA_VALIDATOR: {
metadata: null,
segment: notifyRewardAmountSegmentSchema,
},
ProjectOwnershipChanged: {
metadata: null,
segment: projectOwnershipChangedSegmentSchema,
},
};
4 changes: 4 additions & 0 deletions src/validators/schemaValidators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ export const sendNotificationValidator = Joi.object({
network: Joi.string(),
script: Joi.string(),
transactionHash: Joi.string(),

// Project ownership change attributes
ownerName: Joi.string(),
projectName: Joi.string(),
}),
}),
});
Expand Down
Loading