Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle both Set and array for currentUser.authorities when checking interpretations access [DHIS2-15964] #1586

Closed
wants to merge 6 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,36 @@ import {
getCommentAccess,
} from '../getInterpretationAccess.js'

const superuser = {
const superuserD2CurrentUser = {
id: 'iamsuper',
authorities: new Set(['ALL']),
}

const userJoe = {
const userJoeD2CurrentUser = {
id: 'johndoe',
authorities: new Set(['Some']),
}

const userJane = {
const userJaneD2CurrentUser = {
id: 'jane',
authorities: new Set(['Some']),
}

const superuser = {
id: 'iamsuper',
authorities: ['ALL'],
}

const userJoe = {
id: 'johndoe',
authorities: ['Some'],
}

const userJane = {
id: 'jane',
authorities: ['Some'],
}

describe('interpretation and comment access', () => {
describe('getInterpretationAccess', () => {
it('returns true for all accesses for superuser', () => {
Expand Down Expand Up @@ -113,6 +128,234 @@ describe('interpretation and comment access', () => {
delete: false,
})
})

it('returns false for all accesses when no currentUser provided', () => {
const interpretation = {
access: {
write: false,
manage: false,
},
createdBy: userJane,
}

expect(getInterpretationAccess(interpretation)).toMatchObject({
share: false,
comment: false,
edit: false,
delete: false,
})
})

it('returns false for all accesses when currentUser missing authorities', () => {
const interpretation = {
access: {
write: false,
manage: false,
},
createdBy: userJane,
}

expect(
getInterpretationAccess(interpretation, {
id: 'usernoauthorties',
})
).toMatchObject({
share: false,
comment: false,
edit: false,
delete: false,
})
})
})

describe('getInterpretationAccess using D2.currentUser', () => {
it('returns true for all accesses for superuser', () => {
const interpretation = {
access: {
write: true,
manage: true,
},
createdBy: userJoeD2CurrentUser,
}

expect(
getInterpretationAccess(interpretation, superuserD2CurrentUser)
).toMatchObject({
share: true,
comment: true,
edit: true,
delete: true,
})
})
it('returns true for all accesses for creator', () => {
const interpretation = {
access: {
write: true,
manage: true,
},
createdBy: userJoeD2CurrentUser,
}

expect(
getInterpretationAccess(interpretation, userJoeD2CurrentUser)
).toMatchObject({
share: true,
comment: true,
edit: true,
delete: true,
})
})

it('returns false for edit/delete if user is not creator/superuser', () => {
const interpretation = {
access: {
write: true,
manage: true,
},
createdBy: userJaneD2CurrentUser,
}

expect(
getInterpretationAccess(interpretation, userJoeD2CurrentUser)
).toMatchObject({
share: true,
comment: true,
edit: false,
delete: false,
})
})

it('returns false for comment/edit/delete if user is not creator/superuser and no write access', () => {
const interpretation = {
access: {
write: false,
manage: true,
},
createdBy: userJaneD2CurrentUser,
}

expect(
getInterpretationAccess(interpretation, userJoeD2CurrentUser)
).toMatchObject({
share: true,
comment: false,
edit: false,
delete: false,
})
})

it('returns false for share/comment/edit/delete if user is not creator/superuser and no write or manage access', () => {
const interpretation = {
access: {
write: false,
manage: false,
},
createdBy: userJaneD2CurrentUser,
}

expect(
getInterpretationAccess(interpretation, userJoeD2CurrentUser)
).toMatchObject({
share: false,
comment: false,
edit: false,
delete: false,
})
})
})

describe('getCommentAccess using D2.currentUser', () => {
it('returns true for all accesses for superuser', () => {
const interpretation = {
access: {
write: true,
},
}

const comment = {
createdBy: userJoeD2CurrentUser,
}

expect(
getCommentAccess(
comment,
interpretation.access.write,
superuserD2CurrentUser
)
).toMatchObject({
edit: true,
delete: true,
})
})

it('returns true for all accesses for creator when interpretation has write access', () => {
const interpretation = {
access: {
write: true,
},
}

const comment = {
createdBy: userJoeD2CurrentUser,
}

expect(
getCommentAccess(
comment,
interpretation.access.write,
userJoeD2CurrentUser
)
).toMatchObject({
edit: true,
delete: true,
})
})

it('returns true for edit and false for delete for creator when interpretation does not have write access', () => {
const interpretation = {
access: {
write: false,
},
}

const comment = {
createdBy: userJoeD2CurrentUser,
}

expect(
getCommentAccess(
comment,
interpretation.access.write,
userJoeD2CurrentUser
)
).toMatchObject({
edit: true,
delete: false,
})
})

it('returns false for edit/delete for user who is not creator or superuser', () => {
const interpretation = {
access: {
write: true,
},
}

const comment = {
createdBy: userJaneD2CurrentUser,
}

expect(
getCommentAccess(
comment,
interpretation.access.write,
userJoeD2CurrentUser
)
).toMatchObject({
edit: false,
delete: false,
})
})
})

describe('getCommentAccess', () => {
Expand Down
13 changes: 12 additions & 1 deletion src/components/Interpretations/common/getInterpretationAccess.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { isArray } from 'lodash'
jenniferarnesen marked this conversation as resolved.
Show resolved Hide resolved

// For backwards compatibility
// accept both Set (from the old d2.currentUser object) and array
const isSuperuser = (authorities = []) => {
if (isArray(authorities)) {
return authorities.includes('ALL')
}
return authorities.has('ALL')
}
HendrikThePendric marked this conversation as resolved.
Show resolved Hide resolved

const isCreatorOrSuperuser = (object, currentUser) =>
object?.createdBy.id === currentUser?.id ||
currentUser?.authorities.has('ALL')
isSuperuser(currentUser?.authorities)

export const getInterpretationAccess = (interpretation, currentUser) => {
const canEditDelete = isCreatorOrSuperuser(interpretation, currentUser)
Expand Down
Loading