Skip to content

Commit 513b969

Browse files
authored
feat: Wire in open and close times for hacker POST (#663)
* feat: wire in openTime and closeTime into the postHacker route. * feat: Add check to make sure that openTime < closeTime < confirmTime when doing a patch * fix: change update settings test so that the inputs are valid
1 parent 1c4b3ec commit 513b969

File tree

7 files changed

+138
-15
lines changed

7 files changed

+138
-15
lines changed

constants/error.constant.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ const TEAM_MEMBER_422_MESSAGE = "Duplicate team member in input";
2525
const VALIDATION_422_MESSAGE = "Validation failed";
2626
const ACCOUNT_DUPLICATE_422_MESSAGE = "Account already exists";
2727
const ROLE_DUPLICATE_422_MESSAGE = "Role already exists";
28+
const SETTINGS_422_MESSAGE =
29+
"openTime must be before closeTime, and closeTime must be before confirmTime";
2830

2931
const ACCOUNT_TOKEN_401_MESSAGE = "Invalid token for account";
3032
const AUTH_401_MESSAGE = "Invalid Authentication";
3133

3234
const AUTH_403_MESSAGE = "Invalid Authorization";
3335
const ACCOUNT_403_MESSAGE = "Account not verified";
36+
const SETTINGS_403_MESSAGE = "Applications are not open right now";
3437

3538
const TEAM_READ_500_MESSAGE = "Error while retrieving team";
3639
const TEAM_UPDATE_500_MESSAGE = "Error while updating team";
@@ -79,13 +82,15 @@ module.exports = {
7982
HACKER_STATUS_409_MESSAGE: HACKER_STATUS_409_MESSAGE,
8083
TEAM_SIZE_409_MESSAGE: TEAM_SIZE_409_MESSAGE,
8184
ROLE_DUPLICATE_422_MESSAGE: ROLE_DUPLICATE_422_MESSAGE,
85+
SETTINGS_422_MESSAGE: SETTINGS_422_MESSAGE,
8286
ROLE_CREATE_500_MESSAGE: ROLE_CREATE_500_MESSAGE,
8387
TEAM_NAME_409_MESSAGE: TEAM_NAME_409_MESSAGE,
8488
TEAM_JOIN_SAME_409_MESSAGE: TEAM_JOIN_SAME_409_MESSAGE,
8589
TEAM_READ_500_MESSAGE: TEAM_READ_500_MESSAGE,
8690
VOLUNTEER_404_MESSAGE: VOLUNTEER_404_MESSAGE,
8791
SPONSOR_UPDATE_500_MESSAGE: SPONSOR_UPDATE_500_MESSAGE,
8892
SETTINGS_404_MESSAGE: SETTINGS_404_MESSAGE,
93+
SETTINGS_403_MESSAGE: SETTINGS_403_MESSAGE,
8994
TRAVEL_404_MESSAGE: TRAVEL_404_MESSAGE,
9095
TRAVEL_CREATE_500_MESSAGE: TRAVEL_CREATE_500_MESSAGE
9196
};

middlewares/settings.middleware.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,28 @@ async function updateSettings(req, res, next) {
5555
}
5656
}
5757

