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

GrottoCenter / grottocenter-api / 23021407638

12 Mar 2026 08:03PM UTC coverage: 85.34% (-0.07%) from 85.405%
23021407638

push

github

ClemRz
chore(ci): upgrade GitHub Actions to Node.js 24

Upgrade GitHub Actions to Node.js 24 compatible versions:
- actions/checkout v4 -> v6
- actions/setup-node v4 -> v6
- actions/upload-artifact v4 -> v6
- actions/download-artifact v4 -> v8

2669 of 3289 branches covered (81.15%)

Branch coverage included in aggregate %.

5615 of 6418 relevant lines covered (87.49%)

33.35 hits per line

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

87.5
/api/controllers/v1/document/import-rows.js
1
const DocumentService = require('../../../services/DocumentService');
1✔
2
const DocumentCSVImportService = require('../../../services/DocumentCSVImportService');
1✔
3
const RightService = require('../../../services/RightService');
1✔
4
const {
5
  checkColumns,
6
  valIfTruthyOrNull,
7
  getOrCreateAuthor,
8
} = require('../../../utils/csvHelper');
1✔
9

10
module.exports = async (req, res) => {
1✔
11
  const hasRight = RightService.hasGroup(
5✔
12
    req.token.groups,
13
    RightService.G.ADMINISTRATOR
14
  );
15
  if (!hasRight) {
5✔
16
    return res.forbidden('You are not authorized to import documents via CSV.');
1✔
17
  }
18

19
  const cache = await DocumentCSVImportService.loadReferenceCache();
4✔
20

21
  const requestResponse = {
4✔
22
    type: 'document',
23
    total: {},
24
    successfulImport: [],
25
    successfulImportAsDuplicates: [],
26
    failureImport: [],
27
  };
28

29
  for (const [index, data] of req.body.data.entries()) {
4✔
30
    const missingColumns = checkColumns(data);
3✔
31
    // Stop if missing columnes
32
    if (missingColumns.length > 0) {
3✔
33
      requestResponse.failureImport.push({
1✔
34
        line: index + 2,
35
        message: `Columns missing : ${missingColumns.toString()}`,
36
      });
37
      continue; // eslint-disable-line no-continue
1✔
38
    }
39

40
    try {
2✔
41
      // Data formatting
42
      // Author retrieval : create one if not present in db
43
      // eslint-disable-next-line no-await-in-loop
44
      const authorId = await getOrCreateAuthor(data);
2✔
45
      const dataDocument =
46
        // eslint-disable-next-line no-await-in-loop
47
        await DocumentCSVImportService.getConvertedDocumentFromCsv(
2✔
48
          req,
49
          data,
50
          authorId,
51
          cache
52
        );
53
      const dataDescription =
54
        // eslint-disable-next-line no-await-in-loop
55
        await DocumentCSVImportService.getConvertedDescriptionFromCsv(
1✔
56
          data,
57
          authorId,
58
          cache
59
        );
60

61
      // Check for duplicates
62
      const idDb = valIfTruthyOrNull(data.id);
1✔
63
      const nameDb = valIfTruthyOrNull(data['dct:rights/cc:attributionName']);
1✔
64
      // eslint-disable-next-line no-await-in-loop
65
      const dbDocument = await TDocument.findOne({
1✔
66
        idDbImport: idDb,
67
        nameDbImport: nameDb,
68
        isDeleted: false,
69
      });
70
      if (dbDocument) {
1!
71
        // Create a duplicate in DB
72
        // eslint-disable-next-line no-await-in-loop
73
        await TDocumentDuplicate.create({
1✔
74
          author: req.token.id,
75
          content: {
76
            document: dataDocument,
77
            description: dataDescription,
78
          },
79
          dateInscription: new Date(),
80
          document: dbDocument.id,
81
        });
82

83
        requestResponse.successfulImportAsDuplicates.push({
1✔
84
          line: index + 2,
85
          message: `Document with id ${idDb} has been created as a document duplicate.`,
86
        });
87
        continue; // eslint-disable-line no-continue
1✔
88
      }
89

90
      // eslint-disable-next-line no-await-in-loop
91
      const createdDocument = await DocumentService.createDocument(
×
92
        req,
93
        dataDocument,
94
        dataDescription,
95
        true
96
      );
97
      // eslint-disable-next-line no-await-in-loop
98
      const docFiles = await TFile.find({ document: createdDocument.id });
×
99

100
      requestResponse.successfulImport.push({
×
101
        documentId: createdDocument.id,
102
        title: dataDescription.title,
103
        filesImported: docFiles.map((f) => f.fileName).join(','),
×
104
      });
105
    } catch (err) {
106
      sails.log.error(err);
1✔
107
      requestResponse.failureImport.push({
1✔
108
        line: index + 2,
109
        message: err.toString(),
110
      });
111
    }
112
  }
113

114
  requestResponse.total = {
4✔
115
    success: requestResponse.successfulImport.length,
116
    successfulImportAsDuplicates:
117
      requestResponse.successfulImportAsDuplicates.length,
118
    failure: requestResponse.failureImport.length,
119
  };
120

121
  return res.ok(requestResponse);
4✔
122
};
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