Skip to content

Commit 21ac657

Browse files
authored
Merge pull request #59 from topcoder-platform/dev
Production release for connect `Admin functionality update 01` milestone
2 parents 3829cc8 + 754abce commit 21ac657

17 files changed

+362
-18
lines changed

src/constants.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ export const USER_ROLE = {
3030
TOPCODER_ADMIN: 'administrator',
3131
MANAGER: 'Connect Manager',
3232
COPILOT: 'Connect Copilot',
33+
CONNECT_ADMIN: 'Connect Admin',
3334
};
3435

36+
export const ADMIN_ROLES = [USER_ROLE.CONNECT_ADMIN, USER_ROLE.TOPCODER_ADMIN];
37+
3538

3639
export const EVENT = {
3740
ROUTING_KEY: {

src/permissions/project.delete.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import _ from 'lodash';
55
import util from '../util';
66
import models from '../models';
7-
import { USER_ROLE, PROJECT_MEMBER_ROLE } from '../constants';
7+
import { PROJECT_MEMBER_ROLE } from '../constants';
88

99
/**
1010
* Super admin, Topcoder Managers are allowed to edit any project
@@ -20,7 +20,7 @@ module.exports = freq => new Promise((resolve, reject) => {
2020
req.context = req.context || {};
2121
req.context.currentProjectMembers = members;
2222
// check if auth user has acecss to this project
23-
const hasAccess = util.hasRole(req, USER_ROLE.TOPCODER_ADMIN) ||
23+
const hasAccess = util.hasAdminRole(req) ||
2424
!_.isUndefined(_.find(members, m => m.userId === req.authUser.userId &&
2525
((m.role === PROJECT_MEMBER_ROLE.CUSTOMER && m.isPrimary) ||
2626
m.role === PROJECT_MEMBER_ROLE.MANAGER)));

src/permissions/project.edit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = freq => new Promise((resolve, reject) => {
1919
req.context = req.context || {};
2020
req.context.currentProjectMembers = members;
2121
// check if auth user has acecss to this project
22-
const hasAccess = util.hasRole(req, USER_ROLE.TOPCODER_ADMIN)
22+
const hasAccess = util.hasAdminRole(req)
2323
|| util.hasRole(req, USER_ROLE.MANAGER)
2424
|| !_.isUndefined(_.find(members, m => m.userId === req.authUser.userId));
2525

src/permissions/project.view.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module.exports = freq => new Promise((resolve, reject) => {
2020
req.context = req.context || {};
2121
req.context.currentProjectMembers = members;
2222
// check if auth user has acecss to this project
23-
const hasAccess = util.hasRole(req, USER_ROLE.TOPCODER_ADMIN)
23+
const hasAccess = util.hasAdminRole(req)
2424
|| util.hasRole(req, USER_ROLE.MANAGER)
2525
|| !_.isUndefined(_.find(members, m => m.userId === currentUserId));
2626

src/permissions/projectMember.delete.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import _ from 'lodash';
22
import util from '../util';
33
import models from '../models';
44
import {
5-
USER_ROLE,
65
PROJECT_MEMBER_ROLE,
76
} from '../constants';
87

@@ -25,7 +24,7 @@ module.exports = freq => new Promise((resolve, reject) => {
2524
const prjMemberId = _.parseInt(req.params.id);
2625
const memberToBeRemoved = _.find(members, m => m.id === prjMemberId);
2726
// check if auth user has acecss to this project
28-
const hasAccess = util.hasRole(req, USER_ROLE.TOPCODER_ADMIN)
27+
const hasAccess = util.hasAdminRole(req)
2928
|| (authMember && memberToBeRemoved && (authMember.role === PROJECT_MEMBER_ROLE.MANAGER ||
3029
(authMember.role === PROJECT_MEMBER_ROLE.CUSTOMER && authMember.isPrimary &&
3130
memberToBeRemoved.role === PROJECT_MEMBER_ROLE.CUSTOMER) ||

src/routes/projectMembers/update.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ describe('Project members update', () => {
267267
resJson.isPrimary.should.be.false;
268268
resJson.updatedBy.should.equal(40051332);
269269
deleteSpy.should.have.been.calledOnce;
270-
server.services.pubsub.publish.calledWith('project.member.removed').should.be.true;
270+
server.services.pubsub.publish.calledWith('project.member.updated').should.be.true;
271271
done();
272272
}
273273
});

src/routes/projects/create.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ module.exports = [
6666
*/
6767
(req, res, next) => {
6868
const project = req.body.param;
69-
const userRole = util.hasRole(req, USER_ROLE.MANAGER)
69+
// by default connect admin and managers joins projects as manager
70+
const userRole = util.hasRoles(req, [USER_ROLE.CONNECT_ADMIN, USER_ROLE.MANAGER])
7071
? PROJECT_MEMBER_ROLE.MANAGER
7172
: PROJECT_MEMBER_ROLE.CUSTOMER;
7273
// set defaults
@@ -136,6 +137,7 @@ module.exports = [
136137
req.log.error(err);
137138
return Promise.resolve();
138139
});
140+
// return Promise.resolve();
139141
})
140142

