Skip to content

Commit feb02b3

Browse files
Merge pull request #19 from Giveth/f_746_add_editable_field_to_notificationType
Add isEmailEditable and isWebEditable to notificationType schema
2 parents f706773 + 1ee0010 commit feb02b3

8 files changed

+262
-94
lines changed

migrations/1660540253547-createNotificationType.ts

+24
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,30 @@ export class createNotificationType1660540253547 implements MigrationInterface {
3737
isNullable: false,
3838
default: false,
3939
},
40+
{
41+
name: 'webDefaultValue',
42+
type: 'boolean',
43+
isNullable: false,
44+
default: true,
45+
},
46+
{
47+
name: 'emailDefaultValue',
48+
type: 'boolean',
49+
isNullable: false,
50+
default: false,
51+
},
52+
{
53+
name: 'isWebEditable',
54+
type: 'boolean',
55+
isNullable: false,
56+
default: true,
57+
},
58+
{
59+
name: 'isEmailEditable',
60+
type: 'boolean',
61+
isNullable: false,
62+
default: false,
63+
},
4064
{
4165
name: 'categoryGroup',
4266
type: 'text',

migrations/1660716115917-seedNotificationType.ts

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export const GivethNotificationTypes = {
164164
title: 'Project published',
165165
description: 'When Project has been published',
166166
showOnSettingPage: true,
167+
isEmailEditable: true,
167168
category: NOTIFICATION_CATEGORY.PROJECT_RELATED,
168169
icon: 'IconPublish',
169170
microService: MICRO_SERVICES.givethio,
@@ -1758,6 +1759,8 @@ export const GivethNotificationTypes = {
17581759
title: 'Project status',
17591760
description: 'Your project status',
17601761
showOnSettingPage: true,
1762+
isEmailEditable: true,
1763+
isWebEditable: false,
17611764
microService: MICRO_SERVICES.givethio,
17621765
schemaValidator: null,
17631766
emailNotifierService: null,
@@ -1781,6 +1784,7 @@ export const GivethNotificationTypes = {
17811784
description:
17821785
'When someone donates to your project, when you donate to a project, donation success and failure.',
17831786
showOnSettingPage: true,
1787+
isEmailEditable: true,
17841788
microService: MICRO_SERVICES.givethio,
17851789
schemaValidator: null,
17861790
emailNotifierService: null,

src/controllers/v1/notificationSettingsController.ts

+27-24
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import { Route, Tags, Body, Security, Inject, Get, Query, Put } from 'tsoa';
22
import { logger } from '../../utils/logger';
33
import {
4+
findNotificationSettingById,
45
getUserNotificationSettings,
56
updateUserNotificationSetting,
67
} from '../../repositories/notificationSettingRepository';
78
import { UserAddress } from '../../entities/userAddress';
9+
import { errorMessages } from '../../utils/errorMessages';
10+
import {
11+
sendNotificationValidator,
12+
updateNotificationSettings,
13+
updateOneNotificationSetting,
14+
validateWithJoiSchema,
15+
} from '../../validators/schemaValidators';
816

917
interface SettingParams {
1018
id: number;
11-
allowNotifications?: string;
12-
allowEmailNotification?: string;
13-
allowDappPushNotification?: string;
19+
allowEmailNotification: boolean;
20+
allowDappPushNotification: boolean;
1421
}
1522

1623
@Route('/v1/notification_settings')
@@ -32,19 +39,16 @@ export class NotificationSettingsController {
3239
const { settings } = body;
3340

3441
try {
42+
validateWithJoiSchema(body, updateNotificationSettings);
43+
3544
const updatedNotifications = await Promise.all(
3645
settings.map(async setting => {
37-
const {
38-
id,
39-
allowNotifications,
40-
allowEmailNotification,
41-
allowDappPushNotification,
42-
} = setting;
46+
const { id, allowEmailNotification, allowDappPushNotification } =
47+
setting;
4348

4449
const updatedNotification = await updateUserNotificationSetting({
4550
notificationSettingId: id,
4651
userAddressId: user.id,
47-
allowNotifications,
4852
allowEmailNotification,
4953
allowDappPushNotification,
5054
});
@@ -66,32 +70,31 @@ export class NotificationSettingsController {
6670
@Body()
6771
body: {
6872
id: number;
69-
allowNotifications?: string;
70-
allowEmailNotification?: string;
71-
allowDappPushNotification?: string;
73+
allowEmailNotification: boolean;
74+
allowDappPushNotification: boolean;
7275
},
7376
@Inject()
7477
params: {
7578
user: UserAddress;
7679
},
7780
) {
7881
const { user } = params;
79-
const {
80-
id,
81-
allowNotifications,
82-
allowEmailNotification,
83-
allowDappPushNotification,
84-
} = body;
82+
const { id, allowEmailNotification, allowDappPushNotification } = body;
8583
try {
86-
const updatedNotification = await updateUserNotificationSetting({
84+
validateWithJoiSchema(body, updateOneNotificationSetting);
85+
86+
const notificationSetting = await findNotificationSettingById(id);
87+
88+
if (!notificationSetting) {
89+
throw new Error(errorMessages.NOTIFICATION_SETTING_NOT_FOUND);
90+
}
91+
const newSettingData = {
8792
notificationSettingId: id,
8893
userAddressId: user.id,
89-
allowNotifications,
9094
allowEmailNotification,
9195
allowDappPushNotification,
92-
});
93-
94-
return updatedNotification;
96+
};
97+
return await updateUserNotificationSetting(newSettingData);
9598
} catch (e) {
9699
logger.error('updateNotificationSetting() error', e);
97100
throw e;

src/entities/notificationType.ts

+13
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ export class NotificationType extends BaseEntity {
8383
@Column('boolean', { default: false })
8484
showOnSettingPage?: boolean;
8585

86+
// https://github.com/Giveth/impact-graph/issues/746
87+
@Column('boolean', { nullable: true, default: false })
88+
isEmailEditable: boolean;
89+
90+
@Column('boolean', { nullable: true, default: true })
91+
isWebEditable: boolean;
92+
93+
@Column('boolean', { nullable: true, default: false })
94+
emailDefaultValue: boolean;
95+
96+
@Column('boolean', { nullable: true, default: false })
97+
webDefaultValue: boolean;
98+
8699
@Index()
87100
@Column('text', { nullable: true })
88101
categoryGroup?: string;

src/repositories/notificationSettingRepository.test.ts

+54-11
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,69 @@ function updateUserNotificationSettingTestCases() {
103103
userAddressId: userAddress.id,
104104
})
105105
.andWhere('notificationType.isGroupParent = false')
106+
.andWhere('notificationType.isEmailEditable = true')
107+
.andWhere('notificationType.isWebEditable = true')
106108
.getOne();
107109

108110
assert.isTrue(userNotificationSetting?.userAddressId === userAddress.id);
109111

110112
const updatedSetting = await updateUserNotificationSetting({
111113
notificationSettingId: userNotificationSetting!.id,
112114
userAddressId: userAddress.id,
113-
allowNotifications: 'false',
114-
allowEmailNotification: 'false',
115-
allowDappPushNotification: 'false',
115+
allowEmailNotification: false,
116+
allowDappPushNotification: false,
116117
});
118+
assert.isOk(updatedSetting);
119+
assert.isFalse(updatedSetting?.allowEmailNotification);
120+
assert.isFalse(updatedSetting?.allowDappPushNotification);
121+
});
122+
it('update user notification settings, cant change when isEmailEditable is false', async () => {
123+
const userAddress = await createNewUserAddressIfNotExists(walletAddress);
117124

125+
const userNotificationSetting =
126+
await NotificationSetting.createQueryBuilder('setting')
127+
.leftJoinAndSelect('setting.notificationType', 'notificationType')
128+
.where('setting."userAddressId" = :userAddressId', {
129+
userAddressId: userAddress.id,
130+
})
131+
.andWhere('notificationType.isGroupParent = false')
132+
.andWhere('notificationType.isEmailEditable = false')
133+
.andWhere('notificationType.isWebEditable = true')
134+
.getOne();
135+
136+
assert.isTrue(userNotificationSetting?.userAddressId === userAddress.id);
137+
138+
const updatedSetting = await updateUserNotificationSetting({
139+
notificationSettingId: userNotificationSetting!.id,
140+
userAddressId: userAddress.id,
141+
allowEmailNotification: false,
142+
allowDappPushNotification: false,
143+
});
118144
assert.isOk(updatedSetting);
119-
assert.isTrue(
120-
userNotificationSetting!.allowNotifications !==
121-
updatedSetting!.allowNotifications,
122-
);
123-
assert.equal(userNotificationSetting!.allowNotifications, true);
124-
assert.equal(updatedSetting.allowNotifications, false);
125-
assert.equal(updatedSetting.allowEmailNotification, false);
126-
assert.equal(updatedSetting.allowDappPushNotification, false);
145+
assert.isTrue(updatedSetting?.allowEmailNotification);
146+
assert.isFalse(updatedSetting?.allowDappPushNotification);
147+
});
148+
it('update user notification settings, cant change when isWebEditable is false', async () => {
149+
const userAddress = await createNewUserAddressIfNotExists(walletAddress);
150+
151+
const userNotificationSetting =
152+
await NotificationSetting.createQueryBuilder('setting')
153+
.leftJoinAndSelect('setting.notificationType', 'notificationType')
154+
.where('setting."userAddressId" = :userAddressId', {
155+
userAddressId: userAddress.id,
156+
})
157+
.andWhere('notificationType.isWebEditable = false')
158+
.getOne();
159+
160+
assert.isTrue(userNotificationSetting?.userAddressId === userAddress.id);
161+
162+
const updatedSetting = await updateUserNotificationSetting({
163+
notificationSettingId: userNotificationSetting!.id,
164+
userAddressId: userAddress.id,
165+
allowEmailNotification: false,
166+
allowDappPushNotification: false,
167+
});
168+
assert.isOk(updatedSetting);
169+
assert.isTrue(updatedSetting?.allowDappPushNotification);
127170
});
128171
}

src/repositories/notificationSettingRepository.ts

+40-25
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,34 @@ export const findNotificationSettingByNotificationTypeAndUserAddress =
7676
}
7777
};
7878

79+
export const findNotificationSettingById = async (
80+
id: number,
81+
): Promise<NotificationSetting | null> => {
82+
try {
83+
return await NotificationSetting.createQueryBuilder('notificationSetting')
84+
.leftJoinAndSelect(
85+
'notificationSetting.notificationType',
86+
'notificationType',
87+
)
88+
.where('notificationSetting.id = :id', {
89+
id,
90+
})
91+
.getOne();
92+
} catch (e) {
93+
logger.error(
94+
'findNotificationSettingByNotificationTypeAndUserAddress() error',
95+
e,
96+
);
97+
throw e;
98+
}
99+
};
100+
79101
export const updateUserNotificationSetting = async (params: {
80102
notificationSettingId: number;
81103
userAddressId: number;
82-
allowNotifications?: string;
83-
allowEmailNotification?: string;
84-
allowDappPushNotification?: string;
85-
}) => {
104+
allowEmailNotification: boolean;
105+
allowDappPushNotification: boolean;
106+
}): Promise<NotificationSetting> => {
86107
const notificationSetting = await NotificationSetting.createQueryBuilder(
87108
'notificationSetting',
88109
)
@@ -102,15 +123,13 @@ export const updateUserNotificationSetting = async (params: {
102123
if (!notificationSetting)
103124
throw new Error(errorMessages.NOTIFICATION_SETTING_NOT_FOUND);
104125

105-
if (params.allowNotifications)
106-
notificationSetting.allowNotifications =
107-
params.allowNotifications === 'true';
108-
if (params.allowEmailNotification)
109-
notificationSetting.allowEmailNotification =
110-
params.allowEmailNotification === 'true';
111-
if (params.allowDappPushNotification)
126+
if (notificationSetting.notificationType?.isEmailEditable) {
127+
notificationSetting.allowEmailNotification = params.allowEmailNotification;
128+
}
129+
if (notificationSetting.notificationType?.isWebEditable) {
112130
notificationSetting.allowDappPushNotification =
113-
params.allowDappPushNotification === 'true';
131+
params.allowDappPushNotification;
132+
}
114133

115134
if (
116135
notificationSetting?.notificationType?.isGroupParent &&
@@ -119,7 +138,6 @@ export const updateUserNotificationSetting = async (params: {
119138
await updateChildNotificationSettings({
120139
categoryGroup: notificationSetting?.notificationType?.categoryGroup,
121140
userAddressId: params.userAddressId,
122-
allowNotifications: notificationSetting.allowNotifications,
123141
allowEmailNotification: notificationSetting.allowEmailNotification,
124142
allowDappPushNotification: notificationSetting.allowDappPushNotification,
125143
});
@@ -131,9 +149,8 @@ export const updateUserNotificationSetting = async (params: {
131149
export const updateChildNotificationSettings = async (params: {
132150
categoryGroup: string;
133151
userAddressId: number;
134-
allowNotifications?: boolean;
135-
allowEmailNotification?: boolean;
136-
allowDappPushNotification?: boolean;
152+
allowEmailNotification: boolean;
153+
allowDappPushNotification: boolean;
137154
}) => {
138155
// Grab type ids
139156
const notificationTypes = await NotificationType.createQueryBuilder(
@@ -153,14 +170,12 @@ export const updateChildNotificationSettings = async (params: {
153170
if (notificationTypeIds.length === 0) return;
154171

155172
await NotificationSetting.query(`
156-
UPDATE notification_setting
157-
SET "allowNotifications" = ${
158-
params.allowNotifications
159-
}, "allowEmailNotification" = ${
160-
params.allowEmailNotification
161-
}, "allowDappPushNotification" = ${params.allowDappPushNotification}
162-
WHERE "notificationTypeId" IN (${notificationTypeIds.join(
163-
',',
164-
)}) AND "userAddressId" = ${params.userAddressId}
173+
UPDATE notification_setting
174+
SET "allowEmailNotification" = ${
175+
params.allowEmailNotification
176+
}, "allowDappPushNotification" = ${params.allowDappPushNotification}
177+
WHERE "notificationTypeId" IN (${notificationTypeIds.join(
178+
',',
179+
)}) AND "userAddressId" = ${params.userAddressId}
165180
`);
166181
};

0 commit comments

Comments
 (0)