Skip to content

Commit 6acd302

Browse files
committed
merge branch 'LED4MEMBERS' into Request-Button4LEDSIGN
th
2 parents 86a5910 + 9a70800 commit 6acd302

File tree

3 files changed

+58
-42
lines changed

3 files changed

+58
-42
lines changed

api/main_endpoints/models/PermissionRequest.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ const PermissionRequestSchema = new Schema(
88
type: Schema.Types.ObjectId,
99
ref: 'User',
1010
required: true,
11-
index: true,
1211
},
1312
type: {
1413
type: String,
15-
enum: Object.keys(PermissionRequestTypes),
14+
enum: Object.values(PermissionRequestTypes),
1615
required: true,
1716
},
1817
deletedAt: {
@@ -24,7 +23,7 @@ const PermissionRequestSchema = new Schema(
2423
);
2524

2625
// Compound unique index prevents duplicate active requests per user+type
27-
PermissionRequestSchema.index({ userId: 1, type: 1 }, { unique: true });
26+
PermissionRequestSchema.index({ userId: 1, type: 1 }, { unique: true, partialFilterExpression: { deletedAt: null }});
2827

2928
module.exports = mongoose.model('PermissionRequest', PermissionRequestSchema);
3029

api/main_endpoints/routes/PermissionRequest.js

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const express = require('express');
22
const router = express.Router();
33
const PermissionRequest = require('../models/PermissionRequest');
4-
const { OK, UNAUTHORIZED, SERVER_ERROR, NOT_FOUND, BAD_REQUEST } = require('../../util/constants').STATUS_CODES;
4+
const { OK, UNAUTHORIZED, FORBIDDEN, SERVER_ERROR, NOT_FOUND, BAD_REQUEST, CONFLICT } = require('../../util/constants').STATUS_CODES;
55
const membershipState = require('../../util/constants.js').MEMBERSHIP_STATE;
66
const { decodeToken } = require('../util/token-functions.js');
77
const logger = require('../../util/logger');
@@ -17,69 +17,84 @@ router.post('/create', async (req, res) => {
1717
}
1818

1919
try {
20-
const permissionRequest = await PermissionRequest.create({
20+
await PermissionRequest.create({
2121
userId: decoded.token._id,
2222
type,
2323
});
24-
const populated = await PermissionRequest.findById(permissionRequest._id)
25-
.populate('userId', 'firstName lastName email');
26-
res.status(OK).send(populated);
24+
res.sendStatus(OK);
2725
} catch (error) {
28-
if (error.code === 11000) return res.status(BAD_REQUEST).send({ error: 'Request already exists' });
26+
if (error.code === 11000) return res.sendStatus(CONFLICT);
2927
logger.error('Failed to create permission request:', error);
3028
res.sendStatus(SERVER_ERROR);
3129
}
3230
});
3331

34-
router.get('/getAll', async (req, res) => {
35-
const decoded = await decodeToken(req, membershipState.OFFICER);
32+
router.get('/get', async (req, res) => {
33+
const decoded = await decodeToken(req, membershipState.MEMBER);
3634
if (decoded.status !== OK) return res.sendStatus(decoded.status);
3735

36+
const { userId: queryUserId, type } = req.query;
37+
const isOfficer = decoded.token.accessLevel >= membershipState.OFFICER;
38+
3839
try {
39-
const requests = await PermissionRequest.find({ deletedAt: null })
40+
const query = { deletedAt: null };
41+
42+
// If theres no userId, return all for officers and admins
43+
if (!queryUserId) {
44+
if (!isOfficer) {
45+
return res.sendStatus(UNAUTHORIZED);
46+
}
47+
} else {
48+
// If there is a userId, check their perms
49+
if (!isOfficer && queryUserId !== decoded.token._id.toString()) {
50+
return res.sendStatus(FORBIDDEN);
51+
}
52+
query.userId = queryUserId;
53+
}
54+
55+
// If there is a type, filter by it
56+
if (type && Object.keys(PermissionRequestTypes).includes(type)) {
57+
query.type = type;
58+
}
59+
60+
const requests = await PermissionRequest.find(query)
4061
.populate('userId', 'firstName lastName email')
4162
.sort({ createdAt: -1 });
63+
4264
res.status(OK).send(requests);
4365
} catch (error) {
4466
logger.error('Failed to get permission requests:', error);
4567
res.sendStatus(SERVER_ERROR);
4668
}
4769
});
4870

49-
router.get('/get', async (req, res) => {
50-
const decoded = await decodeToken(req, membershipState.MEMBER);
51-
if (decoded.status !== OK) return res.sendStatus(decoded.status);
52-
53-
try {
54-
const request = await PermissionRequest.findOne({
55-
userId: decoded.token._id,
56-
type: req.query.type,
57-
deletedAt: null,
58-
}).populate('userId', 'firstName lastName email');
59-
60-
if (!request) return res.sendStatus(NOT_FOUND);
61-
res.status(OK).send(request);
62-
} catch (error) {
63-
logger.error('Failed to get permission request:', error);
64-
res.sendStatus(SERVER_ERROR);
65-
}
66-
});
67-
6871
router.post('/delete', async (req, res) => {
6972
const decoded = await decodeToken(req, membershipState.MEMBER);
7073
if (decoded.status !== OK) return res.sendStatus(decoded.status);
7174

72-
const { type } = req.body;
75+
const { type, _id } = req.body;
7376
if (!type || !Object.keys(PermissionRequestTypes).includes(type)) {
7477
return res.status(BAD_REQUEST).send({ error: 'Invalid type' });
7578
}
7679

7780
try {
78-
const request = await PermissionRequest.findOne({
79-
userId: decoded.token._id,
80-
type,
81-
deletedAt: null,
82-
});
81+
let request;
82+
// Officers or admins can delete any request by id
83+
if (decoded.token.accessLevel >= membershipState.OFFICER && _id) {
84+
request = await PermissionRequest.findOne({
85+
_id,
86+
type,
87+
deletedAt: null,
88+
});
89+
} else {
90+
// Members can delete their own requests and officers can delete their own requests without id
91+
request = await PermissionRequest.findOne({
92+
userId: decoded.token._id,
93+
type,
94+
deletedAt: null,
95+
});
96+
}
97+
8398
if (!request) return res.sendStatus(NOT_FOUND);
8499
request.deletedAt = new Date();
85100
await request.save();

test/api/PermissionRequest.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,22 @@ describe('PermissionRequest', () => {
6363
});
6464

6565
describe('/GET get', () => {
66-
it('Should return 404 when request does not exist', async () => {
66+
it('Should return empty array when request does not exist', async () => {
6767
const userId = new mongoose.Types.ObjectId();
6868
setTokenStatus(true, { _id: userId, email: 'test@test.com', accessLevel: 'MEMBER' });
69-
const res = await test.sendGetRequest('/api/PermissionRequest/get?type=' + PermissionRequestTypes.LED_SIGN);
70-
expect(res).to.have.status(NOT_FOUND);
69+
const res = await test.sendGetRequest('/api/PermissionRequest/get?userId=' + userId + '&type=' + PermissionRequestTypes.LED_SIGN);
70+
expect(res).to.have.status(OK);
71+
expect(res.body).to.be.an('array').that.is.empty;
7172
});
7273

7374
it('Should return permission request when it exists', async () => {
7475
const userId = new mongoose.Types.ObjectId();
7576
setTokenStatus(true, { _id: userId, email: 'test@test.com', accessLevel: 'MEMBER' });
7677
await new PermissionRequest({ userId, type: PermissionRequestTypes.LED_SIGN }).save();
77-
const res = await test.sendGetRequest('/api/PermissionRequest/get?type=' + PermissionRequestTypes.LED_SIGN);
78+
const res = await test.sendGetRequest('/api/PermissionRequest/get?userId=' + userId + '&type=' + PermissionRequestTypes.LED_SIGN);
7879
expect(res).to.have.status(OK);
79-
expect(res.body.type).to.equal(PermissionRequestTypes.LED_SIGN);
80+
expect(res.body).to.be.an('array').with.length(1);
81+
expect(res.body[0].type).to.equal(PermissionRequestTypes.LED_SIGN);
8082
});
8183
});
8284

0 commit comments

Comments
 (0)