diff --git a/migrations/1722907373955-seedNotificationTypeForProjectOwnershipChanged.ts b/migrations/1722907373955-seedNotificationTypeForProjectOwnershipChanged.ts new file mode 100644 index 0000000..c2cdc11 --- /dev/null +++ b/migrations/1722907373955-seedNotificationTypeForProjectOwnershipChanged.ts @@ -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 { + await queryRunner.manager.save(NotificationType, notificationTypes); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DELETE FROM notification_type WHERE "name" IN + (${NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_TO}, + ${NOTIFICATION_TYPE_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM});`, + ); + } +} diff --git a/src/entities/notificationType.ts b/src/entities/notificationType.ts index a26fad5..55f69f9 100644 --- a/src/entities/notificationType.ts +++ b/src/entities/notificationType.ts @@ -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 }[]; diff --git a/src/routes/v1/notificationRouter.test.ts b/src/routes/v1/notificationRouter.test.ts index 6f6fa7a..5aab98f 100644 --- a/src/routes/v1/notificationRouter.test.ts +++ b/src/routes/v1/notificationRouter.test.ts @@ -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: 'aliebrahimi2079@gmail.com', + 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: 'aliebrahimi2079@gmail.com', + 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: 'aliebrahimi2079@gmail.com', + 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: 'aliebrahimi2079@gmail.com', + 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() { diff --git a/src/services/notificationService.test.ts b/src/services/notificationService.test.ts index 01c0f75..ec23aad 100644 --- a/src/services/notificationService.test.ts +++ b/src/services/notificationService.test.ts @@ -50,4 +50,62 @@ describe('activityCreator', () => { }), ); }); + + it('should create attributes for PROJECT_OWNER_CHANGED_TO', () => { + const payload = { + email: 'test@example.com', + 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: 'test@example.com', + 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'], + }), + ); + }); }); diff --git a/src/services/notificationService.ts b/src/services/notificationService.ts index 1ed4a0f..0780213 100644 --- a/src/services/notificationService.ts +++ b/src/services/notificationService.ts @@ -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; diff --git a/src/types/general.ts b/src/types/general.ts index c0e3059..3d6781c 100644 --- a/src/types/general.ts +++ b/src/types/general.ts @@ -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', } diff --git a/src/types/notifications.ts b/src/types/notifications.ts index 68d1d35..e44c964 100644 --- a/src/types/notifications.ts +++ b/src/types/notifications.ts @@ -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 = { @@ -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', }; diff --git a/src/utils/validators/segmentAndMetadataValidators.ts b/src/utils/validators/segmentAndMetadataValidators.ts index 915d5bf..eeb7b44 100644 --- a/src/utils/validators/segmentAndMetadataValidators.ts +++ b/src/utils/validators/segmentAndMetadataValidators.ts @@ -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; @@ -352,4 +359,8 @@ export const SEGMENT_METADATA_SCHEMA_VALIDATOR: { metadata: null, segment: notifyRewardAmountSegmentSchema, }, + ProjectOwnershipChanged: { + metadata: null, + segment: projectOwnershipChangedSegmentSchema, + }, }; diff --git a/src/validators/schemaValidators.ts b/src/validators/schemaValidators.ts index ccd99ff..484b818 100644 --- a/src/validators/schemaValidators.ts +++ b/src/validators/schemaValidators.ts @@ -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(), }), }), });