Bugzilla – Attachment 192887 Details for
Bug 10190
Overdue notice triggers based on item type
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 10190: feat: permissions
Bug-10190-feat-permissions.patch (text/plain), 13.76 KB, created by
ChloƩ Zermatten
on 2026-02-10 13:08:02 UTC
(
hide
)
Description:
Bug 10190: feat: permissions
Filename:
MIME Type:
Creator:
ChloƩ Zermatten
Created:
2026-02-10 13:08:02 UTC
Size:
13.76 KB
patch
obsolete
>From 27fdfafa229f6ca355de11bd9367ae26aba8f23e Mon Sep 17 00:00:00 2001 >From: Chloe Zermatten <chloe.zermatten@openfifth.co.uk> >Date: Fri, 30 Jan 2026 10:46:58 +0000 >Subject: [PATCH] Bug 10190: feat: permissions > >- add a config API endpoint to Circulations Triggers so permissions can be fetched >- update the permissions in the Vue App so that manage_circ_rules is required >- update the permissions in the Circulation Rules API so that manage_circ_rules is required for PUT operations >- update the circulation-rules store to so that it is compatible with recently intorduced compostables >- implement a redirect into the route so that permission requirements are honoured >--- > Koha/REST/V1/CirculationRules.pm | 21 +++++++++ > .../definitions/circulation_rules_config.yaml | 7 +++ > .../paths/circulation_rules_config.yaml | 39 ++++++++++++++++ > api/v1/swagger/swagger.yaml | 7 +++ > .../prog/en/modules/admin/admin-home.tt | 2 +- > .../js/fetch/circulation-rules-api-client.js | 9 ++++ > .../CirculationTriggersList.vue | 1 - > .../Admin/CirculationTriggers/Main.vue | 1 + > .../vue/modules/admin/circulation_triggers.ts | 30 ++++++++++-- > .../prog/js/vue/stores/circulation-rules.js | 46 ++++++++++++++----- > 10 files changed, 146 insertions(+), 17 deletions(-) > create mode 100644 api/v1/swagger/definitions/circulation_rules_config.yaml > create mode 100644 api/v1/swagger/paths/circulation_rules_config.yaml > >diff --git a/Koha/REST/V1/CirculationRules.pm b/Koha/REST/V1/CirculationRules.pm >index 7c2935cfb33..23f77a0681d 100644 >--- a/Koha/REST/V1/CirculationRules.pm >+++ b/Koha/REST/V1/CirculationRules.pm >@@ -316,4 +316,25 @@ sub _all_kinds { > return \@all_valid_kinds; > } > >+=head3 config >+ >+Return the configuration options needed for the Circulations Triggers Vue app >+ >+=cut >+ >+sub config { >+ my $c = shift->openapi->valid_input or return; >+ >+ my $patron = $c->stash('koha.user'); >+ my $userflags = C4::Auth::haspermission( $patron->userid ); >+ my $permissions = Koha::Auth::Permissions->get_authz_from_flags( { flags => $userflags } ); >+ >+ return $c->render( >+ status => 200, >+ openapi => { >+ permissions => $permissions, >+ }, >+ ); >+} >+ > 1; >diff --git a/api/v1/swagger/definitions/circulation_rules_config.yaml b/api/v1/swagger/definitions/circulation_rules_config.yaml >new file mode 100644 >index 00000000000..f9e71160cd1 >--- /dev/null >+++ b/api/v1/swagger/definitions/circulation_rules_config.yaml >@@ -0,0 +1,7 @@ >+--- >+type: object >+properties: >+ permissions: >+ type: object >+ description: List of permissions for the user >+additionalProperties: false >diff --git a/api/v1/swagger/paths/circulation_rules_config.yaml b/api/v1/swagger/paths/circulation_rules_config.yaml >new file mode 100644 >index 00000000000..a4624ff8111 >--- /dev/null >+++ b/api/v1/swagger/paths/circulation_rules_config.yaml >@@ -0,0 +1,39 @@ >+--- >+/circulation_rules/config: >+ get: >+ x-mojo-to: CirculationRules#config >+ operationId: getCirculationRulesConfig >+ description: This resource returns a list of options needed for the Circulation Triggers Vue app >+ summary: get the CirculationRules config >+ tags: >+ - circulation_rules_config >+ produces: >+ - application/json >+ responses: >+ 200: >+ description: The Circulation Rules config >+ schema: >+ $ref: "../swagger.yaml#/definitions/circulation_rules_config" >+ 400: >+ description: Bad request >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ 403: >+ description: Access forbidden >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ 500: >+ description: | >+ Internal server error. Possible `error_code` attribute values: >+ >+ * `internal_server_error` >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ 503: >+ description: Under maintenance >+ schema: >+ $ref: "../swagger.yaml#/definitions/error" >+ x-koha-authorization: >+ permissions: >+ - acquisition: '*' >+ - erm: 1 >diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml >index 9a9b7af7565..cecd4b26b7b 100644 >--- a/api/v1/swagger/swagger.yaml >+++ b/api/v1/swagger/swagger.yaml >@@ -16,6 +16,8 @@ definitions: > $ref: ./definitions/authorised_value_category.yaml > circulation_rules: > $ref: ./definitions/circulation_rules.yaml >+ circulation_rules_config: >+ $ref: ./definitions/circulation_rules_config.yaml > identity_provider: > $ref: ./definitions/identity_provider.yaml > identity_provider_domain: >@@ -323,6 +325,8 @@ paths: > $ref: ./paths/circulation_rules.yaml#/~1circulation_rules > /circulation_rules/kinds: > $ref: ./paths/circulation_rules.yaml#/~1circulation_rules~1kinds >+ /circulation_rules/config: >+ $ref: ./paths/circulation_rules_config.yaml#/~1circulation_rules~1config > /cities: > $ref: ./paths/cities.yaml#/~1cities > "/cities/{city_id}": >@@ -1239,6 +1243,9 @@ tags: > - description: "Manage circulation rules\n" > name: circulation_rules > x-displayName: Circulation rules >+ - description: "Retrieve configuration relevant to circulation rules\n" >+ name: circulation_rules_config >+ x-displayName: Circulation rules config > - description: "Manage cities\n" > name: cities > x-displayName: Cities >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index b6dc0040f07..7dcb68d22f0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -96,7 +96,7 @@ > <dt><a href="/cgi-bin/koha/admin/smart-rules.pl">Circulation and fine rules</a></dt> > <dd>Define circulation and fine rules for combinations of libraries, patron categories, and item types</dd> > [% END %] >- [% IF ( CAN_user_tools_edit_notice_status_triggers ) %] >+ [% IF ( CAN_user_parameters_manage_circ_rules ) %] > <dt><a href="/cgi-bin/koha/admin/circulation_triggers">Circulation triggers</a></dt> > <dd>Define triggers for circulation notices</dd> > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-rules-api-client.js b/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-rules-api-client.js >index ecf033db6fd..17b85bfa361 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-rules-api-client.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/fetch/circulation-rules-api-client.js >@@ -5,6 +5,15 @@ export class CircRuleAPIClient { > }); > } > >+ get config() { >+ return { >+ getAll: () => >+ this.httpClient.get({ >+ endpoint: "/config", >+ }), >+ }; >+ } >+ > get circ_rules() { > return { > getAll: (query, params, headers) => >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersList.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersList.vue >index 3060373d563..4f52ad12663 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersList.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/CirculationTriggersList.vue >@@ -288,7 +288,6 @@ import { storeToRefs } from "pinia"; > export default { > setup() { > const circRulesStore = inject("circRulesStore"); >- circRulesStore.init(); > const { > updateTriggerCount, > setAllRawRuleSets, >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue >index 9a05c2d347c..8c1b12f4527 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Admin/CirculationTriggers/Main.vue >@@ -29,6 +29,7 @@ import { inject } from "vue"; > export default { > setup() { > const circRulesStore = inject("circRulesStore"); >+ circRulesStore.init(); > letters.unshift({ > name: "No letter", > code: "", >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts >index f5e6a50c50b..10f31c85a23 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/admin/circulation_triggers.ts >@@ -51,7 +51,31 @@ app.provide("navigationStore", navigationStore); > app.provide("circRulesStore", circRulesStore); > app.mount("#__app"); > >-router.beforeEach(to => { >- navigationStore.$patch({ current: to.matched, params: to.params || {} }); >- removeMessages(); // This will actually flag the messages as displayed already >+router.beforeEach((to, from, next) => { >+ circRulesStore >+ .loadUserPermissions() >+ .then(() => { >+ if ( >+ !circRulesStore.isUserPermitted( >+ "CAN_user_parameters_manage_circ_rules" >+ ) >+ ) { >+ navigationStore.$patch({ >+ navigationBlocked: true, >+ currentPermission: null, >+ }); >+ removeMessages(); // This will actually flag the messages as displayed already >+ window.location.href = "/cgi-bin/koha/mainpage.pl"; >+ return; >+ } >+ navigationStore.$patch({ >+ current: to.matched, >+ params: to.params || {}, >+ }); >+ removeMessages(); // This will actually flag the messages as displayed already >+ next(); >+ }) >+ .catch(() => { >+ window.location.href = "/cgi-bin/koha/mainpage.pl"; >+ }); > }); >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js >index cf1004f2e35..56f03894135 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/circulation-rules.js >@@ -2,16 +2,19 @@ import { defineStore } from "pinia"; > import { $__ } from "../i18n"; > import { APIClient } from "../fetch/api-client.js"; > import { isEqual } from "lodash"; >+import { permissionsActions } from "../composables/permissions"; >+import { reactive, toRefs } from "vue"; > >-export const useCircRulesStore = defineStore("circRules", { >- // NOTES ON RULE SETS TYPES >- // exhaustive: includes 'pure fallback' rules sets for contexts that no rules match. >- // Format: [{overdue_X_<rule_name>: {value: mixed: isFallback: bool}}] >- // effective: includes sets only for contexts for which one or more rule exists in the db. These sets will include fallbacks. >- // Format: [{overdue_X_<rule_name>: <value>}} >- // raw: includes only the exact sets as they are found in the db >- // Format: [{overdue_X_<rule_name>: <value>}}] >- state: () => ({ >+// NOTES ON RULE SETS TYPES >+// exhaustive: includes 'pure fallback' rules sets for contexts that no rules match. >+// Format: [{overdue_X_<rule_name>: {value: mixed: isFallback: bool}}] >+// effective: includes sets only for contexts for which one or more rule exists in the db. These sets will include fallbacks. >+// Format: [{overdue_X_<rule_name>: <value>}} >+// raw: includes only the exact sets as they are found in the db >+// Format: [{overdue_X_<rule_name>: <value>}}] >+ >+export const useCircRulesStore = defineStore("circRules", () => { >+ const store = reactive({ > // context > currentLibraryId: "*", > currentPatronCategoryId: null, >@@ -21,6 +24,7 @@ export const useCircRulesStore = defineStore("circRules", { > itemTypes: [], > libraries: [], > patronCategories: [], >+ userPermissions: null, > letters: [], > ruleSuffixes: ["delay", "notice", "mtt", "restrict", "has_rules"], > transportTypes: [ >@@ -36,14 +40,21 @@ export const useCircRulesStore = defineStore("circRules", { > allExhaustiveEffectiveRuleSets: [], // main data set for display all applied rules for current library > currentAndDefaultRawRuleSets: [], // data set to identify effective rules from (combines allDefaultLibraryRawRuleSets and allCurrentLibraryRawRuleSets) > storeInitialized: false, >- }), >- actions: { >+ }); >+ >+ const actions = { > // controllers > async init() { > await this.getItemTypes(); > await this.getLibraries(); > await this.getPatronCategories(); > }, >+ async loadUserPermissions() { >+ if (this.userPermissions !== null) { >+ return; >+ } >+ await this.getConfigurationOptions(); >+ }, > // utilities > formatTriggerSpecificRuleSetForDisplay( > context, >@@ -403,6 +414,11 @@ export const useCircRulesStore = defineStore("circRules", { > throw e; > } > }, >+ async getConfigurationOptions() { >+ const client = APIClient.circRule; >+ const { permissions } = await client.config.getAll(); >+ this.userPermissions = permissions; >+ }, > async getItemTypes() { > const client = APIClient.item; > let itemTypes = []; >@@ -485,5 +501,11 @@ export const useCircRulesStore = defineStore("circRules", { > //TODO: handle e > } > }, >- }, >+ ...permissionsActions(store), >+ }; >+ >+ return { >+ ...toRefs(store), >+ ...actions, >+ }; > }); >-- >2.39.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 10190
:
170357
|
170358
|
170359
|
170360
|
170361
|
170362
|
170363
|
170364
|
170365
|
170366
|
170367
|
170368
|
170369
|
170370
|
170371
|
170372
|
170373
|
170374
|
170375
|
170376
|
170380
|
170449
|
171727
|
171728
|
171729
|
171730
|
171731
|
171732
|
171733
|
171734
|
171735
|
171736
|
171737
|
171738
|
171739
|
171740
|
171741
|
171742
|
171743
|
171744
|
171745
|
171746
|
171747
|
171748
|
171749
|
171750
|
171751
|
171752
|
171753
|
171754
|
171755
|
172588
|
172589
|
172590
|
172591
|
172592
|
172593
|
172594
|
172595
|
172596
|
172597
|
172598
|
172599
|
172600
|
172601
|
172602
|
172603
|
172604
|
172605
|
172606
|
172607
|
172608
|
172609
|
172612
|
172614
|
172617
|
172619
|
172621
|
172622
|
172623
|
172624
|
172625
|
172626
|
172630
|
172631
|
172632
|
172633
|
172634
|
172635
|
172636
|
172637
|
172638
|
172639
|
172640
|
172641
|
172642
|
172643
|
172644
|
172645
|
172646
|
172647
|
172648
|
172649
|
172650
|
172651
|
172652
|
172653
|
172654
|
172655
|
172656
|
172657
|
172658
|
172659
|
172660
|
172661
|
172662
|
172663
|
178643
|
178644
|
178645
|
178646
|
178647
|
178648
|
178649
|
178650
|
178651
|
178652
|
178653
|
178654
|
178655
|
178656
|
178657
|
178658
|
178659
|
178660
|
178661
|
178662
|
178663
|
178664
|
178665
|
178666
|
178667
|
178668
|
178669
|
178670
|
178671
|
178672
|
178673
|
178674
|
178675
|
188075
|
188076
|
188077
|
188078
|
188079
|
188080
|
188081
|
188082
|
188083
|
188084
|
188085
|
188086
|
188087
|
188088
|
188476
|
189345
|
189863
|
189864
|
189865
|
189866
|
189867
|
189868
|
191749
|
191750
|
191751
|
191752
|
191753
|
191754
|
191755
|
191756
|
191757
|
191758
|
191759
|
191760
|
191761
|
191762
|
191763
|
191795
|
191796
|
191805
|
191854
|
191873
|
192871
|
192872
|
192873
|
192874
|
192875
|
192876
|
192877
|
192878
|
192879
|
192880
|
192881
|
192882
|
192883
|
192884
|
192885
|
192886
| 192887 |
192888
|
192889
|
192890
|
192891
|
192892
|
192893
|
192894
|
192895
|
192896
|
192897
|
192898
|
192899