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

GrottoCenter / grottocenter-api / 5846492135

pending completion
5846492135

push

github

vmarseguerra
refactor(right): replaces rights with a static groups system

750 of 1943 branches covered (38.6%)

Branch coverage included in aggregate %.

59 of 59 new or added lines in 35 files covered. (100.0%)

2700 of 5005 relevant lines covered (53.95%)

14.64 hits per line

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

8.0
/api/controllers/v1/document/multiple-validate.js
1
const DocumentService = require('../../../services/DocumentService');
1✔
2
const FileService = require('../../../services/FileService');
1✔
3
const RightService = require('../../../services/RightService');
1✔
4
const {
5
  NOTIFICATION_TYPES,
6
  NOTIFICATION_ENTITIES,
7
} = require('../../../services/NotificationService');
1✔
8
const NotificationService = require('../../../services/NotificationService');
1✔
9

10
async function markDocumentValidated(
11
  documentId,
12
  validationComment,
13
  validationAuthor
14
) {
15
  await TDocument.updateOne(documentId).set({
×
16
    isValidated: true,
17
    modifiedDocJson: null,
18
    dateValidation: new Date(),
19
    validationComment,
20
    validator: validationAuthor,
21
  });
22
}
23

24
async function validateAndUpdateDocument(
25
  document,
26
  validationComment,
27
  validationAuthor
28
) {
29
  const {
30
    documentMainLanguage,
31
    author,
32
    description,
33
    titleAndDescriptionLanguage,
34
    title,
35
    modifiedFiles,
36
    deletedFiles,
37
    newFiles,
38
    ...cleanedData
39
  } = document.modifiedDocJson;
×
40

41
  await sails.getDatastore().transaction(async (db) => {
×
42
    // Update associated data not handled by TDocument manually
43
    // Updated before the TDocument update so the last_change_document DB trigger will fetch the last updated name
44
    await TDescription.updateOne({ document: document.id })
×
45
      .set({
46
        author,
47
        body: description,
48
        document: document.id,
49
        language: titleAndDescriptionLanguage.id,
50
        title,
51
      })
52
      .usingConnection(db);
53

54
    await TDocument.updateOne(document.id)
×
55
      .set({
56
        ...cleanedData,
57
        // Currently, only one language per document is allowed
58
        ...(documentMainLanguage && {
×
59
          languages: documentMainLanguage.id,
60
        }),
61
        modifiedDocJson: null,
62
        dateValidation: new Date(),
63
        isValidated: true,
64
        validationComment,
65
        validator: validationAuthor,
66
      })
67
      .usingConnection(db);
68

69
    const filePromises = [];
×
70
    // Files have already been created,
71
    // they just need to be linked to the document.
72
    if (newFiles) {
×
73
      filePromises.push(
×
74
        ...newFiles.map((f) => TFile.updateOne(f.id).set({ isValidated: true }))
×
75
      );
76
    }
77
    if (modifiedFiles) {
×
78
      filePromises.push(
×
79
        ...modifiedFiles.map((f) => FileService.document.update(f))
×
80
      );
81
    }
82

83
    if (deletedFiles) {
×
84
      filePromises.push(
×
85
        ...deletedFiles.map((f) => FileService.document.delete(f))
×
86
      );
87
    }
88
    await Promise.all(filePromises);
×
89
  });
90
}
91

92
async function updateESAndNotify(req, documentId, hasChange, userId) {
93
  const found = await TDocument.findOne(documentId)
×
94
    .populate('author')
95
    .populate('authorizationDocument')
96
    .populate('authors')
97
    .populate('cave')
98
    .populate('descriptions')
99
    .populate('editor')
100
    .populate('entrance')
101
    .populate('identifierType')
102
    .populate('languages')
103
    .populate('library')
104
    .populate('license')
105
    .populate('massif')
106
    .populate('option')
107
    .populate('parent')
108
    .populate('regions')
109
    .populate('reviewer')
110
    .populate('subjects')
111
    .populate('type');
112
  await DocumentService.setNamesOfPopulatedDocument(found);
×
113

114
  if (hasChange) {
×
115
    await DocumentService.updateDocumentInElasticSearchIndexes(found);
×
116
  } else {
117
    await DocumentService.addDocumentToElasticSearchIndexes(found);
×
118
  }
119

120
  await NotificationService.notifySubscribers(
×
121
    req,
122
    found,
123
    userId,
124
    NOTIFICATION_TYPES.VALIDATE,
125
    NOTIFICATION_ENTITIES.DOCUMENT
126
  );
127
}
128

129
module.exports = async (req, res) => {
1✔
130
  const hasRight = RightService.hasGroup(
×
131
    req.token.groups,
132
    RightService.G.MODERATOR
133
  );
134
  if (!hasRight) {
×
135
    return res.forbidden(
×
136
      'You are not authorized to validate multiple documents.'
137
    );
138
  }
139

140
  const documentChanges = [];
×
141
  // Validate input
142
  for (const doc of req.param('documents') ?? []) {
×
143
    const isValidated = doc.isValidated
×
144
      ? !(doc.isValidated.toLowerCase() === 'false')
145
      : true;
146

147
    if (isValidated === false && !doc.validationComment) {
×
148
      return res.badRequest(
×
149
        `If the document with id ${doc.id} is refused, a comment must be provided.`
150
      );
151
    }
152

153
    documentChanges.push({
×
154
      id: doc.id,
155
      isValidated,
156
      validationComment: doc.validationComment,
157
    });
158
  }
159
  const documentIds = documentChanges.map((e) => e.id);
×
160
  const foundDocuments = await TDocument.find({ id: documentIds });
×
161

162
  for (const document of foundDocuments) {
×
163
    const change = documentChanges.find((d) => d.id === document.id);
×
164
    const isAModifiedDoc = !!document.modifiedDocJson;
×
165
    if (!change.isValidated) {
×
166
      // Validate it but do not update its fields
167
      // eslint-disable-next-line no-await-in-loop
168
      await markDocumentValidated(
×
169
        document.id,
170
        change.validationComment,
171
        req.token.id
172
      );
173
      continue; // eslint-disable-line no-continue
×
174
    }
175

176
    if (isAModifiedDoc) {
×
177
      // eslint-disable-next-line no-await-in-loop
178
      await validateAndUpdateDocument(
×
179
        document,
180
        change.validationComment,
181
        req.token.id
182
      );
183
    } else {
184
      // Likely a document creation
185
      // eslint-disable-next-line no-await-in-loop
186
      await markDocumentValidated(
×
187
        document.id,
188
        change.validationComment,
189
        req.token.id
190
      );
191
    }
192

193
    // eslint-disable-next-line no-await-in-loop
194
    await updateESAndNotify(
×
195
      res,
196
      document.id,
197
      isAModifiedDoc,
198
      req.token.id
199
    ).catch((err) =>
200
      sails.log.error(
×
201
        'Document multiple validate updateESAndNotify error',
202
        document,
203
        err
204
      )
205
    );
206
  }
207

208
  return res.ok();
×
209
};
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