58+
/**
59+
* @function confirmValidPatch
60+
* @param {{body:{settingsDetails:{openTime:Date, closeTime:Date, confirmTime:Date}}}} req
61+
* @param {*} res
62+
* @param {*} next
63+
* @return {void}
64+
* @description Confirms that openTime < closeTime < confirmTime
65+
*/
66+
function confirmValidPatch(req, res, next) {
67+
const openTime = new Date(req.body.settingsDetails.openTime);
68+
const closeTime = new Date(req.body.settingsDetails.closeTime);
69+
const confirmTime = new Date(req.body.settingsDetails.confirmTime);
70+
if (openTime < closeTime && closeTime < confirmTime) {
71+
return next();
72+
}
73+
return next({
74+
status: 422,
75+
message: Constants.Error.SETTINGS_422_MESSAGE,
76+
error: req.body.settingsDetails
77+
});
78+
}
79+
5880
/**
5981
* @function updateSettings
6082
* @param {*} req
@@ -76,8 +98,38 @@ async function getSettings(req, res, next) {
7698
}
7799
}
78100

101+
/**
102+
* @function confirmAppsOpen
103+
* @param {*} req
104+
* @param {*} res
105+
* @param {*} next
106+
* @description Only succeeds if the currentTime > openTime, and currentTime < closeTime
107+
*/
108+
async function confirmAppsOpen(req, res, next) {
109+
const settings = await Services.Settings.getSettings();
110+
if (!settings) {
111+
return next({
112+
status: 500,
113+
message: Constants.Error.GENERIC_500_MESSAGE
114+
});
115+
} else {
116+
const now = Date.now();
117+
const openTime = new Date(settings.openTime);
118+
const closeTime = new Date(settings.closeTime);
119+
if (openTime < now && closeTime > now) {
120+
return next();
121+
}
122+
return next({
123+
status: 403,
124+
message: Constants.Error.SETTINGS_403_MESSAGE
125+
});
126+
}
127+
}
128+
79129
module.exports = {
80130
parsePatch: parsePatch,
131+
confirmValidPatch: confirmValidPatch,
132+
confirmAppsOpen: Middleware.Util.asyncMiddleware(confirmAppsOpen),
81133
updateSettings: Middleware.Util.asyncMiddleware(updateSettings),
82134
getSettings: Middleware.Util.asyncMiddleware(getSettings)
83135
};

routes/api/hacker.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const Middleware = {
1414
Util: require("../../middlewares/util.middleware"),
1515
Hacker: require("../../middlewares/hacker.middleware"),
1616
Auth: require("../../middlewares/auth.middleware"),
17-
Search: require("../../middlewares/search.middleware")
17+
Search: require("../../middlewares/search.middleware"),
18+
Settings: require("../../middlewares/settings.middleware")
1819
};
1920
const Services = {
2021
Hacker: require("../../services/hacker.service"),
@@ -180,8 +181,9 @@ module.exports = {
180181
Middleware.Auth.ensureAuthenticated(),
181182
Middleware.Auth.ensureAuthorized(),
182183
Middleware.Validator.Hacker.newHackerValidator,
183-
184184
Middleware.parseBody.middleware,
185+
Middleware.Settings.confirmAppsOpen,
186+
185187
// validate type
186188
Middleware.Hacker.validateConfirmedStatusFromAccountId,
187189
// validate that the accountId is not being used for any other thing

routes/api/settings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ module.exports = {
7878
Middleware.Validator.Settings.createSettingsValidator,
7979
Middleware.parseBody.middleware,
8080
Middleware.Settings.parsePatch,
81+
Middleware.Settings.confirmValidPatch,
8182
Middleware.Settings.updateSettings,
8283
Controllers.Settings.patchedSettings
8384
);

tests/hacker.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const util = {
1818
auth: require("./util/auth.test.util"),
1919
hacker: require("./util/hacker.test.util"),
2020
account: require("./util/account.test.util"),
21+
settings: require("./util/settings.test.util"),
2122
accountConfirmation: require("./util/accountConfirmation.test.util")
2223
};
2324
const StorageService = require("../services/storage.service");
@@ -459,6 +460,56 @@ describe("POST create hacker", function() {
459460
});
460461
});
461462

