Skip to content

Commit 63627f5

Browse files
authored
Merge pull request #424 from Real-Dev-Squad/move-to-members
Move to members
2 parents 0b64d71 + c3c5b04 commit 63627f5

File tree

6 files changed

+205
-4
lines changed

6 files changed

+205
-4
lines changed

constants/roles.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const ROLES = {
2+
SUPER_USER: 'superUser',
3+
APP_OWNER: 'appOwner'
4+
}
5+
6+
module.exports = ROLES

controllers/members.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
const { ROLES } = require('../constants/users')
2-
const { fetchUsers, migrateUsers, deleteIsMemberProperty, fetchUsersWithRole } = require('../models/members')
2+
const { fetchUsers, migrateUsers, deleteIsMemberProperty, fetchUsersWithRole, moveToMembers: updateToMemberRole } = require('../models/members')
33
const tasks = require('../models/tasks')
4+
const { fetchUser } = require('../models/users')
5+
6+
const ERROR_MESSAGE = 'Something went wrong. Please try again or contact admin'
47

58
/**
69
* Fetches the data about our members
@@ -47,12 +50,38 @@ const getIdleMembers = async (req, res) => {
4750
}
4851
}
4952

53+
/**
54+
* Makes a new member a member
55+
*
56+
* @param req {Object} - Express request object
57+
* @param res {Object} - Express response object
58+
*/
59+
60+
const moveToMembers = async (req, res) => {
61+
try {
62+
const { username } = req.params
63+
const result = await fetchUser({ username })
64+
if (result.userExists) {
65+
const successObject = await updateToMemberRole(result.user.id)
66+
if (successObject.isAlreadyMember) {
67+
return res.boom.badRequest('User is already a member')
68+
}
69+
return res.status(204).send()
70+
}
71+
return res.boom.notFound("User doesn't exist")
72+
} catch (err) {
73+
logger.error(`Error while retriving contributions ${err}`)
74+
return res.boom.badImplementation(ERROR_MESSAGE)
75+
}
76+
}
77+
5078
/**
5179
* Returns the lists of usernames migrated
5280
*
5381
* @param req {Object} - Express request object
5482
* @param res {Object} - Express response object
5583
*/
84+
5685
const migrateUserRoles = async (req, res) => {
5786
try {
5887
const migratedUserData = await migrateUsers()
@@ -88,6 +117,7 @@ const deleteIsMember = async (req, res) => {
88117
module.exports = {
89118
getMembers,
90119
getIdleMembers,
120+
moveToMembers,
91121
migrateUserRoles,
92122
deleteIsMember
93123
}

models/members.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ const fetchUsers = async () => {
3939
}
4040
}
4141

42+
/**
43+
* changes the role of a new user to member
44+
* @param userId { String }: User id of user to be modified
45+
* @return { Object }: whether moveToMember was successful or not and whether user is already a member or not
46+
*/
47+
48+
const moveToMembers = async (userId) => {
49+
try {
50+
const userDoc = await userModel.doc(userId).get()
51+
const user = userDoc.data()
52+
if (user?.roles?.member) return { isAlreadyMember: true, movedToMember: false }
53+
const roles = user.roles ? { ...user.roles, member: true } : { member: true }
54+
await userModel.doc(userId).update({
55+
roles
56+
})
57+
return { isAlreadyMember: false, movedToMember: true }
58+
} catch (err) {
59+
logger.error('Error updating user', err)
60+
throw err
61+
}
62+
}
63+
4264
/**
4365
* Migrate user roles
4466
* @return {Promise<usersMigrated|Object>}
@@ -127,6 +149,7 @@ const fetchUsersWithRole = async (role) => {
127149
}
128150

129151
module.exports = {
152+
moveToMembers,
130153
fetchUsers,
131154
migrateUsers,
132155
deleteIsMemberProperty,

public/apiSchema.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

routes/members.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
const express = require('express')
22
const router = express.Router()
3-
const { getMembers, getIdleMembers, migrateUserRoles, deleteIsMember } = require('../controllers/members')
3+
const { getMembers, getIdleMembers, migrateUserRoles, deleteIsMember, moveToMembers } = require('../controllers/members')
44
const { authorizeUser } = require('../middlewares/authorization')
55
const authenticate = require('../middlewares/authenticate')
66
const { addRecruiter } = require('../controllers/recruiters')
77
const { validateRecruiter } = require('../middlewares/validators/recruiter')
8+
const { SUPER_USER } = require('../constants/roles')
89

910
/**
1011
* @swagger
@@ -86,6 +87,51 @@ router.get('/idle', getIdleMembers)
8687

8788
router.post('/intro/:username', validateRecruiter, addRecruiter)
8889

90+
/**
91+
* @swagger
92+
* /moveToMembers/:username:
93+
* patch:
94+
* summary: Changes the role of a new member(the username provided in params) to member
95+
* tags:
96+
* - Members
97+
* security:
98+
* - bearerAuth: []
99+
* responses:
100+
* 204:
101+
* description: no content
102+
* 400:
103+
* description: badRequest
104+
* content:
105+
* application/json:
106+
* schema:
107+
* type: object
108+
* properties:
109+
* message:
110+
* type: string
111+
* example: User Already is a member
112+
*
113+
* 401:
114+
* description: unAuthorized
115+
* content:
116+
* application/json:
117+
* schema:
118+
* $ref: '#/components/schemas/errors/unAuthorized'
119+
* 404:
120+
* description: notFound
121+
* content:
122+
* application/json:
123+
* schema:
124+
* $ref: '#/components/schemas/errors/notFound'
125+
*
126+
* 500:
127+
* description: serverUnavailable
128+
* content:
129+
* application/json:
130+
* schema:
131+
* $ref: '#/components/schemas/errors/serverUnavailable'
132+
*/
133+
134+
router.patch('/moveToMembers/:username', authenticate, authorizeUser(SUPER_USER), moveToMembers)
89135
/**
90136
* @swagger
91137
* /members/member-to-role-migration:

test/integration/members.test.js

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,34 @@ const { expect } = chai
33
const chaiHttp = require('chai-http')
44

55
const app = require('../../server')
6+
const authService = require('../../services/authService')
67
const addUser = require('../utils/addUser')
78
const cleanDb = require('../utils/cleanDb')
89

10+
// Import fixtures
11+
const userData = require('../fixtures/user/user')()
12+
13+
const config = require('config')
14+
const cookieName = config.get('userToken.cookieName')
15+
916
chai.use(chaiHttp)
1017

18+
const superUser = userData[4]
19+
const userAlreadyMember = userData[0]
20+
const userToBeMadeMember = userData[1]
21+
const nonSuperUser = userData[2]
22+
1123
describe('Members', function () {
24+
let jwt
25+
1226
afterEach(async function () {
13-
await cleanDb()
1427
await addUser()
1528
})
1629

30+
after(async function () {
31+
await cleanDb()
32+
})
33+
1734
describe('GET /members', function () {
1835
before(async function () {
1936
await cleanDb()
@@ -89,4 +106,83 @@ describe('Members', function () {
89106
})
90107
})
91108
})
109+
110+
describe('PATCH /members/moveToMembers/:username', function () {
111+
before(async function () {
112+
await cleanDb()
113+
const userId = await addUser(superUser)
114+
jwt = authService.generateAuthToken({ userId })
115+
})
116+
117+
it("Should return 404 if user doesn't exist", function (done) {
118+
chai
119+
.request(app)
120+
.patch(`/members/moveToMembers/${userToBeMadeMember.username}`)
121+
.set('cookie', `${cookieName}=${jwt}`)
122+
.end((err, res) => {
123+
if (err) { return done(err) }
124+
125+
expect(res).to.have.status(404)
126+
expect(res.body).to.be.a('object')
127+
expect(res.body.message).to.equal("User doesn't exist")
128+
129+
return done()
130+
})
131+
})
132+
133+
it('Should make the user a member', function (done) {
134+
addUser(userToBeMadeMember).then(() => {
135+
chai
136+
.request(app)
137+
.patch(`/members/moveToMembers/${userToBeMadeMember.username}`)
138+
.set('cookie', `${cookieName}=${jwt}`)
139+
.end((err, res) => {
140+
if (err) { return done(err) }
141+
142+
expect(res).to.have.status(204)
143+
/* eslint-disable no-unused-expressions */
144+
expect(res.body).to.be.a('object').to.be.empty
145+
146+
return done()
147+
})
148+
})
149+
})
150+
151+
it('Should return 400 if user is already a member', function (done) {
152+
addUser(userAlreadyMember).then(() => {
153+
chai
154+
.request(app)
155+
.patch(`/members/moveToMembers/${userAlreadyMember.username}`)
156+
.set('cookie', `${cookieName}=${jwt}`)
157+
.end((err, res) => {
158+
if (err) { return done(err) }
159+
160+
expect(res).to.have.status(400)
161+
expect(res.body).to.be.a('object')
162+
expect(res.body.message).to.equal('User is already a member')
163+
164+
return done()
165+
})
166+
})
167+
})
168+
169+
it('Should return 401 if user is not a super_user', function (done) {
170+
addUser(nonSuperUser).then(nonSuperUserId => {
171+
const nonSuperUserJwt = authService.generateAuthToken({ nonSuperUserId })
172+
chai
173+
.request(app)
174+
.patch(`/members/moveToMembers/${nonSuperUser.username}`)
175+
.set('cookie', `${cookieName}=${nonSuperUserJwt}`)
176+
.end((err, res) => {
177+
if (err) { return done(err) }
178+
179+
expect(res).to.have.status(401)
180+
expect(res.body).to.be.a('object')
181+
expect(res.body.message).to.equal('You are not authorized for this action.')
182+
183+
return done()
184+
})
185+
})
186+
})
187+
})
92188
})

0 commit comments

Comments
 (0)