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

GrottoCenter / grottocenter-api / 10996310862

23 Sep 2024 02:22PM UTC coverage: 46.158% (-2.8%) from 48.952%
10996310862

push

github

vmarseguerra
feat(entities): adds delete / restore for document

740 of 2203 branches covered (33.59%)

Branch coverage included in aggregate %.

24 of 153 new or added lines in 17 files covered. (15.69%)

484 existing lines in 49 files now uncovered.

2462 of 4734 relevant lines covered (52.01%)

4.5 hits per line

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

7.69
/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

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

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

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

NEW
33
    await TDocument.destroyOne({ id: documentId }); // Soft delete
×
NEW
34
    await DocumentService.createESDocument(document).catch(() => {});
×
NEW
35
    document.isDeleted = true;
×
36
  }
37

NEW
38
  const deletePermanently = !!req.param('isPermanent');
×
NEW
39
  const mergeIntoId = parseInt(req.param('entityId'), 10);
×
NEW
40
  let shouldMergeInto = !Number.isNaN(mergeIntoId);
×
41
  let mergeIntoEntity;
NEW
42
  if (shouldMergeInto) {
×
NEW
43
    mergeIntoEntity = await DocumentService.appendPopulateForFullDocument(
×
44
      TDocument.findOne(mergeIntoId)
45
    );
NEW
46
    shouldMergeInto = !!mergeIntoEntity;
×
47
  }
48

NEW
49
  if (deletePermanently) {
×
NEW
50
    await TDocument.update({ redirectTo: documentId }).set({
×
51
      redirectTo: shouldMergeInto ? mergeIntoId : null,
×
52
    });
NEW
53
    await TDocument.update({ parent: documentId }).set({
×
54
      parent: shouldMergeInto ? mergeIntoId : null,
×
55
    });
NEW
56
    await HDocument.update({ parent: documentId }).set({
×
57
      parent: shouldMergeInto ? mergeIntoId : null,
×
58
    });
NEW
59
    await TDocument.update({ authorizationDocument: null }).set({
×
60
      authorizationDocument: null,
61
    });
62

NEW
63
    await TNotification.destroy({ document: documentId });
×
64

65
    // eslint-disable-next-line no-inner-declarations
66
    async function linkedEntitiesDeleteOrMerge(key) {
NEW
67
      if (document[key].length === 0) return;
×
NEW
68
      if (shouldMergeInto) {
×
NEW
69
        const existingEntities = mergeIntoEntity[key].map((e) => e.id);
×
NEW
70
        const entitiesToAdd = document[key]
×
NEW
71
          .map((e) => e.id)
×
NEW
72
          .filter((e) => !existingEntities.includes(e));
×
NEW
73
        await TDocument.addToCollection(mergeIntoId, key, entitiesToAdd);
×
74
      }
NEW
75
      await TDocument.updateOne(documentId).set({ [key]: [] });
×
76
    }
77

NEW
78
    if (document.files.length > 0) {
×
NEW
79
      if (shouldMergeInto) {
×
NEW
80
        TFile.update({ document: documentId }).set({ document: mergeIntoId });
×
81
      } else {
NEW
82
        await Promise.all(
×
NEW
83
          document.files.map((e) => FileService.document.delete(e))
×
84
        );
85
      }
86
    }
87

NEW
88
    await linkedEntitiesDeleteOrMerge('countries');
×
NEW
89
    await linkedEntitiesDeleteOrMerge('isoRegions');
×
NEW
90
    await linkedEntitiesDeleteOrMerge('languages');
×
NEW
91
    await linkedEntitiesDeleteOrMerge('massifs');
×
NEW
92
    await linkedEntitiesDeleteOrMerge('subjects');
×
NEW
93
    await linkedEntitiesDeleteOrMerge('authorsGrotto');
×
NEW
94
    await linkedEntitiesDeleteOrMerge('authors');
×
95

NEW
96
    await TDocument.updateOne(documentId).set({ regions: [] });
×
97

NEW
98
    await TDocumentDuplicate.destroy({ id: documentId });
×
99

100
    // Documents have no TName but a TDescription instead
NEW
101
    await TDescription.destroy({ document: documentId }); // TDescription first soft delete
×
NEW
102
    await HDescription.destroy({ document: documentId });
×
NEW
103
    await TDescription.destroy({ document: documentId });
×
104

NEW
105
    await HDocument.destroy({ t_id: documentId });
×
NEW
106
    await TDocument.destroyOne({ id: documentId }); // Hard delete
×
107
  }
108

NEW
109
  await NotificationService.notifySubscribers(
×
110
    req,
111
    document,
112
    req.token.id,
113
    deletePermanently
×
114
      ? NotificationService.NOTIFICATION_TYPES.PERMANENT_DELETE
115
      : NotificationService.NOTIFICATION_TYPES.DELETE,
116
    NotificationService.NOTIFICATION_ENTITIES.DOCUMENT
117
  );
118

NEW
119
  return ControllerService.treatAndConvert(
×
120
    req,
121
    null,
122
    document,
123
    { controllerMethod: 'DocumentController.delete' },
124
    res,
125
    toDocument
126
  );
127
};
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