Skip to content

Commit 8d741d1

Browse files
committed
Merge branch 'beta' into next
2 parents 9a0b62b + 1b06057 commit 8d741d1

File tree

5 files changed

+124
-0
lines changed

5 files changed

+124
-0
lines changed

CHANGELOG/CHANGELOG_beta.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [2.13.0-beta.1](https://github.com/ReliefApplications/ems-backend/compare/v2.12.2...v2.13.0-beta.1) (2025-02-27)
2+
3+
4+
### Features
5+
6+
* improve back-end caching for common services requests ([173877b](https://github.com/ReliefApplications/ems-backend/commit/173877b6f880194f1da554e4711bbbcb647181bd))
7+
18
# [2.12.0-beta.14](https://github.com/ReliefApplications/ems-backend/compare/v2.12.0-beta.13...v2.12.0-beta.14) (2025-02-14)
29

310

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { GraphQLError, GraphQLNonNull, GraphQLID } from 'graphql';
2+
import { logger } from '@services/logger.service';
3+
import { graphQLAuthCheck } from '@schema/shared';
4+
import { Context } from '@server/apollo/context';
5+
import { EmailDistributionList, EmailNotification } from '@models';
6+
import { EmailDistributionListType } from '@schema/types/emailDistribution.type';
7+
import extendAbilityForApplications from '@security/extendAbilityForApplication';
8+
import { AppAbility } from '@security/defineUserAbility';
9+
10+
/**
11+
* Mutation to delete an existing distribution list.
12+
*/
13+
export default {
14+
type: EmailDistributionListType,
15+
args: {
16+
id: { type: new GraphQLNonNull(GraphQLID) },
17+
},
18+
async resolve(_, { id }, context: Context) {
19+
graphQLAuthCheck(context);
20+
21+
try {
22+
const distributionList = await EmailDistributionList.findOne({
23+
_id: id,
24+
isDeleted: 0,
25+
});
26+
27+
if (!distributionList) {
28+
throw new GraphQLError(context.i18next.t('common.errors.dataNotFound'));
29+
}
30+
31+
const user = context.user;
32+
const ability: AppAbility = extendAbilityForApplications(
33+
user,
34+
distributionList.applicationId.toString()
35+
);
36+
37+
if (ability.cannot('update', 'EmailNotification')) {
38+
throw new GraphQLError(
39+
context.i18next.t('common.errors.permissionNotGranted')
40+
);
41+
}
42+
43+
// Unset the reference in any EmailNotifications using this distribution list
44+
await EmailNotification.updateMany(
45+
{ emailDistributionList: distributionList._id },
46+
{ $unset: { emailDistributionList: 1 } }
47+
);
48+
49+
// Delete DL
50+
await distributionList.deleteOne();
51+
52+
return distributionList;
53+
} catch (err) {
54+
logger.error(err.message, { stack: err.stack });
55+
if (err instanceof GraphQLError) {
56+
throw new GraphQLError(err.message);
57+
}
58+
throw new GraphQLError(
59+
context.i18next.t('common.errors.internalServerError')
60+
);
61+
}
62+
},
63+
};

src/schema/mutation/deleteEmailNotification.mutation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Types } from 'mongoose';
1515
import { Context } from '@server/apollo/context';
1616
import extendAbilityForApplications from '@security/extendAbilityForApplication';
1717
import { CustomTemplate } from '@models/customTemplate.model';
18+
import { deleteFile } from '@utils/notification/util';
1819

1920
/** Arguments for the deleteEmailNotification mutation */
2021
type DeleteEmailNotificationArgs = {
@@ -60,6 +61,7 @@ export default {
6061
_id: args.id,
6162
applicationId: args.applicationId,
6263
});
64+
await deleteFile(emailNotification.attachments, context);
6365
} else {
6466
// Handle cases where the user has limited permissions
6567
const accessibleEmailNotification = await EmailNotification.findOne({
@@ -73,6 +75,7 @@ export default {
7375
_id: args.id,
7476
applicationId: args.applicationId,
7577
});
78+
await deleteFile(emailNotification.attachments, context);
7679
}
7780
}
7881

src/schema/mutation/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import editEmailDistributionList from './editEmailDistributionList.mutation';
9696
import addCustomTemplate from './addCustomTemplate.mutation';
9797
import editCustomTemplate from './editCustomTemplate.mutation';
9898
import deleteEmailNotification from './deleteEmailNotification.mutation';
99+
import deleteEmailDistributionList from './deleteEmailDistributionList.mutation';
99100

100101
/** GraphQL mutation definition */
101102
const Mutation = new GraphQLObjectType({
@@ -198,6 +199,7 @@ const Mutation = new GraphQLObjectType({
198199
deleteDashboardTemplates,
199200
editCustomTemplate,
200201
deleteEmailNotification,
202+
deleteEmailDistributionList,
201203
},
202204
});
203205

src/utils/notification/util.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import { EmailNotificationAttachment } from '@models/emailNotification.model';
2+
import { Context } from '@server/apollo/context';
3+
import { logger } from '@services/logger.service';
4+
import axios from 'axios';
5+
import config from 'config';
6+
17
/**
28
* Returns headers required for Azure Function
39
*
@@ -13,3 +19,46 @@ export const azureFunctionHeaders = (req: any) => {
1319
}),
1420
};
1521
};
22+
23+
/**
24+
* Deletes files from document management
25+
*
26+
* @param attachments - attachment details, including file info and whether to send as an attachment.
27+
* @param context - context from GraphQL resolver, used to get accesstoken
28+
* @returns promise that resolves when the files have been deleted.
29+
*/
30+
export async function deleteFile(
31+
attachments: EmailNotificationAttachment,
32+
context: Context
33+
) {
34+
if (
35+
!attachments.files ||
36+
attachments.files.length === 0 ||
37+
!context.accesstoken
38+
) {
39+
return;
40+
}
41+
42+
const attachmentRequests = attachments.files.map(async (file) => {
43+
const { driveId, itemId, fileName } = file;
44+
45+
try {
46+
if (attachments.sendAsAttachment) {
47+
await axios.delete(
48+
`${config.get(
49+
'commonServices.url'
50+
)}/documents/drives/${driveId}/items/${itemId}`,
51+
{
52+
headers: {
53+
Authorization: `Bearer ${context.accesstoken}`,
54+
},
55+
}
56+
);
57+
}
58+
} catch (error) {
59+
logger.error(`Failed to delete file: ${fileName}`, error.message);
60+
}
61+
});
62+
63+
await Promise.all(attachmentRequests);
64+
}

0 commit comments

Comments
 (0)