Skip to content

Commit 7d74d53

Browse files
author
gondzo
committed
Merge branch 'maxceem-dev' into dev
2 parents b687593 + ff8cd2c commit 7d74d53

13 files changed

+881
-11
lines changed

common/Permission.js

+25
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,35 @@ function providerRoleCheck(req, res, next) {
3737
next();
3838
});
3939
}
40+
/**
41+
* check the user permission
42+
* if user role not pilot, then cannot perform pilot actions
43+
* @param req
44+
* @param res
45+
* @param next
46+
*/
47+
function pilotRoleCheck(req, res, next) {
48+
User.findOne({_id: req.auth.sub}, (err, user) => {
49+
if (!user) {
50+
throw new errors.AuthenticationRequiredError('Anonymous is not allowed to access', 401);
51+
}
52+
53+
if (user.role !== Role.PILOT) {
54+
throw new errors.NotPermittedError('Non-pilot is not allowed to access', 403);
55+
}
56+
req.auth.payload = {
57+
role: Role.PILOT,
58+
};
59+
next();
60+
});
61+
}
4062

4163

4264
module.exports = {
4365
providerRole() {
4466
return providerRoleCheck;
4567
},
68+
pilotRole() {
69+
return pilotRoleCheck;
70+
},
4671
};

controllers/MissionController.js

+33
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ module.exports = {
2323
getAllByDrone,
2424
download,
2525
remove,
26+
getPilotChecklist,
27+
updatePilotChecklist,
28+
fetchPilotMissions,
2629
};
2730

2831
/**
@@ -98,3 +101,33 @@ function* monthlyCountByDrone(req, res) {
98101
function* getAllByDrone(req, res) {
99102
res.json(yield MissionService.getAllByDrone(req.params.droneId, req.query));
100103
}
104+
105+
/**
106+
* Get a pilot checklist
107+
*
108+
* @param req the request
109+
* @param res the response
110+
*/
111+
function* getPilotChecklist(req, res) {
112+
res.json(yield MissionService.getPilotChecklist(req.params.id, req.auth.sub));
113+
}
114+
115+
/**
116+
* Update a pilot checklist
117+
*
118+
* @param req the request
119+
* @param res the response
120+
*/
121+
function* updatePilotChecklist(req, res) {
122+
res.json(yield MissionService.updatePilotChecklist(req.params.id, req.auth.sub, req.body));
123+
}
124+
125+
/**
126+
* Fetch pilot mission list
127+
*
128+
* @param req the request
129+
* @param res the response
130+
*/
131+
function* fetchPilotMissions(req, res) {
132+
res.json(yield MissionService.fetchPilotMissions(req.auth.sub, req.query));
133+
}

data/questions.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{"text": "Check your drone battery charge"},
3+
{"text": "Check for potential equipment damage"},
4+
{"text": "Check the current and anticipated weather"},
5+
{"text": "Check your available file storage"},
6+
{"text": "Determine ideal starting and landing spots"},
7+
{"text": "Ensure a strong signal from drone to controller"},
8+
{"text": "Scout the space you’re about to shoot"},
9+
{"text": "Inform others of your project'"}
10+
]

data/users.json

+21
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,26 @@
2727
"socialNetworkType": "google-oauth2",
2828
"socialNetworkId": 1,
2929
"socialNetworkAccessToken": "123456"
30+
},
31+
{
32+
"name": "pilot",
33+
"firstName": "fisrt",
34+
"lastName": "last",
35+
"email": "[email protected]",
36+
"password": "pilot",
37+
"avatarUrl": "http://google.com",
38+
"phone": "+1 123-1234-123",
39+
"address": {
40+
"coordinates": [
41+
73,
42+
56
43+
],
44+
"line1": "Address 1",
45+
"city": "City 1",
46+
"postalCode": "10000",
47+
"state": "state",
48+
"primary": true
49+
},
50+
"role": "pilot"
3051
}
3152
]

enum.js

+7
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ const DroneType = {
6666
type2: 'type2',
6767
};
6868

