• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GrottoCenter / grottocenter-api / 11479910404

23 Oct 2024 12:30PM UTC coverage: 45.243% (+0.02%) from 45.225%
11479910404

Pull #1330

github

vmarseguerra
feat(notification): auto deletion of old notifications after 2 months
Pull Request #1330: Small improvements

728 of 2231 branches covered (32.63%)

Branch coverage included in aggregate %.

3 of 12 new or added lines in 3 files covered. (25.0%)

1 existing line in 1 file now uncovered.

2458 of 4811 relevant lines covered (51.09%)

4.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.6
/api/controllers/v1/document/delete.js
1
const ControllerService = require('../../../services/ControllerService');
1✔
2
const NotificationService = require('../../../services/NotificationService');
1✔
3
const DocumentService = require('../../../services/DocumentService');
1✔
4
const RightService = require('../../../services/RightService');
1✔
5
const { toDocument } = require('../../../services/mapping/converters');
1✔
6
const FileService = require('../../../services/FileService');
1✔
7
const RecentChangeService = require('../../../services/RecentChangeService');
1✔
8

9
module.exports = async (req, res) => {
1✔
10
  const hasRight = RightService.hasGroup(
×
11
    req.token.groups,
12
    RightService.G.MODERATOR
13
  );
14
  if (!hasRight) {
×
15
    return res.forbidden('You are not authorized to delete a document.');
×
16
  }
17

18
  // Check if document exists and if it's not already deleted
19
  const documentId = req.param('id');
×
20
  const document = await DocumentService.getPopulatedDocument(documentId);
×
21
  if (!document) {
×
22
    return res.notFound({ message: `Document of id ${documentId} not found.` });
×
23
  }
24

25
  if (!document.isDeleted) {
×
26
    const redirectTo = parseInt(req.param('entityId'), 10);
×
27
    if (!Number.isNaN(redirectTo)) {
×
28
      document.redirectTo = redirectTo;
×
29
      await TDocument.updateOne(documentId)
×
30
        .set({ redirectTo })
31
        .catch(() => {});
32
    }
33

34
    await TDocument.destroyOne({ id: documentId }); // Soft delete
×
35
    document.isDeleted = true;
×
36

37
    await DocumentService.deleteESDocument(document).catch(() => {});
×
38
    await RecentChangeService.setDeleteRestoreAuthor(
×
39
      'delete',
40
      'document',
41
      documentId,
42
      req.token.id
43
    );
44
  }
45

46
  const deletePermanently = !!req.param('isPermanent');
×
47
  const mergeIntoId = parseInt(req.param('entityId'), 10);
×
48
  let shouldMergeInto = !Number.isNaN(mergeIntoId);
×
49
  let mergeIntoEntity;
50
  if (shouldMergeInto) {
×
51
    mergeIntoEntity = await DocumentService.appendPopulateForFullDocument(
×
52
      TDocument.findOne(mergeIntoId)
53
    );
54
    shouldMergeInto = !!mergeIntoEntity;
×
55
  }
56

57
  if (deletePermanently) {
×
58
    await TDocument.update({ redirectTo: documentId }).set({
×
59
      dateReviewed: new Date(), // Avoid a uniqueness error
60
      redirectTo: shouldMergeInto ? mergeIntoId : null,
×
61
    });
NEW
62
    await TDocument.update({ parent: documentId })
×
63
      .set({
64
        dateReviewed: new Date(), // Avoid a uniqueness error
65
        parent: shouldMergeInto ? mergeIntoId : null,
×
66
      })
67
      .meta({ fetch: false });
UNCOV
68
    await HDocument.update({ parent: documentId }).set({
×
69
      parent: shouldMergeInto ? mergeIntoId : null,
×
70
    });
NEW
71
    await TDocument.update({ authorizationDocument: documentId }).set({
×
72
      dateReviewed: new Date(), // Avoid a uniqueness error
73
      authorizationDocument: null,
74
    });
75

76
    await TNotification.destroy({ document: documentId });
×
77

78
    // eslint-disable-next-line no-inner-declarations
79
    async function linkedEntitiesDeleteOrMerge(key) {
80
      if (document[key].length === 0) return;
×
81
      if (shouldMergeInto) {
×
82
        const existingEntities = mergeIntoEntity[key].map((e) => e.id);
×
83
        const entitiesToAdd = document[key]
×
84
          .map((e) => e.id)
×
85
          .filter((e) => !existingEntities.includes(e));
×
86
        await TDocument.addToCollection(mergeIntoId, key, entitiesToAdd);
×
87
      }
88
      await TDocument.updateOne(documentId).set({ [key]: [] });
×
89
    }
90

91
    if (document.files.length > 0) {
×
92
      if (shouldMergeInto) {
×
93
        TFile.update({ document: documentId }).set({ document: mergeIntoId });
×
94
      } else {
95
        await Promise.all(
×
96
          document.files.map((e) => FileService.document.delete(e))
×
97
        );
98
      }
99
    }
100

101
    await linkedEntitiesDeleteOrMerge('countries');
×
102
    await linkedEntitiesDeleteOrMerge('isoRegions');
×
103
    await linkedEntitiesDeleteOrMerge('languages');
×
104
    await linkedEntitiesDeleteOrMerge('massifs');
×
105
    await linkedEntitiesDeleteOrMerge('subjects');
×
106
    await linkedEntitiesDeleteOrMerge('authorsGrotto');
×
107
    await linkedEntitiesDeleteOrMerge('authors');
×
108

109
    await TDocument.updateOne(documentId).set({ regions: [] });
×
110

111
    await TDocumentDuplicate.destroy({ id: documentId });
×
112

113
    // Documents have no TName but a TDescription instead
114
    await TDescription.destroy({ document: documentId }); // TDescription first soft delete
×
115
    await HDescription.destroy({ document: documentId });
×
116
    await TDescription.destroy({ document: documentId });
×
117

118
    await HDocument.destroy({ t_id: documentId });
×
119
    await TDocument.destroyOne({ id: documentId }); // Hard delete
×
120
  }
121

122
  await NotificationService.notifySubscribers(
×
123
    req,
124
    document,
125
    req.token.id,
126
    deletePermanently
×
127
      ? NotificationService.NOTIFICATION_TYPES.PERMANENT_DELETE
128
      : NotificationService.NOTIFICATION_TYPES.DELETE,
129
    NotificationService.NOTIFICATION_ENTITIES.DOCUMENT
130
  );
131

132
  return ControllerService.treatAndConvert(
×
133
    req,
134
    null,
135
    document,
136
    { controllerMethod: 'DocumentController.delete' },
137
    res,
138
    toDocument
139
  );
140
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc