@ministryofjustice/hmpps-prison-permissions-lib 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Please use this to capture reasoning behind changes:
4
4
 
5
+ ## 2.3.0
6
+
7
+ Adding an extra option `readOnly` to the `PermissionsService` which defaults to `false`. When set to `true`, this
8
+ will only grant read permissions. This allows a service to configure itself as read-only if required. This was initially
9
+ required by the Prisoner Profile to display a read-only view of duplicate prisoner profiles.
10
+
11
+ ## 2.2.1
12
+
13
+ Minor dependency update
14
+
5
15
  ## 2.2.0
6
16
 
7
17
  Introduced permissions for the Prisoner Moves domain. The first couple of permissions added are
@@ -9,20 +19,31 @@ Introduced permissions for the Prisoner Moves domain. The first couple of permis
9
19
  follow the base checks and just require additional roles.
10
20
 
11
21
  # 2.1.0
12
- Adds the sensitive edits role to the edit_contacts permission so users can edit Next of Kin and Emergency contacts in the prisoner profile without requiring Contacts Administrator or Authoriser roles.
22
+
23
+ Adds the sensitive edits role to the edit_contacts permission so users can edit Next of Kin and Emergency contacts in
24
+ the prisoner profile without requiring Contacts Administrator or Authoriser roles.
13
25
 
14
26
  # 2.0.1
15
- Fixes incorrect usage of `previousPrisonId` and `previousPrisonLeavingDate` when checking contacts read permissions. These are only used in the context of transfers, not releases. The correct ones now in use are `lastPrisonId` and `releaseDate`.
27
+
28
+ Fixes incorrect usage of `previousPrisonId` and `previousPrisonLeavingDate` when checking contacts read permissions.
29
+ These are only used in the context of transfers, not releases. The correct ones now in use are `lastPrisonId` and
30
+ `releaseDate`.
16
31
 
17
32
  # 2.0.0
18
- Replaced contacts read permissions check with one that handles released prisoners differently. Checks for current prisoners are unaffected.
33
+
34
+ Replaced contacts read permissions check with one that handles released prisoners differently. Checks for current
35
+ prisoners are unaffected.
19
36
 
20
37
  To be permitted to read contacts for released prisoners:
21
- - the user's roles must include `InactiveBookings` and one or both of the following: `ContactsAdministrator, ContactsAuthoriser`
38
+
39
+ - the user's roles must include `InactiveBookings` and one or both of the following:
40
+ `ContactsAdministrator, ContactsAuthoriser`
22
41
  - the prisoner must have been released within the last 3 years (`PermissionCheckStatus.EXCEEDS_TIME_RESTRICTION`)
23
42
  - the previous prison of the prisoner must match the user's caseload
24
43
 
25
- These changes were requested by the contacts team after noticing the 'External Contacts' widget was not showing on the prisoner profiles of released prisoners. This was due to a caseload mismatch, as the assigned caseload for released prisoners is 'OUT'.
44
+ These changes were requested by the contacts team after noticing the 'External Contacts' widget was not showing on the
45
+ prisoner profiles of released prisoners. This was due to a caseload mismatch, as the assigned caseload for released
46
+ prisoners is 'OUT'.
26
47
 
27
48
  ## 1.1.2
28
49
 
package/README.md CHANGED
@@ -79,6 +79,7 @@ The permissions service should be created just like any other of your services.
79
79
  * `logger`: Bunyan logger for logging permissions events. Defaults to using `console`.
80
80
  * `telemetryClient`: Optional but recommended. Instead of just logging permissions events, this provides richer metadata
81
81
  to Application Insights.
82
+ * `readOnly`: Optional boolean (defaults to false) which, if set to true, will only grant read permissions.
82
83
 
83
84
  e.g.
84
85
 
package/dist/index.cjs CHANGED
@@ -14,6 +14,7 @@ exports.PermissionCheckStatus = void 0;
14
14
  PermissionCheckStatus["EXCEEDS_TIME_RESTRICTION"] = "EXCEEDS_TIME_RESTRICTION";
15
15
  PermissionCheckStatus["ROLE_NOT_PRESENT"] = "ROLE_NOT_PRESENT";
16
16
  PermissionCheckStatus["NOT_PRISON_USER"] = "NOT_PRISON_USER";
17
+ PermissionCheckStatus["READ_ONLY"] = "READ_ONLY";
17
18
  PermissionCheckStatus["OK"] = "OK";
18
19
  })(exports.PermissionCheckStatus || (exports.PermissionCheckStatus = {}));
19
20
 
