Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit f1df1d4

Browse files
#638 - Provide new route to get all uploads and support capturing failed records data in uploads
1 parent 541aeef commit f1df1d4

File tree

6 files changed

+171
-10
lines changed

6 files changed

+171
-10
lines changed

docs/swagger.yaml

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,65 @@ paths:
9090
- api_key: []
9191
x-swagger-router-controller: "Templates"
9292
/uploads:
93+
get:
94+
summary: "Get all uploads"
95+
description: |
96+
"Return all uploads. You can specify the date from when you would like the records.""
97+
tags:
98+
- "uploads"
99+
operationId: "getUploads"
100+
parameters:
101+
- name: "from"
102+
in: "query"
103+
description: "The date from when you would like the uploads (inclusive)"
104+
required: false
105+
type: "string"
106+
default: "today's value"
107+
responses:
108+
"200":
109+
description: "Success"
110+
schema:
111+
type: array
112+
items:
113+
$ref: '#/definitions/Upload'
114+
"400":
115+
$ref: "#/definitions/BadRequest"
116+
"401":
117+
$ref: "#/definitions/Unauthorized"
118+
"403":
119+
$ref: "#/definitions/Forbidden"
120+
"404":
121+
$ref: "#/definitions/NotFound"
122+
"500":
123+
$ref: "#/definitions/ServerError"
124+
125+
head:
126+
summary: "Get only status code for fetching all uploads"
127+
description: "Equivalent to GET /uploads, but returns only status codes"
128+
tags:
129+
- "uploads"
130+
operationId: "headUploads"
131+
parameters:
132+
- name: "from"
133+
in: "query"
134+
description: "The date from when you would like the uploads (inclusive)"
135+
required: false
136+
type: "string"
137+
default: "today's value"
138+
responses:
139+
"200":
140+
description: "Success"
141+
"400":
142+
$ref: "#/definitions/BadRequest"
143+
"401":
144+
$ref: "#/definitions/Unauthorized"
145+
"403":
146+
$ref: "#/definitions/Forbidden"
147+
"404":
148+
$ref: "#/definitions/NotFound"
149+
"500":
150+
$ref: "#/definitions/ServerError"
151+
93152
post:
94153
tags:
95154
- "uploads"
@@ -176,7 +235,7 @@ paths:
176235
description: "The request body"
177236
required: true
178237
schema:
179-
$ref: "#/definitions/body"
238+
$ref: "#/definitions/PartiallyUpdateUpload"
180239
responses:
181240
"200":
182241
description: "Success"
@@ -258,6 +317,10 @@ definitions:
258317
type: "string"
259318
format: "uri"
260319
description: "S3 signed url"
320+
failedRecordsUrl:
321+
type: "string"
322+
format: "uri"
323+
description: "S3 signed url"
261324
status:
262325
type: "string"
263326
enum:
@@ -368,7 +431,7 @@ definitions:
368431
example: "Creating a resource with a name already exists."
369432
description: "The conflict error message."
370433
description: "The conflict error entity."
371-
body:
434+
PartiallyUpdateUpload:
372435
type: "object"
373436
required:
374437
- "status"
@@ -377,3 +440,5 @@ definitions:
377440
type: "string"
378441
info:
379442
type: "string"
443+
failedRecordsObjectKey:
444+
type: "string"

src/common/helper.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,23 @@ async function getById (modelName, id) {
129129
})
130130
}
131131

132+
/**
133+
* Get all Data by model
134+
* @param {String} modelName The dynamoose model name
135+
* @returns found record(s)
136+
*/
137+
async function getAll (modelName, query) {
138+
return new Promise((resolve, reject) => {
139+
models[modelName].scan(query).exec((err, result) => {
140+
if (err) {
141+
reject(err)
142+
} else {
143+
resolve(result)
144+
}
145+
})
146+
})
147+
}
148+
132149
/**
133150
* Create item in database
134151
* @param {Object} modelName The dynamoose model name
@@ -201,11 +218,16 @@ async function uploadToS3 (bucket, file, fileName) {
201218
* @returns {string} signed url
202219
*/
203220
function generateS3Url (objectKey) {
204-
const url = s3.getSignedUrl('getObject', {
205-
Bucket: config.UPLOAD_S3_BUCKET,
206-
Key: objectKey,
207-
Expires: parseInt(config.S3_OBJECT_URL_EXPIRY_TIME)
208-
})
221+
let url
222+
223+
if (objectKey) {
224+
url = s3.getSignedUrl('getObject', {
225+
Bucket: config.UPLOAD_S3_BUCKET,
226+
Key: objectKey,
227+
Expires: parseInt(config.S3_OBJECT_URL_EXPIRY_TIME)
228+
})
229+
}
230+
209231
return url
210232
}
211233

