Skip to content

Commit f79bd90

Browse files
committed
Edit team permission now includes owner of org
1 parent 8c30f30 commit f79bd90

File tree

4 files changed

+88
-10
lines changed

4 files changed

+88
-10
lines changed

app/lib/organization.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ async function createOrgTeam (organizationId, data, osmId) {
165165
return conn.transaction(async trx => {
166166
const record = await team.create(data, osmId, trx)
167167
await trx('organization_team').insert({ team_id: record.id, organization_id: organizationId })
168+
return record
168169
})
169170
}
170171

app/lib/team.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,20 @@ async function isPublic (teamId) {
332332
return (privacy === 'public')
333333
}
334334

335+
/**
336+
* associatedOrg
337+
*
338+
* If the team is part of an org, return its associated org
339+
* @param teamId - team id
340+
* @returns {int} organization id or null
341+
*/
342+
async function associatedOrg (teamId) {
343+
if (!teamId) throw new Error('team id is required as first argument')
344+
345+
const conn = await db()
346+
return unpack(conn('organization_team').where('team_id', teamId).returning('organization_id'))
347+
}
348+
335349
module.exports = {
336350
get,
337351
list,
@@ -349,5 +363,6 @@ module.exports = {
349363
isModerator,
350364
isMember,
351365
isPublic,
352-
resolveMemberNames
366+
resolveMemberNames,
367+
associatedOrg
353368
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1-
const { isModerator } = require('../../lib/team')
1+
const { isModerator, associatedOrg } = require('../../lib/team')
2+
const { isOwner } = require('../../lib/organization')
23

34
/**
45
* team:update
56
*
67
* To update a team, the authenticated user needs to
7-
* be a moderator of the team
8+
* be a moderator of the team or an owner of the organization
9+
* that the team is associated to
810
*
911
* @param {string} uid user id
1012
* @param {Object} params request parameters
1113
* @returns {boolean} can the request go through?
1214
*/
1315
async function updateTeam (uid, { id }) {
14-
return isModerator(id, uid)
16+
// user has to be authenticated
17+
if (!uid) return false
18+
19+
// check if user is an owner of this team through an organization
20+
const org = await associatedOrg(id)
21+
const ownerOfTeam = org && (await isOwner(org.organization_id, uid))
22+
23+
return ownerOfTeam || isModerator(id, uid)
1524
}
1625

1726
module.exports = updateTeam

app/tests/permissions/update-team.test.js

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ test.before(async () => {
1717

1818
// stub hydra introspect
1919
let introspectStub = sinon.stub(hydra, 'introspect')
20-
introspectStub.withArgs('validToken').returns({
20+
introspectStub.withArgs('user100').returns({
2121
active: true,
2222
sub: '100'
2323
})
24-
introspectStub.withArgs('differentUser').returns({
24+
introspectStub.withArgs('user101').returns({
2525
active: true,
2626
sub: '101'
2727
})
@@ -39,11 +39,11 @@ test.after.always(async () => {
3939
test('a team moderator can update a team', async t => {
4040
let res = await agent.post('/api/teams')
4141
.send({ name: 'road team 1' })
42-
.set('Authorization', `Bearer validToken`)
42+
.set('Authorization', `Bearer user100`)
4343
.expect(200)
4444

4545
let res2 = await agent.put(`/api/teams/${res.body.id}`)
46-
.set('Authorization', `Bearer validToken`)
46+
.set('Authorization', `Bearer user100`)
4747
.send({ name: 'building team 1' })
4848

4949
t.is(res2.status, 200)
@@ -52,12 +52,65 @@ test('a team moderator can update a team', async t => {
5252
test('a non-team moderator cannot update a team', async t => {
5353
let res = await agent.post('/api/teams')
5454
.send({ name: 'road team 2' })
55-
.set('Authorization', `Bearer validToken`)
55+
.set('Authorization', `Bearer user100`)
5656
.expect(200)
5757

5858
let res2 = await agent.put(`/api/teams/${res.body.id}`)
59-
.set('Authorization', `Bearer differentUser`)
59+
.set('Authorization', `Bearer user101`)
6060
.send({ name: 'building team 2' })
6161

6262
t.is(res2.status, 401)
6363
})
64+
65+
test('an org team can be updated by the the org manager', async t => {
66+
// Let's create an organization, user100 is the owner
67+
const res = await agent.post('/api/organizations')
68+
.send({ name: 'org manager can update team' })
69+
.set('Authorization', `Bearer user100`)
70+
.expect(200)
71+
72+
// Let's set user101 to be a manager of this organization and create a
73+
// team in the organization
74+
await agent.put(`/api/organizations/${res.body.id}/addManager/101`)
75+
.set('Authorization', `Bearer user100`)
76+
.expect(200)
77+
78+
const res2 = await agent.post(`/api/organizations/${res.body.id}/teams`)
79+
.send({ name: 'org team can be updated by manager - team' })
80+
.set('Authorization', `Bearer user101`)
81+
.expect(200)
82+
83+
// Use the manager to update the team
84+
const res3 = await agent.put(`/api/teams/${res2.body.id}`)
85+
.send({ name: 'org team can be updated by manager - team2' })
86+
.set('Authorization', `Bearer user101`)
87+
88+
t.is(res3.status, 200)
89+
})
90+
91+
test('an org team can be updated by the owner of the org', async t => {
92+
// Let's create an organization, user100 is the owner
93+
const res = await agent.post('/api/organizations')
94+
.send({ name: 'org owner can update team' })
95+
.set('Authorization', `Bearer user100`)
96+
.expect(200)
97+
98+
// Let's set user101 to be a manager of this organization and create a
99+
// team in the organization
100+
await agent.put(`/api/organizations/${res.body.id}/addManager/101`)
101+
.set('Authorization', `Bearer user100`)
102+
.expect(200)
103+
104+
const res2 = await agent.post(`/api/organizations/${res.body.id}/teams`)
105+
.send({ name: 'org team can be updated by owner - team' })
106+
.set('Authorization', `Bearer user101`)
107+
.expect(200)
108+
109+
// user101 is the moderator and manager, but user100 should be able
110+
// to edit this team
111+
const res3 = await agent.put(`/api/teams/${res2.body.id}`)
112+
.send({ name: 'org team can be updated by owner - team2' })
113+
.set('Authorization', `Bearer user100`)
114+
115+
t.is(res3.status, 200)
116+
})

0 commit comments

Comments
 (0)