@@ -244,12 +245,15 @@ const baseCheckConditions = {
244
245
  const baseCheckStatus = (user, prisoner) => getPermissionStatus(user, prisoner, baseCheckConditions);
245
246
 
246
247
  const matchBaseCheckAnd = (additionalConditions) => (permission, context) => {
247
- const { user, prisoner, baseCheckStatus } = context;
248
+ const { user, prisoner, baseCheckStatus, readOnly } = context;
248
249
  const baseCheckPassed = baseCheckStatus === exports.PermissionCheckStatus.OK;
249
- const permissionStatus = getPermissionStatus(user, prisoner, {
250
- ...baseCheckConditions,
251
- ...additionalConditions,
252
- });
250
+ const readOnlyCheckPassed = readOnly ? permission.endsWith(':read') : true;
251
+ const permissionStatus = readOnlyCheckPassed
252
+ ? getPermissionStatus(user, prisoner, {
253
+ ...baseCheckConditions,
254
+ ...additionalConditions,
255
+ })
256
+ : exports.PermissionCheckStatus.READ_ONLY;
253
257
  const permissionCheckPassed = baseCheckPassed && permissionStatus === exports.PermissionCheckStatus.OK;
254
258
  if (!permissionCheckPassed)
255
259
  logDeniedPermissionCheck(permission, context, permissionStatus);
@@ -321,8 +325,8 @@ function prisonerAdjudicationsCheck(context) {
321
325
 
322
326
  exports.PrisonerIncentivesPermission = void 0;
323
327
  (function (PrisonerIncentivesPermission) {
324
- PrisonerIncentivesPermission["read_incentive_level"] = "prisoner:prisoner-incentives:read_incentive_level";
325
- PrisonerIncentivesPermission["read_incentive_level_history"] = "prisoner:prisoner-incentives:read_incentive_level_history";
328
+ PrisonerIncentivesPermission["read_incentive_level"] = "prisoner:incentives:incentive-level:read";
329
+ PrisonerIncentivesPermission["read_incentive_level_history"] = "prisoner:incentives:incentive-level-history:read";
326
330
  })(exports.PrisonerIncentivesPermission || (exports.PrisonerIncentivesPermission = {}));
327
331
 
328
332
  const incentiveLevelHistoryReadCheck = matchBaseCheckAnd({
@@ -907,12 +911,14 @@ function probationCheck(context) {
907
911
  exports.PersonInterventionsPermission = void 0;
908
912
  (function (PersonInterventionsPermission) {
909
913
  PersonInterventionsPermission["read_csip"] = "prisoner:csip:read";
914
+ PersonInterventionsPermission["edit_csip"] = "prisoner:csip:edit";
910
915
  })(exports.PersonInterventionsPermission || (exports.PersonInterventionsPermission = {}));
911
916
 
912
917
  function personInterventionsCheck(context) {
913
918
  const check = checkWith(context);
914
919
  return {
915
920
  ...check(exports.PersonInterventionsPermission.read_csip, inUsersCaseLoad),
921
+ ...check(exports.PersonInterventionsPermission.edit_csip, inUsersCaseLoad),
916
922
  };
917
923
  }
918
924
 
@@ -950,12 +956,14 @@ function personPlanAndNeedsCheck(context) {
950
956
  class PermissionsService {
951
957
  prisonerSearchClient;
952
958
  permissionsLogger;
953
- static create({ prisonerSearchConfig, authenticationClient, logger = console, telemetryClient, }) {
954
- return new PermissionsService(new PrisonerSearchClient(logger, prisonerSearchConfig, authenticationClient), new PermissionsLogger(logger, telemetryClient));
959
+ readOnly;
960
+ static create({ prisonerSearchConfig, authenticationClient, logger = console, telemetryClient, readOnly = false, }) {
961
+ return new PermissionsService(new PrisonerSearchClient(logger, prisonerSearchConfig, authenticationClient), new PermissionsLogger(logger, telemetryClient), readOnly);
955
962
  }
956
- constructor(prisonerSearchClient, permissionsLogger) {
963
+ constructor(prisonerSearchClient, permissionsLogger, readOnly) {
957
964
  this.prisonerSearchClient = prisonerSearchClient;
958
965
  this.permissionsLogger = permissionsLogger;
966
+ this.readOnly = readOnly;
959
967
  }
960
968
  getPrisonerPermissions({ user, prisoner, requestDependentOn, }) {
961
969
  const context = {
@@ -964,6 +972,7 @@ class PermissionsService {
964
972
  baseCheckStatus: baseCheckStatus(user, prisoner),
965
973
  requestDependentOn,
966
974
  permissionsLogger: this.permissionsLogger,
975
+ readOnly: this.readOnly,
967
976
  };
968
977
  return {
969
978
  [exports.PrisonerBasePermission.read]: baseCheck(exports.PrisonerBasePermission.read, context),
@@ -1202,6 +1211,7 @@ const probationDomainPermissionPaths = {
1202
1211
  // eslint-disable-next-line import/prefer-default-export
1203
1212
  const personInterventionsPermissionPaths = {
1204
1213
  [exports.PersonInterventionsPermission.read_csip]: `domainGroups.interventions.personInterventions.${exports.PersonInterventionsPermission.read_csip}`,
1214
+ [exports.PersonInterventionsPermission.edit_csip]: `domainGroups.interventions.personInterventions.${exports.PersonInterventionsPermission.edit_csip}`,
1205
1215
  };
1206
1216
 
1207
1217
  // eslint-disable-next-line import/prefer-default-export