@@ -291,6 +313,7 @@ module.exports = {
291313
createTable,
292314
deleteTable,
293315
getById,
316+
getAll,
294317
create,
295318
update,
296319
uploadToS3,

src/controllers/UploadController.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ async function uploadEntity (req, res) {
1313
res.send(result)
1414
}
1515

16+
/**
17+
* Get upload
18+
* @param {Object} req the request
19+
* @param {Object} res the response
20+
*/
21+
async function getEntities (req, res) {
22+
const result = await service.getEntities(req.query)
23+
res.send(result)
24+
}
25+
1626
/**
1727
* Get upload
1828
* @param {Object} req the request
@@ -34,6 +44,7 @@ async function partiallyUpdate (req, res) {
3444
}
3545

3646
module.exports = {
47+
getEntities,
3748
getEntity,
3849
uploadEntity,
3950
partiallyUpdate

src/models/Upload.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ const schema = new Schema({
4343
updatedBy: {
4444
type: String,
4545
required: true
46+
},
47+
failedRecordsObjectKey: {
48+
type: String,
49+
required: false
4650
}
4751
},
4852
{

src/routes.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ module.exports = {
2929
auth: 'jwt',
3030
access: constants.AllAuthenticatedUsers,
3131
scopes: [constants.Scopes.CreateUpload, constants.Scopes.AllUpload]
32+
},
33+
get: {
34+
controller: 'UploadController',
35+
method: 'getEntities',
36+
auth: 'jwt',
37+
access: constants.AllAuthenticatedUsers,
38+
scopes: [constants.Scopes.GetUpload, constants.Scopes.AllUpload]
3239
}
3340
},
3441
'/uploads/:id': {

src/services/UploadService.js

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,39 @@ async function ensureFileTypeIsValid (upload) {
3232
}
3333
}
3434

35+
/**
36+
* Returns all uploads (filtered by created date)
37+
* @param {Object} query the filter query
38+
* @returns {Object} the upload of given id
39+
*/
40+
async function getEntities (query) {
41+
if (!query.from) {
42+
query.from = (new Date((new Date()).setDate((new Date()).getDate() - 1)).toISOString()) // 24 hours ago
43+
}
44+
const uploads = await helper.getAll(config.AMAZON.DYNAMODB_UPLOAD_TABLE, { created: { ge: query.from } })
45+
const res = _.map(uploads, (upload) => {
46+
upload = _.extend(
47+
_.omit(
48+
_.pickBy(upload, _.isString),
49+
['objectKey', 'failedRecordsObjectKey']
50+
),
51+
{
52+
url: helper.generateS3Url(upload.objectKey),
53+
failedRecordsUrl: helper.generateS3Url(upload.failedRecordsObjectKey)
54+
}
55+
)
56+
57+
return upload
58+
})
59+
return res
60+
}
61+
62+
getEntity.schema = {
63+
query: Joi.object().keys({
64+
from: Joi.date().iso()
65+
})
66+
}
67+
3568
/**
3669
* Get upload entity by id.
3770
* @param {String} id the upload id
@@ -40,7 +73,15 @@ async function ensureFileTypeIsValid (upload) {
4073
async function getEntity (id) {
4174
// get from DB
4275
const upload = await helper.getById(config.AMAZON.DYNAMODB_UPLOAD_TABLE, id)
43-
const res = _.extend(_.omit(_.pickBy(upload, _.isString), 'objectKey'), { url: helper.generateS3Url(upload.objectKey) })
76+
const res = _.extend(
77+
_.omit(
78+
_.pickBy(upload, _.isString),
79+
['objectKey', 'failedRecordsObjectKey']),
80+
{
81+
url: helper.generateS3Url(upload.objectKey),
82+
failedRecordsUrl: helper.generateS3Url(upload.failedRecordsObjectKey)
83+
}
84+
)
4485
return res
4586
}
4687

@@ -109,7 +150,15 @@ async function partiallyUpdate (authUser, id, data) {
109150
}
110151
// then update data in DB
111152
await helper.update(upload, data)
112-
const res = _.extend(_.omit(_.pickBy(upload, _.isString), 'objectKey'), { url: helper.generateS3Url(upload.objectKey) })
153+
const res = _.extend(
154+
_.omit(
155+
_.pickBy(upload, _.isString),
156+
['objectKey', 'failedRecordsObjectKey']),
157+
{
158+
url: helper.generateS3Url(upload.objectKey),
159+
failedRecordsUrl: helper.generateS3Url(upload.failedRecordsObjectKey)
160+
}
161+
)
113162
return res
114163
}
115164

@@ -118,11 +167,13 @@ partiallyUpdate.schema = {
118167
authUser: Joi.object().required(),
119168
data: Joi.object().keys({
120169
status: Joi.string().valid('pending', 'completed', 'failed').required(),
121-
info: Joi.string()
170+
info: Joi.string(),
171+
failedRecordsObjectKey: Joi.string()
122172
}).required()
123173
}
124174

125175
module.exports = {
176+
getEntities,
126177
getEntity,
127178
create,
128179
partiallyUpdate

0 commit comments

Comments
 (0)