From ef551679d0fc6f360baa7fcd4887814fe400f6f2 Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Mon, 5 Aug 2024 05:41:40 +0330 Subject: [PATCH 1/7] add notify ownership change method to the notification center adapter --- .../NotificationAdapterInterface.ts | 9 +++++++ .../NotificationCenterAdapter.ts | 24 +++++++++++++++++++ src/analytics/analytics.ts | 1 + 3 files changed, 34 insertions(+) diff --git a/src/adapters/notifications/NotificationAdapterInterface.ts b/src/adapters/notifications/NotificationAdapterInterface.ts index 7e19aaacb..cd57cd081 100644 --- a/src/adapters/notifications/NotificationAdapterInterface.ts +++ b/src/adapters/notifications/NotificationAdapterInterface.ts @@ -19,6 +19,12 @@ export interface ProjectsHaveNewRankingInputParam { newBottomRank: number; } +export interface ProjectOwnershipChangedParams { + previousOwnerUser: User | null; + newOwnerUser: User | null; + projectName: string; +} + export interface OrttoPerson { fields: { 'str::first': string; @@ -114,4 +120,7 @@ export interface NotificationAdapterInterface { params: BroadCastNotificationInputParams, ): Promise; projectsHaveNewRank(params: ProjectsHaveNewRankingInputParam): Promise; + notifyProjectOwnershipChange( + params: ProjectOwnershipChangedParams, + ): Promise; } diff --git a/src/adapters/notifications/NotificationCenterAdapter.ts b/src/adapters/notifications/NotificationCenterAdapter.ts index 1cc873ba6..d4eb6588f 100644 --- a/src/adapters/notifications/NotificationCenterAdapter.ts +++ b/src/adapters/notifications/NotificationCenterAdapter.ts @@ -4,6 +4,7 @@ import { BroadCastNotificationInputParams, NotificationAdapterInterface, OrttoPerson, + ProjectOwnershipChangedParams, ProjectsHaveNewRankingInputParam, } from './NotificationAdapterInterface'; import { Donation } from '../../entities/donation'; @@ -989,6 +990,29 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { }); } } + + async notifyProjectOwnershipChange( + params: ProjectOwnershipChangedParams, + ): Promise { + try { + const payload = { + previousOwnerEmail: params.previousOwnerUser?.email, + newOwnerEmail: params.newOwnerUser?.email, + projectName: params.projectName, + previousOwnerName: params.previousOwnerUser?.name, + newOwnerName: params.newOwnerUser?.name, + }; + + await callSendNotification({ + eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED, + segment: { + payload, + }, + }); + } catch (e) { + logger.error('notifyProjectOwnershipChange >> error', e); + } + } } const getEmailDataDonationAttributes = async (params: { diff --git a/src/analytics/analytics.ts b/src/analytics/analytics.ts index 44b40ffc4..bec278127 100644 --- a/src/analytics/analytics.ts +++ b/src/analytics/analytics.ts @@ -49,4 +49,5 @@ export enum NOTIFICATIONS_EVENT_NAMES { SUBSCRIBE_ONBOARDING = 'Subscribe onboarding', CREATE_ORTTO_PROFILE = 'Create Ortto profile', SEND_EMAIL_CONFIRMATION = 'Send email confirmation', + PROJECT_OWNERSHIP_CHANGED = 'Project ownership changed', } From 59490d8c3aa8277484627b1245d4342f95afb746 Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Mon, 5 Aug 2024 05:43:33 +0330 Subject: [PATCH 2/7] call notify project ownership change method in projects tab --- src/server/adminJs/tabs/projectsTab.ts | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/server/adminJs/tabs/projectsTab.ts b/src/server/adminJs/tabs/projectsTab.ts index 6a7596a73..1c0ec7f92 100644 --- a/src/server/adminJs/tabs/projectsTab.ts +++ b/src/server/adminJs/tabs/projectsTab.ts @@ -56,6 +56,7 @@ import { User } from '../../../entities/user'; import { refreshProjectEstimatedMatchingView } from '../../../services/projectViewsService'; import { extractAdminJsReferrerUrlParams } from '../adminJs'; import { relateManyProjectsToQfRound } from '../../../repositories/qfRoundRepository2'; +import { NotificationCenterAdapter } from '../../../adapters/notifications/NotificationCenterAdapter'; // add queries depending on which filters were selected export const buildProjectsQuery = ( @@ -658,6 +659,22 @@ export const exportProjectsWithFiltersToCsv = async ( }; } }; + +async function sendOwnershipChangeEmails( + project: Project, + previousOwnerUser: User | null, + newOwnerUser: User | null, +) { + const notificationCenter = new NotificationCenterAdapter(); + + const params = { + previousOwnerUser, + newOwnerUser, + projectName: project.title, + }; + await notificationCenter.notifyProjectOwnershipChange(params); +} + export const projectsTab = { resource: Project, options: { @@ -1082,9 +1099,10 @@ export const projectsTab = { }); if (project) { if (request?.record?.params?.adminChanged) { - const adminUser = await User.findOne({ + const newAdminUser = await User.findOne({ where: { id: request?.record?.params?.newAdminId }, }); + const previousAdminUser = project.adminUser; const previousAdminAddress = project.adminUser?.walletAddress; if (previousAdminAddress) { if (project.adminAddressHistory) { @@ -1093,8 +1111,13 @@ export const projectsTab = { project.adminAddressHistory = [previousAdminAddress]; } } - project.adminUser = adminUser!; + project.adminUser = newAdminUser!; await project.save(); + await sendOwnershipChangeEmails( + project, + previousAdminUser, + newAdminUser, + ); } // Not required for now // Project.notifySegment(project, SegmentEvents.PROJECT_EDITED); From 70f11fdaf0ba21738f6f8f53dcb8152ee57e55df Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Tue, 6 Aug 2024 04:21:59 +0330 Subject: [PATCH 3/7] add notifyProjectOwnershipChange to mock notification adapter --- src/adapters/notifications/MockNotificationAdapter.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/adapters/notifications/MockNotificationAdapter.ts b/src/adapters/notifications/MockNotificationAdapter.ts index e47a3825c..4aaab77c4 100644 --- a/src/adapters/notifications/MockNotificationAdapter.ts +++ b/src/adapters/notifications/MockNotificationAdapter.ts @@ -2,6 +2,7 @@ import { BroadCastNotificationInputParams, NotificationAdapterInterface, OrttoPerson, + ProjectOwnershipChangedParams, ProjectsHaveNewRankingInputParam, } from './NotificationAdapterInterface'; import { Donation } from '../../entities/donation'; @@ -267,4 +268,13 @@ export class MockNotificationAdapter implements NotificationAdapterInterface { }); return Promise.resolve(undefined); } + + notifyProjectOwnershipChange( + params: ProjectOwnershipChangedParams, + ): Promise { + logger.debug('MockNotificationAdapter notifyProjectOwnershipChange', { + params, + }); + return Promise.resolve(undefined); + } } From bd14be529827122fe0803409ea388040d431be77 Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Tue, 6 Aug 2024 07:35:32 +0330 Subject: [PATCH 4/7] separate sending emails to new and old project owner --- .../NotificationCenterAdapter.ts | 25 +++++++++++++------ src/analytics/analytics.ts | 3 ++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/adapters/notifications/NotificationCenterAdapter.ts b/src/adapters/notifications/NotificationCenterAdapter.ts index d4eb6588f..05faa7b00 100644 --- a/src/adapters/notifications/NotificationCenterAdapter.ts +++ b/src/adapters/notifications/NotificationCenterAdapter.ts @@ -995,18 +995,29 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { params: ProjectOwnershipChangedParams, ): Promise { try { - const payload = { - previousOwnerEmail: params.previousOwnerUser?.email, - newOwnerEmail: params.newOwnerUser?.email, + const newOwnerPayload = { + ownerEmail: params.newOwnerUser?.email, + ownerName: params.newOwnerUser?.name, projectName: params.projectName, - previousOwnerName: params.previousOwnerUser?.name, - newOwnerName: params.newOwnerUser?.name, }; await callSendNotification({ - eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED, + eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO, segment: { - payload, + payload: newOwnerPayload, + }, + }); + + const oldOwnerPayload = { + ownerEmail: params.previousOwnerUser?.email, + ownerName: params.previousOwnerUser?.name, + projectName: params.projectName, + }; + + await callSendNotification({ + eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM, + segment: { + payload: oldOwnerPayload, }, }); } catch (e) { diff --git a/src/analytics/analytics.ts b/src/analytics/analytics.ts index bec278127..9f4213aa9 100644 --- a/src/analytics/analytics.ts +++ b/src/analytics/analytics.ts @@ -49,5 +49,6 @@ export enum NOTIFICATIONS_EVENT_NAMES { SUBSCRIBE_ONBOARDING = 'Subscribe onboarding', CREATE_ORTTO_PROFILE = 'Create Ortto profile', SEND_EMAIL_CONFIRMATION = 'Send email confirmation', - PROJECT_OWNERSHIP_CHANGED = 'Project ownership changed', + PROJECT_OWNERSHIP_CHANGED_TO = 'Project ownership changed to', + PROJECT_OWNERSHIP_CHANGED_FROM = 'Project ownership changed from', } From 3a587f621937c776ffdb40ffe959bc4910fd539f Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Tue, 6 Aug 2024 07:55:18 +0330 Subject: [PATCH 5/7] change email field name to be compatible with notification center --- src/adapters/notifications/NotificationCenterAdapter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/notifications/NotificationCenterAdapter.ts b/src/adapters/notifications/NotificationCenterAdapter.ts index 05faa7b00..0a4fe0ffb 100644 --- a/src/adapters/notifications/NotificationCenterAdapter.ts +++ b/src/adapters/notifications/NotificationCenterAdapter.ts @@ -996,7 +996,7 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { ): Promise { try { const newOwnerPayload = { - ownerEmail: params.newOwnerUser?.email, + email: params.newOwnerUser?.email, ownerName: params.newOwnerUser?.name, projectName: params.projectName, }; @@ -1009,7 +1009,7 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { }); const oldOwnerPayload = { - ownerEmail: params.previousOwnerUser?.email, + email: params.previousOwnerUser?.email, ownerName: params.previousOwnerUser?.name, projectName: params.projectName, }; From c06f9041219fdaebb2bddc941331f2285f38b7c1 Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Tue, 6 Aug 2024 07:58:04 +0330 Subject: [PATCH 6/7] add conditions to send notification only when the owner have an email address --- .../NotificationCenterAdapter.ts | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/adapters/notifications/NotificationCenterAdapter.ts b/src/adapters/notifications/NotificationCenterAdapter.ts index 0a4fe0ffb..c0cbd7454 100644 --- a/src/adapters/notifications/NotificationCenterAdapter.ts +++ b/src/adapters/notifications/NotificationCenterAdapter.ts @@ -997,29 +997,33 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { try { const newOwnerPayload = { email: params.newOwnerUser?.email, - ownerName: params.newOwnerUser?.name, + ownerName: params.newOwnerUser?.name || '', projectName: params.projectName, }; - await callSendNotification({ - eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO, - segment: { - payload: newOwnerPayload, - }, - }); + if (newOwnerPayload.email) { + await callSendNotification({ + eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_TO, + segment: { + payload: newOwnerPayload, + }, + }); + } const oldOwnerPayload = { email: params.previousOwnerUser?.email, - ownerName: params.previousOwnerUser?.name, + ownerName: params.previousOwnerUser?.name || '', projectName: params.projectName, }; - await callSendNotification({ - eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM, - segment: { - payload: oldOwnerPayload, - }, - }); + if (oldOwnerPayload.email) { + await callSendNotification({ + eventName: NOTIFICATIONS_EVENT_NAMES.PROJECT_OWNERSHIP_CHANGED_FROM, + segment: { + payload: oldOwnerPayload, + }, + }); + } } catch (e) { logger.error('notifyProjectOwnershipChange >> error', e); } From 5141a5cb50f7001d1bff07dc360c1157c3e092da Mon Sep 17 00:00:00 2001 From: ali ebrahimi Date: Tue, 6 Aug 2024 08:36:18 +0330 Subject: [PATCH 7/7] add userId to project owner changed notification --- src/adapters/notifications/NotificationCenterAdapter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/adapters/notifications/NotificationCenterAdapter.ts b/src/adapters/notifications/NotificationCenterAdapter.ts index c0cbd7454..c8b48f52c 100644 --- a/src/adapters/notifications/NotificationCenterAdapter.ts +++ b/src/adapters/notifications/NotificationCenterAdapter.ts @@ -997,6 +997,7 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { try { const newOwnerPayload = { email: params.newOwnerUser?.email, + userId: params.newOwnerUser?.id || 0, ownerName: params.newOwnerUser?.name || '', projectName: params.projectName, }; @@ -1012,6 +1013,7 @@ export class NotificationCenterAdapter implements NotificationAdapterInterface { const oldOwnerPayload = { email: params.previousOwnerUser?.email, + userId: params.previousOwnerUser?.id || 0, ownerName: params.previousOwnerUser?.name || '', projectName: params.projectName, };