463+
it("should FAIL to create a new hacker when applications have not yet opened.", function(done) {
464+
// Upload application not yet open.
465+
util.settings.setApplicationNotYetOpen().then(
466+
util.auth.login(agent, newHackerAccount0, (error) => {
467+
if (error) {
468+
agent.close();
469+
return done(error);
470+
}
471+
return agent
472+
.post(`/api/hacker/`)
473+
.type("application/json")
474+
.send(newHacker0)
475+
.end(function(err, res) {
476+
res.should.have.status(403);
477+
res.should.be.json;
478+
res.body.should.have.property("message");
479+
res.body.message.should.equal(
480+
Constants.Error.SETTINGS_403_MESSAGE
481+
);
482+
done();
483+
});
484+
})
485+
);
486+
});
487+
488+
it("should FAIL to create a new hacker when applications have closed.", function(done) {
489+
// Upload application closed.
490+
util.settings.setApplicationClosed().then(
491+
util.auth.login(agent, newHackerAccount0, (error) => {
492+
if (error) {
493+
agent.close();
494+
return done(error);
495+
}
496+
return agent
497+
.post(`/api/hacker/`)
498+
.type("application/json")
499+
.send(newHacker0)
500+
.end(function(err, res) {
501+
res.should.have.status(403);
502+
res.should.be.json;
503+
res.body.should.have.property("message");
504+
res.body.message.should.equal(
505+
Constants.Error.SETTINGS_403_MESSAGE
506+
);
507+
done();
508+
});
509+
})
510+
);
511+
});
512+
462513
// should fail due to travel request larger than 100
463514
it("should FAIL if the new hacker inputs a value larger than 100 for travel reimbursement", function(done) {
464515
util.auth.login(agent, newHackerAccount0, (error) => {

tests/settings.test.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const agent = chai.request.agent(server.app);
77
chai.should();
88
const util = {
99
account: require("./util/account.test.util"),
10-
auth: require("./util/auth.test.util")
10+
auth: require("./util/auth.test.util"),
11+
settings: require("./util/settings.test.util")
1112
};
1213

1314
const Constants = {
@@ -84,11 +85,7 @@ describe("PATCH settings", function() {
8485
agent
8586
.patch(`/api/settings/`)
8687
.type("application/json")
87-
.send({
88-
openTime: new Date().toString(),
89-
closeTime: new Date().toString(),
90-
confirmTime: new Date().toString()
91-
})
88+
.send(util.settings.settingConfirmClosed)
9289
// does not have password because of to stripped json
9390
.end(function(err, res) {
9491
res.should.have.status(200);

tests/util/settings.test.util.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
const Settings = require("../../models/settings.model");
22
const logger = require("../../services/logger.service");
33

4-
const settingRegistrationNotYetOpen = {
4+
const settingApplicationNotYetOpen = {
55
openTime: new Date(Date.now() + 100000000000),
66
closeTime: new Date(Date.now() + 10000000000000000),
77
confirmTime: new Date(Date.now() + 100000000000000000)
88
};
99

10-
const settingRegistrationOpen = {
10+
const settingApplicationOpen = {
1111
openTime: new Date(Date.now() - 100),
1212
closeTime: new Date(Date.now() + 10000000000),
1313
confirmTime: new Date(Date.now() + 100000000000000)
1414
};
1515

16-
const settingRegistrationClosed = {
16+
const settingApplicationClosed = {
1717
openTime: new Date(Date.now() - 100),
1818
closeTime: new Date(Date.now() - 1000),
1919
confirmTime: new Date(Date.now() + 100000000000000)
@@ -26,9 +26,22 @@ const settingConfirmClosed = {
2626
};
2727

2828
async function storeAll() {
29-
const toStore = new Settings(settingRegistrationClosed);
29+
const toStore = new Settings(settingApplicationOpen);
3030
Settings.collection.insertOne(toStore);
3131
}
32+
33+
async function setApplicationClosed() {
34+
await dropAll();
35+
const toStore = new Settings(settingApplicationClosed);
36+
Settings.collection.insertOne(toStore);
37+
}
38+
39+
async function setApplicationNotYetOpen() {
40+
await dropAll();
41+
const toStore = new Settings(settingApplicationNotYetOpen);
42+
Settings.collection.insertOne(toStore);
43+
}
44+
3245
async function dropAll() {
3346
try {
3447
await Settings.collection.drop();
@@ -43,8 +56,10 @@ async function dropAll() {
4356
module.exports = {
4457
storeAll: storeAll,
4558
dropAll: dropAll,
46-
settingRegistrationNotYetOpen: settingRegistrationNotYetOpen,
47-
settingRegistrationOpen: settingRegistrationOpen,
48-
settingRegistrationClosed: settingRegistrationClosed,
59+
setApplicationClosed: setApplicationClosed,
60+
setApplicationNotYetOpen: setApplicationNotYetOpen,
61+
settingApplicationNotYetOpen: settingApplicationNotYetOpen,
62+
settingApplicationOpen: settingApplicationOpen,
63+
settingApplicationClosed: settingApplicationClosed,
4964
settingConfirmClosed: settingConfirmClosed
5065
};

0 commit comments

Comments
 (0)