141143
.then(() => {

src/routes/projects/delete.spec.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,39 @@ describe('Project delete test', () => {
100100
}
101101
});
102102
});
103+
104+
it('should return 204, for connect admin, if project was successfully removed', (done) => {
105+
request(server)
106+
.delete(`/v4/projects/${project1.id}`)
107+
.set({
108+
Authorization: `Bearer ${testUtil.jwts.admin}`,
109+
})
110+
.expect(204)
111+
.end((err) => {
112+
if (err) {
113+
done(err);
114+
} else {
115+
server.services.pubsub.publish.calledWith('project.deleted').should.be.true;
116+
done();
117+
}
118+
});
119+
});
120+
121+
it('should return 204, for connect admin, if project was successfully removed', (done) => {
122+
request(server)
123+
.delete(`/v4/projects/${project1.id}`)
124+
.set({
125+
Authorization: `Bearer ${testUtil.jwts.admin}`,
126+
})
127+
.expect(204)
128+
.end((err) => {
129+
if (err) {
130+
done(err);
131+
} else {
132+
server.services.pubsub.publish.calledWith('project.deleted').should.be.true;
133+
done();
134+
}
135+
});
136+
});
103137
});
104138
});

src/routes/projects/get.spec.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,25 @@ describe('GET Project', () => {
136136
});
137137
});
138138

