Skip to content

Commit 350732b

Browse files
committed
feat(Norppa): Add support for feedbackLiaison special group
1 parent 6bde10e commit 350732b

File tree

3 files changed

+119
-10
lines changed

3 files changed

+119
-10
lines changed

src/auth/IAMConfig.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const ANY = 'ANY'
77
/**
88
* Map from jory IAM to one or more programmes
99
*/
10-
const joryMap = {
10+
const joryMap: Record<string, string | string[]> = {
1111
'grp-avoin-johto': 'H930',
1212
'grp-kielikeskus-esihenkilot': 'H906', // note, all will be given kojo in kojomap
1313
'hy-ttdk-tuk-jory': '100-K001',
@@ -429,6 +429,8 @@ const hyOneGroups = ['hy-one'] // opintoasiainneuvosto
429429

430430
const employeeGroups = ['hy-employees']
431431

432+
const feedbackLiaisonGroups = ['hy-palautevastaavat']
433+
432434
const oodikoneIams = [
433435
'grp-oodikone-users',
434436
'grp-oodikone-basic-users',
@@ -466,6 +468,8 @@ const isHyOneIam = (iam) => hyOneGroups.includes(iam)
466468

467469
const isJoryIam = (iam) => joryGroups.includes(iam)
468470

471+
const isFeedbackLiaisonIam = (iam) => feedbackLiaisonGroups.includes(iam)
472+
469473
const isKosuIam = (iam) => kosuGroups.includes(iam)
470474

471475
const isUniversityWideIam = (iam) => universityWideGroups.includes(iam)
@@ -489,7 +493,7 @@ const isStudyLeaderGroup = (iam, allIams) => {
489493
})
490494
}
491495

492-
const iamToOrganisationCode = (iam) => {
496+
const joryIamToOrganisationCode = (iam) => {
493497
const organisationCodes = joryMap[iam]
494498
if (Array.isArray(organisationCodes)) {
495499
return organisationCodes
@@ -539,6 +543,7 @@ const relevantIAMs = new Set(
539543
hyOneGroups,
540544
employeeGroups,
541545
oodikoneIams,
546+
feedbackLiaisonGroups,
542547
katselmusViewerIams,
543548
].flat(),
544549
)
@@ -568,10 +573,11 @@ export {
568573
isDoctoralIam,
569574
isEmployeeIam,
570575
iamToDoctoralSchool,
571-
iamToOrganisationCode,
576+
joryIamToOrganisationCode,
572577
kosuIamToFaculties,
573578
dekaaniIamToFaculty,
574579
iamToFaculty,
580+
isFeedbackLiaisonIam,
575581
opetusVaradekaani,
576582
isStudyLeaderGroup,
577583
relevantIAMs,

src/auth/IAMRights.ts

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
isKosuIam,
88
isUniversityWideIam,
99
isDoctoralIam,
10-
iamToOrganisationCode,
10+
isFeedbackLiaisonIam,
11+
joryIamToOrganisationCode,
1112
isEmployeeIam,
1213
iamToDoctoralSchool,
1314
kosuIamToFaculties,
@@ -22,7 +23,7 @@ import { Programme } from '../organisation/types'
2223

2324
type AccessSpecialGroupFunction = (hyGroups: string[]) => {
2425
access?: { [programmeCode: string]: OrganisationAccess }
25-
specialGroup?: { [key: string]: boolean }
26+
specialGroup?: { [key: string]: boolean | string[] }
2627
}
2728

2829
/**
@@ -55,7 +56,7 @@ const getSuperAdmin: AccessSpecialGroupFunction = (hyGroups) => {
5556
}
5657

5758
/**
58-
* NOT USED
59+
* NOT USED (wait is this used?)
5960
* Grant admin rights if the user has correct iams (eg. grp-ospa)
6061
* @returns admin special group
6162
*/
@@ -106,6 +107,26 @@ const getJory: AccessSpecialGroupFunction = (hyGroups) => {
106107
return {}
107108
}
108109

110+
/**
111+
* Needed primarily for Norppa
112+
* Grant feedback liaison special group if the user has feedback liaison iam AND jory iam
113+
* The feedbackLiaison special group contains a list of programme keys that the user is jory in
114+
* @returns feedback liaison special group
115+
*/
116+
const getFeedbackLiaison: AccessSpecialGroupFunction = (hyGroups) => {
117+
const isFeedbackLiaison = hyGroups.some(isFeedbackLiaisonIam)
118+
119+
const joryIams = hyGroups.filter(isJoryIam)
120+
const joryProgrammes = joryIams
121+
.map(joryIamToOrganisationCode)
122+
.flatMap((codes) => codes.map(mapToDegreeCode))
123+
124+
if (isFeedbackLiaison && joryProgrammes.length > 0) {
125+
return { specialGroup: { feedbackLiaison: joryProgrammes } }
126+
}
127+
return {}
128+
}
129+
109130
/**
110131
* Needed for Oodikone
111132
* Grant kosu special group if the user has kosu iams (eg. hy-ypa-opa-kosu-kumpula)
@@ -125,7 +146,15 @@ const getKosu: AccessSpecialGroupFunction = (hyGroups) => {
125146
const getSpecialGroups: AccessSpecialGroupFunction = (hyGroups) => {
126147
let specialGroup = {}
127148

128-
;[getAdmin, getSuperAdmin, getOpenUni, getHyOne, getJory, getKosu]
149+
;[
150+
getAdmin,
151+
getSuperAdmin,
152+
getOpenUni,
153+
getHyOne,
154+
getJory,
155+
getKosu,
156+
getFeedbackLiaison,
157+
]
129158
.map((f) => f(hyGroups))
130159
.forEach(({ specialGroup: newSpecialGroup }) => {
131160
specialGroup = { ...specialGroup, ...newSpecialGroup }
@@ -230,7 +259,7 @@ const getDoctoralSchoolAccess: AccessSpecialGroupFunction = (hyGroups) => {
230259
const getProgrammeAdminAccess: AccessSpecialGroupFunction = (hyGroups) => {
231260
const orgCodes = hyGroups
232261
.filter((iam) => isStudyLeaderGroup(iam, hyGroups))
233-
.map((iam) => iamToOrganisationCode(iam))
262+
.map((iam) => joryIamToOrganisationCode(iam))
234263
.filter(Boolean)
235264

236265
const degreeCodes = orgCodes.flatMap((codes) => codes.map(mapToDegreeCode))
@@ -257,7 +286,7 @@ const getProgrammeAdminAccess: AccessSpecialGroupFunction = (hyGroups) => {
257286
const getProgrammeWriteAccess: AccessSpecialGroupFunction = (hyGroups) => {
258287
if (!hyGroups.some(isEmployeeIam)) return {}
259288
const orgCodes = hyGroups
260-
.map((iam) => iamToOrganisationCode(iam))
289+
.map((iam) => joryIamToOrganisationCode(iam))
261290
.filter(Boolean)
262291
const degreeCodes = orgCodes.flatMap((codes) => codes.map(mapToDegreeCode))
263292
const access = {}
@@ -274,7 +303,7 @@ const getProgrammeWriteAccess: AccessSpecialGroupFunction = (hyGroups) => {
274303
*/
275304
const getProgrammeReadAccess: AccessSpecialGroupFunction = (hyGroups) => {
276305
const orgCodes = hyGroups
277-
.map((iam) => iamToOrganisationCode(iam))
306+
.map((iam) => joryIamToOrganisationCode(iam))
278307
.filter(Boolean)
279308
const degreeCodes = orgCodes.flatMap((codes) => codes.map(mapToDegreeCode))
280309
const access = {}

tests/norppa.spec.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { api } from './util/utils'
3+
4+
describe.concurrent('Norppa', () => {
5+
it('Feedback liaisons special group granted to user with feedback liaison iam and jory iam', async () => {
6+
const res = await api.post('', {
7+
userId: 'tkt-norppa-haba',
8+
iamGroups: ['hy-mltdk-tkt-jory', 'hy-palautevastaavat'],
9+
})
10+
11+
expect(res.status).toBe(200)
12+
13+
const access = await res.json()
14+
15+
const specialGroup = access.specialGroup
16+
17+
expect(specialGroup).toHaveProperty('feedbackLiaison')
18+
expect(specialGroup.feedbackLiaison).toHaveLength(1)
19+
expect(specialGroup.feedbackLiaison).toContain('KH50_005')
20+
})
21+
22+
it('Feedback liaisons special group not granted to user with only jory iam', async () => {
23+
const res = await api.post('', {
24+
userId: 'tkt-norppa-haba',
25+
iamGroups: ['hy-mltdk-tkt-jory'],
26+
})
27+
28+
expect(res.status).toBe(200)
29+
30+
const access = await res.json()
31+
32+
const specialGroup = access.specialGroup
33+
34+
expect(specialGroup).not.toHaveProperty('feedbackLiaison')
35+
})
36+
37+
it('Feedback liaisons special group not granted to user with only feedback liaison iam', async () => {
38+
const res = await api.post('', {
39+
userId: 'tkt-norppa-haba',
40+
iamGroups: ['hy-palautevastaavat'],
41+
})
42+
43+
expect(res.status).toBe(200)
44+
45+
const access = await res.json()
46+
47+
const specialGroup = access.specialGroup
48+
49+
expect(specialGroup).not.toHaveProperty('feedbackLiaison')
50+
})
51+
52+
it('Feedback liaisons special group contains programme codes of each programme where user is in jory', async () => {
53+
const res = await api.post('', {
54+
userId: 'tkt-norppa-haba',
55+
iamGroups: [
56+
'hy-ltdk-psyk-jory', // ['300-K001', '300-M004']
57+
'hy-ltdk-ll-jory', // '300-M001'
58+
'hy-palautevastaavat',
59+
],
60+
})
61+
62+
expect(res.status).toBe(200)
63+
64+
const access = await res.json()
65+
66+
const specialGroup = access.specialGroup
67+
68+
expect(specialGroup).toHaveProperty('feedbackLiaison')
69+
expect(specialGroup.feedbackLiaison).toHaveLength(3)
70+
expect(specialGroup.feedbackLiaison).toContain('KH30_001')
71+
expect(specialGroup.feedbackLiaison).toContain('MH30_004')
72+
expect(specialGroup.feedbackLiaison).toContain('MH30_001')
73+
})
74+
})

0 commit comments

Comments
 (0)