diff --git a/Koha/REST/V1/CirculationRules.pm b/Koha/REST/V1/CirculationRules.pm
index 7c2935cfb3..23f77a0681 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 0000000000..f9e71160cd
--- /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 0000000000..a4624ff811
--- /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 2304f7330e..b2497735f7 100644
--- a/api/v1/swagger/swagger.yaml
+++ b/api/v1/swagger/swagger.yaml
@@ -18,6 +18,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:
@@ -355,6 +357,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}":
@@ -1340,6 +1344,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 11666cae17..96937fadfe 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 @@
Circulation and fine rules
Define circulation and fine rules for combinations of libraries, patron categories, and item types
[% END %]
- [% IF ( CAN_user_tools_edit_notice_status_triggers ) %]
+ [% IF ( CAN_user_parameters_manage_circ_rules ) %]
Circulation triggers
Define triggers for circulation notices
[% 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 ecf033db6f..17b85bfa36 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 3060373d56..4f52ad1266 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 9a05c2d347..8c1b12f452 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 f5e6a50c50..10f31c85a2 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 cf1004f2e3..56f0389413 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_: {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_: }}
- // raw: includes only the exact sets as they are found in the db
- // Format: [{overdue_X_: }}]
- state: () => ({
+// NOTES ON RULE SETS TYPES
+// exhaustive: includes 'pure fallback' rules sets for contexts that no rules match.
+// Format: [{overdue_X_: {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_: }}
+// raw: includes only the exact sets as they are found in the db
+// Format: [{overdue_X_: }}]
+
+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,
+ };
});