139+
it('should return the project for connect admin ', (done) => {
140+
request(server)
141+
.get(`/v4/projects/${project1.id}`)
142+
.set({
143+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
144+
})
145+
.expect('Content-Type', /json/)
146+
.expect(200)
147+
.end((err, res) => {
148+
if (err) {
149+
done(err);
150+
} else {
151+
const resJson = res.body.result.content;
152+
should.exist(resJson);
153+
done();
154+
}
155+
});
156+
});
157+
139158
it('should return attachment with downloadUrl', (done) => {
140159
models.ProjectAttachment.create({
141160
projectId: project1.id,
@@ -172,6 +191,7 @@ describe('GET Project', () => {
172191
.expect('Content-Type', /json/)
173192
.expect(200)
174193
.end((err, res) => {
194+
stub.restore();
175195
if (err) {
176196
done(err);
177197
} else {
@@ -181,7 +201,6 @@ describe('GET Project', () => {
181201
resJson.attachments.should.have.lengthOf(1);
182202
resJson.attachments[0].filePath.should.equal(attachment.filePath);
183203
resJson.attachments[0].downloadUrl.should.exist;
184-
stub.restore();
185204
done();
186205
}
187206
});

src/routes/projects/list-db.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ module.exports = [
123123
req.log.debug(criteria);
124124

125125
if (!memberOnly
126-
&& (util.hasRole(req, USER_ROLE.TOPCODER_ADMIN)
126+
&& (util.hasAdminRole(req)
127127
|| util.hasRole(req, USER_ROLE.MANAGER))) {
128128
// admins & topcoder managers can see all projects
129129
return retrieveProjects(req, criteria, sort, req.query.fields)

src/routes/projects/list-db.spec.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,5 +300,109 @@ describe('LIST Project db', () => {
300300
}
301301
});
302302
});
303+
304+
describe('for connect admin ', () => {
305+
it('should return the project ', (done) => {
306+
request(server)
307+
.get('/v4/projects/db/?fields=id%2Cmembers.id')
308+
.set({
309+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
310+
})
311+
.expect('Content-Type', /json/)
312+
.expect(200)
313+
.end((err, res) => {
314+
if (err) {
315+
done(err);
316+
} else {
317+
const resJson = res.body.result.content;
318+
should.exist(resJson);
319+
resJson.should.have.lengthOf(3);
320+
done();
321+
}
322+
});
323+
});
324+
325+
it('should return all projects that match when filtering by name', (done) => {
326+
request(server)
327+
.get('/v4/projects/db/?filter=keyword%3Dtest')
328+
.set({
329+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
330+
})
331+
.expect('Content-Type', /json/)
332+
.expect(200)
333+
.end((err, res) => {
334+
if (err) {
335+
done(err);
336+
} else {
337+
const resJson = res.body.result.content;
338+
should.exist(resJson);
339+
resJson.should.have.lengthOf(3);
340+
done();
341+
}
342+
});
343+
});
344+
345+
it('should return the project when filtering by keyword, which matches the name', (done) => {
346+
request(server)
347+
.get('/v4/projects/db/?filter=keyword%3D1')
348+
.set({
349+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
350+
})
351+
.expect('Content-Type', /json/)
352+
.expect(200)
353+
.end((err, res) => {
354+
if (err) {
355+
done(err);
356+
} else {
357+
const resJson = res.body.result.content;
358+
should.exist(resJson);
359+
resJson.should.have.lengthOf(1);
360+
resJson[0].name.should.equal('test1');
361+
done();
362+
}
363+
});
364+
});
365+
366+
it('should return the project when filtering by keyword, which matches the description', (done) => {
367+
request(server)
368+
.get('/v4/projects/db/?filter=keyword%3Dproject')
369+
.set({
370+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
371+
})
372+
.expect('Content-Type', /json/)
373+
.expect(200)
374+
.end((err, res) => {
375+
if (err) {
376+
done(err);
377+
} else {
378+
const resJson = res.body.result.content;
379+
should.exist(resJson);
380+
resJson.should.have.lengthOf(3);
381+
done();
382+
}
383+
});
384+
});
385+
386+
it('should return the project when filtering by keyword, which matches the details', (done) => {
387+
request(server)
388+
.get('/v4/projects/db/?filter=keyword%3Dcode')
389+
.set({
390+
Authorization: `Bearer ${testUtil.jwts.connectAdmin}`,
391+
})
392+
.expect('Content-Type', /json/)
393+
.expect(200)
394+
.end((err, res) => {
395+
if (err) {
396+
done(err);
397+
} else {
398+
const resJson = res.body.result.content;
399+
should.exist(resJson);
400+
resJson.should.have.lengthOf(1);
401+
resJson[0].name.should.equal('test1');
402+
done();
403+
}
404+
});
405+
});
406+
});
303407
});
304408
});

src/routes/projects/list.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ module.exports = [
214214
limit: Math.min(req.query.limit || 20, 20),
215215
offset: req.query.offset || 0,
216216
};
217-
req.log.debug(criteria);
217+
req.log.info(criteria);
218218

219219
if (!memberOnly
220-
&& (util.hasRole(req, USER_ROLE.TOPCODER_ADMIN)
220+
&& (util.hasAdminRole(req)
221221
|| util.hasRole(req, USER_ROLE.MANAGER))) {
222222
// admins & topcoder managers can see all projects
223223
return retrieveProjects(req, criteria, sort, req.query.fields)

0 commit comments

Comments
 (0)