69+
const PilotChecklistAnswers = {
70+
YES: 'yes',
71+
NO: 'no',
72+
NOTE: 'note',
73+
};
74+
6975
module.exports = {
7076
SocialType,
7177
DroneStatus,
@@ -77,4 +83,5 @@ module.exports = {
7783
MissionStatus,
7884
NotificationType,
7985
RequestStatus,
86+
PilotChecklistAnswers,
8087
};

generate-test-data.js

+23-7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const Notification = models.Notification;
2929
const Service = models.Service;
3030
const DronePosition = models.DronePosition;
3131
const NoFlyZone = models.NoFlyZone;
32+
const Question = models.Question;
3233

3334
let drones;
3435
if (process.argv[2] === 'drones-within-area') {
@@ -47,6 +48,7 @@ const notifications = require('./data/notifications.json');
4748
const providerUsers = require('./data/provider-users.json');
4849
const positions = require('./data/dronePositions.json');
4950
const noFlyZones = require('./data/no-fly-zones.json');
51+
const questions = require('./data/questions.json');
5052

5153
const MissionStatus = require('./enum').MissionStatus;
5254
const RequestStatus = require('./enum').RequestStatus;
@@ -74,6 +76,7 @@ co(function*() {
7476
yield Notification.remove({});
7577
yield DronePosition.remove({});
7678
yield NoFlyZone.remove({});
79+
yield Question.remove({});
7780

7881
// encrypt password
7982
yield _.map(users, (u) => function* () {
@@ -147,7 +150,7 @@ co(function*() {
147150

148151
_.each(missions, (m, i) => {
149152
m.provider = packageDocs[i % packageDocs.length].provider;
150-
m.pilot = userDocs[0].id; // setting all to first user for testing convinience
153+
m.pilot = userDocs[0].id; // setting all to first user for testing convenience
151154
m.drone = droneDocs[i % droneDocs.length].id;
152155
m.status = _.values(MissionStatus)[Math.floor(Math.random() * _.values(MissionStatus).length)];
153156
m.telemetry = {
@@ -166,18 +169,20 @@ co(function*() {
166169
}];
167170
});
168171
logger.info(`creating ${missions.length} missions`);
169-
const missionDocs = yield Mission.create(missions);
172+
const missionDocs = yield Mission.create(
173+
_.map(missions, (mission, index) => _.assign(mission, {missionName: mission.missionName + ' ' + index}))
174+
);
170175

171176
_.each(reviews, (r, i) => {
172-
r.user = userDocs[0].id; // setting all to first user for testing convinience
177+
r.user = userDocs[0].id; // setting all to first user for testing convenience
173178
r.mission = missionDocs[i % missionDocs.length].id;
174179
r.provider = missionDocs[i % missionDocs.length].provider;
175180
});
176181
logger.info(`creating ${reviews.length} reviews`);
177182
yield Review.create(reviews);
178183

179184
_.each(requests, (r, i) => {
180-
r.user = userDocs[0].id; // setting all to first user for testing convinience
185+
r.user = userDocs[0].id; // setting all to first user for testing convenience
181186
r.package = packageDocs[i % packageDocs.length].id;
182187
r.provider = packageDocs[i % packageDocs.length].provider;
183188
});
@@ -205,8 +210,16 @@ co(function*() {
205210
const mindex = i % missionDocs.length;
206211
missionDocs[mindex].packageRequest = requestDocs[i].id;
207212
missionDocs[mindex].provider = requestDocs[i].provider;
208-
missionDocs[mindex].status = i % 2 ? MissionStatus.IN_PROGRESS : MissionStatus.COMPLETED;
209-
missionDocs[mindex].pilot = providerUserDocs[i % providerDocs.length].id;
213+
// add some missions to the pilot user
214+
if (i % (providerDocs.length + 1) !== providerDocs.length) {
215+
missionDocs[mindex].pilot = providerUserDocs[i % (providerDocs.length + 1)].id;
216+
// for provider user use same statuses as for providerRequests
217+
missionDocs[mindex].status = i % 2 ? MissionStatus.IN_PROGRESS : MissionStatus.COMPLETED;
218+
} else {
219+
missionDocs[mindex].pilot = userDocs[2].id; // pilot user
220+
// for pilot user use all possible statuses
221+
missionDocs[mindex].status = MissionStatus[_.keys(MissionStatus)[Math.floor(_.keys(MissionStatus).length * Math.random())]];
222+
}
210223
missionDocs[mindex].scheduledAt = today.add(1, 'h').toDate(); // +1 hour
211224
missionDocs[mindex].startedAt = today.add(2, 'h').toDate(); // +2 hours
212225
missionDocs[mindex].launchDate = today.toDate();
@@ -218,7 +231,7 @@ co(function*() {
218231
yield missionDocs[mindex].save();
219232
}
220233
_.each(notifications, (n) => {
221-
n.user = userDocs[0].id; // setting all to first user for testing convinience
234+
n.user = userDocs[0].id; // setting all to first user for testing convenience
222235
});
223236
logger.info(`creating ${notifications.length} notifications`);
224237
yield Notification.create(notifications);
@@ -232,6 +245,9 @@ co(function*() {
232245
logger.info(`creating ${noFlyZones.length} no fly zones`);
233246
yield NoFlyZone.create(noFlyZones);
234247

248+
logger.info(`creating ${questions.length} questions`);
249+
const questionDocs = yield Question.create(questions);
250+
235251
logger.info('data created successfully');
236252
}).then(() => {
237253
logger.info('Done');

models/Mission.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,39 @@ const ZoneSchema = new Schema({
4242
style: {type: Mixed, default: {}},
4343
});
4444

45+
// Pilot checklist answer schema
46+
const PilotChecklistAnswerSchema = new Schema({
47+
question: {type: Schema.Types.ObjectId, required: true, unique: true, ref: 'Question'},
48+
answer: {type: String, enum: _.values(enums.PilotChecklistAnswers)},
49+
note: String,
50+
});
51+
52+
if (!PilotChecklistAnswerSchema.options.toObject) {
53+
PilotChecklistAnswerSchema.options.toObject = {};
54+
}
55+
56+
PilotChecklistAnswerSchema.options.toObject.transform = function (doc, ret, options) {
57+
const sanitized = _.omit(ret, '__v', '_id');
58+
return sanitized;
59+
};
60+
61+
// Pilot checklist schema
62+
const PilotChecklistSchema = new Schema({
63+
answers: {type: [PilotChecklistAnswerSchema]},
64+
user: {type: Schema.Types.ObjectId, required: true, ref: 'User'},
65+
});
66+
67+
PilotChecklistSchema.plugin(timestamps);
68+
69+
if (!PilotChecklistSchema.options.toObject) {
70+
PilotChecklistSchema.options.toObject = {};
71+
}
72+
73+
PilotChecklistSchema.options.toObject.transform = function (doc, ret, options) {
74+
const sanitized = _.omit(ret, '__v', '_id');
75+
return sanitized;
76+
};
77+
4578
const MissionSchema = new mongoose.Schema({
4679
missionName: { type: String, required: false },
4780
plannedHomePosition: { type: mongoose.Schema.Types.Mixed, required: false },
@@ -51,6 +84,7 @@ const MissionSchema = new mongoose.Schema({
5184
provider: {type: Schema.Types.ObjectId, required: false, ref: 'Provider'},
5285
packageRequest: {type: Schema.Types.ObjectId, required: false, ref: 'PackageRequest'},
5386
pilot: {type: Schema.Types.ObjectId, required: false, ref: 'User'},
87+
pilotChecklist: PilotChecklistSchema,
5488
startingPoint: {type: Address, required: false},
5589
destinationPoint: {type: Address, required: false},
5690

@@ -119,7 +153,7 @@ if (!MissionSchema.options.toObject) {
119153
* @param {Object} options the transform options
120154
*/
121155
MissionSchema.options.toObject.transform = function (doc, ret, options) { // eslint-disable-line no-unused-vars
122-
const sanitized = _.omit(ret, '__v', '_id', 'createdAt', 'updatedAt', 'packageRequest', 'pilot', 'drone');
156+
const sanitized = _.omit(ret, '__v', '_id', 'createdAt', 'updatedAt', 'packageRequest', 'pilot', 'pilotChecklist', 'drone');
123157
sanitized.startingPoint = _.omit(sanitized.startingPoint, '_id');
124158
sanitized.destinationPoint = _.omit(sanitized.destinationPoint, '_id');
125159
sanitized.id = doc._id;

models/Question.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (C) 2016 TopCoder Inc., All Rights Reserved.
3+
*/
4+
'use strict';
5+
/**
6+
* The Question model
7+
*
8+
* @author TSCCODER
9+
* @version 1.0
10+
*/
11+
12+
const mongoose = require('../datasource').getMongoose();
13+
const helper = require('../common/helper');
14+
15+
const QuestionSchema = new mongoose.Schema({
16+
text: { type: String, required: true },
17+
});
18+
19+
helper.sanitizeSchema(QuestionSchema);
20+
21+
module.exports = {
22+
QuestionSchema,
23+
};

models/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ const NoFlyZoneSchema = require('./NoFlyZone').NoFlyZoneSchema;
8383

8484
const NoFlyZone = db.model('NoFlyZone', NoFlyZoneSchema);
8585

86+
// Question model
87+
const QuestionSchema = require('./Question').QuestionSchema;
88+
89+
const Question = db.model('Question', QuestionSchema);
90+
8691
module.exports = {
8792
Drone,
8893
DronePosition,
@@ -98,4 +103,5 @@ module.exports = {
98103
Service,
99104
Address,
100105
NoFlyZone,
106+
Question,
101107
};

routes.js

+20
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
const auth = require('./common/Auth.js');
1414
const providerRole = require('./common/Permission').providerRole;
15+
const pilotRole = require('./common/Permission').pilotRole;
1516

1617
module.exports = {
1718
'/login': {
@@ -389,4 +390,23 @@ module.exports = {
389390
method: 'remove',
390391
},
391392
},
393+
'/pilot/checklist/:id': {
394+
get: {
395+
controller: 'MissionController',
396+
middleware: [auth(), pilotRole()],
397+
method: 'getPilotChecklist',
398+
},
399+
put: {
400+
controller: 'MissionController',
401+
middleware: [auth(), pilotRole()],
402+
method: 'updatePilotChecklist',
403+
},
404+
},
405+
'/pilot/missions': {
406+
get: {
407+
controller: 'MissionController',
408+
middleware: [auth(), pilotRole()],
409+
method: 'fetchPilotMissions',
410+
},
411+
},
392412
};

0 commit comments

Comments
 (0)