Skip to content

Commit

Permalink
Fix permissions for member and profile API calls
Browse files Browse the repository at this point in the history
  • Loading branch information
kamicut committed Nov 29, 2021
1 parent c7f4068 commit 5eb5bb0
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 67 deletions.
2 changes: 1 addition & 1 deletion app/manage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function manageRouter (nextApp) {
router.get('/api/my/teams', can('public:authenticated'), listMyTeams)
router.post('/api/teams', can('public:authenticated'), createTeam)
router.get('/api/teams/:id', can('team:view'), getTeam)
router.get('/api/teams/:id/members', can('team:view'), getTeamMembers)
router.get('/api/teams/:id/members', can('team:view-members'), getTeamMembers)
router.put('/api/teams/:id', can('team:edit'), updateTeam)
router.delete('/api/teams/:id', can('team:edit'), destroyTeam)
router.put('/api/teams/add/:id/:osmId', can('team:edit'), addMember)
Expand Down
1 change: 1 addition & 0 deletions app/manage/permissions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const keyPermissions = {
const teamPermissions = {
'team:edit': require('./edit-team'),
'team:view': require('./view-team'),
'team:view-members': require('./view-team-members'),
'team:join': require('./join-team'),
'team:member': require('./member-team')
}
Expand Down
24 changes: 24 additions & 0 deletions app/manage/permissions/view-team-members.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const { isPublic, isMember } = require('../../lib/team')

/**
* team:view-members
*
* To view a team's members, the team needs to be either public
* or the user should be a member of the team
*
* @param {string} uid user id
* @param {Object} params request parameters
* @returns {boolean} can the request go through?
*/
async function viewTeamMembers (uid, { id }) {
const publicTeam = await isPublic(id)
if (publicTeam) return publicTeam

try {
return await isMember(id, uid)
} catch (e) {
return false
}
}

module.exports = viewTeamMembers
20 changes: 5 additions & 15 deletions app/manage/permissions/view-team.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
const { isPublic, isMember } = require('../../lib/team')

/**
* team:view
*
* To view a team, the team needs to be either public
* or the user should be a member of the team
* This covers team metadata, this should always be available
* to any users. Permission for individual pieces of metadata are controlled within
* the route code.
*
* @param {string} uid user id
* @param {Object} params request parameters
* @returns {boolean} can the request go through?
*/
async function viewTeam (uid, { id }) {
const publicTeam = await isPublic(id)
if (publicTeam) return publicTeam

try {
return await isMember(id, uid)
} catch (e) {
return false
}
async function viewTeam () {
return true
}

module.exports = viewTeam
8 changes: 8 additions & 0 deletions components/edit-team-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ export default function EditTeamForm ({ initialValues, onSubmit, staff, isCreate
<small className='pt1'>URL to your team's editing policy if you have one (include http/https)</small>
{errors.editing_policy && renderError(errors.editing_policy)}
</div>
<div className='form-control form-control__vertical'>
<label htmlFor='privacy'>Privacy</label>
<Field as='select' name='privacy'>
<option value='public'>Public</option>
<option value='private'>Private</option>
</Field>
<small className='pt1'>A private team does not show its member list or team details to non-members.</small>
</div>
{ staff && isCreateForm
? (
<div className='form-control form-control__vertical'>
Expand Down
10 changes: 5 additions & 5 deletions lib/profiles-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ export async function deleteAttribute (id) {
}

/**
* getUserOrgrofile
* get the profile of a user in a team
* getUserOrgProfile
* get the profile of a user in a org
*/
export async function getUserOrgProfile (orgId, userId) {
const res = await fetch(join(URL, 'organizations', `${orgId}`, `${userId}`), {
Expand All @@ -114,7 +114,7 @@ export async function getUserOrgProfile (orgId, userId) {
})
if (res.status === 200) {
return res.json()
} if (res.status === 404) {
} if (res.status === 404 || res.status === 401) {
return []
} else {
const err = new Error('could not retrieve profile')
Expand All @@ -136,7 +136,7 @@ export async function getUserTeamProfile (teamId, userId) {
})
if (res.status === 200) {
return res.json()
} if (res.status === 404) {
} if (res.status === 404 || res.status === 401) {
return []
} else {
const err = new Error('could not retrieve profile')
Expand Down Expand Up @@ -242,7 +242,7 @@ export async function getTeamProfile (id) {
})
if (res.status === 200) {
return res.json()
} if (res.status === 404) {
} if (res.status === 404 || res.status === 401) {
return []
} else {
const err = new Error('could not retrieve profile')
Expand Down
8 changes: 6 additions & 2 deletions lib/teams-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export async function createOrgTeam (orgId, data) {
* Get team details from the API
*
* @param id - id of team
* @returns {Object} - team details + moderators + members
* @returns {Object} - team details
*/
export async function getTeam (id) {
let res = await fetch(join(URL, `${id}`))
Expand Down Expand Up @@ -124,7 +124,11 @@ export async function getTeamMembers (id) {
let res = await fetch(join(URL, `${id}`, 'members'))
if (res.status === 200) {
return res.json()
} else {
}
if (res.status === 401) { // If unauthorized, don't display team members
return { members: [], moderators: []}
}
else {
const err = new Error('could not retrieve team members')
err.status = res.status
throw err
Expand Down
95 changes: 51 additions & 44 deletions pages/team.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ export default class Team extends Component {
const { id } = this.props
try {
let team = await getTeam(id)
let teamMembers = await getTeamMembers(id)
let teamProfile = await getTeamProfile(id)
let teamMembers = { moderators: [], members: [] }
let teamProfile = []
teamMembers = await getTeamMembers(id)
teamProfile = await getTeamProfile(id)
this.setState({
team,
teamProfile,
Expand Down Expand Up @@ -193,7 +195,7 @@ export default class Team extends Component {
}
}

if (!team || !teamMembers) return null
if (!team) return null

const userId = this.props.user.uid
const members = map(prop('id'), teamMembers.members)
Expand Down Expand Up @@ -291,48 +293,53 @@ export default class Team extends Component {
</Card>
</div>
<div className='team__table'>
<Section>
<div className='section-actions'>
<SectionHeader>Team Members</SectionHeader>
<div>
{ isUserModerator && (
<AddMemberForm
onSubmit={async ({ osmId }) => {
await addMember(team.id, osmId)
return this.getTeam()
}}
{
(team.privacy === 'public' || isMember) ? (
<Section>
<div className='section-actions'>
<SectionHeader>Team Members</SectionHeader>
<div>
{isUserModerator && (
<AddMemberForm
onSubmit={async ({ osmId }) => {
await addMember(team.id, osmId)
return this.getTeam()
}}
/>
)}
</div>
</div>
<Table
rows={memberRows}
columns={columns}
onRowClick={
(row) => {
this.openProfileModal(row)
}
}
/>
<Modal style={{
content: {
maxWidth: '400px',
maxHeight: '400px',
left: 'calc(50% - 200px)',
top: 'calc(50% - 200px)'
},
overlay: {
zIndex: 10000
}
}} isOpen={this.state.modalIsOpen}>
<ProfileModal
user={this.state.profileMeta}
attributes={this.state.profileInfo}
onClose={this.closeProfileModal}
actions={profileActions}
/>
)}
</div>
</div>
<Table
rows={memberRows}
columns={columns}
onRowClick={
(row) => {
this.openProfileModal(row)
}
}
/>
<Modal style={{
content: {
maxWidth: '400px',
maxHeight: '400px',
left: 'calc(50% - 200px)',
top: 'calc(50% - 200px)'
},
overlay: {
zIndex: 10000
}
}} isOpen={this.state.modalIsOpen}>
<ProfileModal
user={this.state.profileMeta}
attributes={this.state.profileInfo}
onClose={this.closeProfileModal}
actions={profileActions}
/>
</Modal>
</Section>
</Modal>
</Section>
)
: <div />
}
</div>
<style jsx>
{`
Expand Down

0 comments on commit 5eb5bb0

Please sign in to comment.