mirror of https://github.com/Lissy93/dashy.git
🔀 Merge pull request #691 from pinarruiz/feature/extend-visibility-items
[FEATURE] Extend visibility to section items
This commit is contained in:
commit
ef786dbb7c
|
@ -48,10 +48,10 @@ Once authentication is enabled, so long as there is no valid token in cookie sto
|
||||||
With authentication setup, by default no access is allowed to your dashboard without first logging in with valid credentials. Guest mode can be enabled to allow for read-only access to a secured dashboard by any user, without the need to log in. A guest user cannot write any changes to the config file, but can apply modifications locally (stored in their browser). You can enable guest access, by setting `appConfig.auth.enableGuestAccess: true`.
|
With authentication setup, by default no access is allowed to your dashboard without first logging in with valid credentials. Guest mode can be enabled to allow for read-only access to a secured dashboard by any user, without the need to log in. A guest user cannot write any changes to the config file, but can apply modifications locally (stored in their browser). You can enable guest access, by setting `appConfig.auth.enableGuestAccess: true`.
|
||||||
|
|
||||||
### Granular Access
|
### Granular Access
|
||||||
You can use the following properties to make certain sections only visible to some users, or hide sections from guests.
|
You can use the following properties to make certain sections or items only visible to some users, or hide sections and items from guests.
|
||||||
- `hideForUsers` - Section will be visible to all users, except for those specified in this list
|
- `hideForUsers` - Section or Item will be visible to all users, except for those specified in this list
|
||||||
- `showForUsers` - Section will be hidden from all users, except for those specified in this list
|
- `showForUsers` - Section or Item will be hidden from all users, except for those specified in this list
|
||||||
- `hideForGuests` - Section will be visible for logged in users, but not for guests
|
- `hideForGuests` - Section or Item will be visible for logged in users, but not for guests
|
||||||
|
|
||||||
For Example:
|
For Example:
|
||||||
|
|
||||||
|
@ -71,7 +71,9 @@ For Example:
|
||||||
displayData:
|
displayData:
|
||||||
hideForGuests: true
|
hideForGuests: true
|
||||||
items:
|
items:
|
||||||
...
|
- title: Hide Me
|
||||||
|
displayData:
|
||||||
|
hideForUsers: [alicia, bob]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Permissions
|
### Permissions
|
||||||
|
@ -149,9 +151,9 @@ appConfig:
|
||||||
Note that if you are using Keycloak V 17 or older, you will also need to set `legacySupport: true` (also under `appConfig.auth.keycloak`). This is because the API endpoint was updated in later versions.
|
Note that if you are using Keycloak V 17 or older, you will also need to set `legacySupport: true` (also under `appConfig.auth.keycloak`). This is because the API endpoint was updated in later versions.
|
||||||
|
|
||||||
### 4. Add groups and roles (Optional)
|
### 4. Add groups and roles (Optional)
|
||||||
Keycloak allows you to assign users roles and groups. You can use these values to configure who can access various sections in Dashy.
|
Keycloak allows you to assign users roles and groups. You can use these values to configure who can access various sections or items in Dashy.
|
||||||
Keycloak server administration and configuration is a deep topic; please refer to the [server admin guide](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-and-access-using-roles-and-groups) to see details about creating and assigning roles and groups.
|
Keycloak server administration and configuration is a deep topic; please refer to the [server admin guide](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-and-access-using-roles-and-groups) to see details about creating and assigning roles and groups.
|
||||||
Once you have groups or roles assigned to users you can configure access under each sections `displayData.showForKeycloakUser` and `displayData.hideForKeycloakUser`.
|
Once you have groups or roles assigned to users you can configure access under each section or item `displayData.showForKeycloakUser` and `displayData.hideForKeycloakUser`.
|
||||||
Both show and hide configurations accept a list of `groups` and `roles` that limit access. If a users data matches one or more items in these lists they will be allowed or excluded as defined.
|
Both show and hide configurations accept a list of `groups` and `roles` that limit access. If a users data matches one or more items in these lists they will be allowed or excluded as defined.
|
||||||
```yaml
|
```yaml
|
||||||
sections:
|
sections:
|
||||||
|
@ -161,6 +163,11 @@ sections:
|
||||||
roles: ['canViewDevResources']
|
roles: ['canViewDevResources']
|
||||||
hideForKeycloakUsers:
|
hideForKeycloakUsers:
|
||||||
groups: ['ProductTeam']
|
groups: ['ProductTeam']
|
||||||
|
items:
|
||||||
|
- title: Not Visible for developers
|
||||||
|
displayData:
|
||||||
|
hideForKeycloakUsers:
|
||||||
|
groups: ['DevelopmentTeam']
|
||||||
```
|
```
|
||||||
|
|
||||||
Depending on how you're hosting Dashy and Keycloak, you may also need to set some HTTP headers, to prevent a CORS error. This would typically be the `Access-Control-Allow-Origin [URL-of Dashy]` on your Keycloak instance. See the [Setting Headers](https://github.com/Lissy93/dashy/blob/master/docs/management.md#setting-headers) guide in the management docs for more info.
|
Depending on how you're hosting Dashy and Keycloak, you may also need to set some HTTP headers, to prevent a CORS error. This would typically be the `Access-Control-Allow-Origin [URL-of Dashy]` on your Keycloak instance. See the [Setting Headers](https://github.com/Lissy93/dashy/blob/master/docs/management.md#setting-headers) guide in the management docs for more info.
|
||||||
|
|
|
@ -36,10 +36,12 @@ The following file provides a reference of all supported configuration options.
|
||||||
- [`keycloak`](#appconfigauthkeycloak-optional) - Auth config for Keycloak
|
- [`keycloak`](#appconfigauthkeycloak-optional) - Auth config for Keycloak
|
||||||
- [**`sections`**](#section) - List of sections
|
- [**`sections`**](#section) - List of sections
|
||||||
- [`displayData`](#sectiondisplaydata-optional) - Section display settings
|
- [`displayData`](#sectiondisplaydata-optional) - Section display settings
|
||||||
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-and-sectiondisplaydatashowforkeycloakusers) - Set user controls
|
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
|
||||||
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for a section
|
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for a section
|
||||||
- [`items`](#sectionitem) - List of items
|
- [`items`](#sectionitem) - List of items
|
||||||
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for an item
|
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for an item
|
||||||
|
- [`displayData`](#itemdisplaydata-optional) - Item display settings
|
||||||
|
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
|
||||||
- [`widgets`](#sectionwidget-optional) - List of widgets
|
- [`widgets`](#sectionwidget-optional) - List of widgets
|
||||||
- [**Notes**](#notes)
|
- [**Notes**](#notes)
|
||||||
- [Editing Config through the UI](#editing-config-through-the-ui)
|
- [Editing Config through the UI](#editing-config-through-the-ui)
|
||||||
|
@ -224,9 +226,24 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||||
**`color`** | `string` | _Optional_ | An optional color for the text and font-awesome icon to be displayed in. Note that this will override the current theme and so may not display well
|
**`color`** | `string` | _Optional_ | An optional color for the text and font-awesome icon to be displayed in. Note that this will override the current theme and so may not display well
|
||||||
**`backgroundColor`** | `string` | _Optional_ | An optional background fill color for the that given item. Again, this will override the current theme and so might not display well against the background
|
**`backgroundColor`** | `string` | _Optional_ | An optional background fill color for the that given item. Again, this will override the current theme and so might not display well against the background
|
||||||
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
|
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
|
||||||
|
**`displayData`** | `object` | _Optional_ | Meta-data to optionally overide display settings for a given item. See [`displayData`](#itemdisplaydata-optional)
|
||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
|
|
||||||
|
### `item.displayData` _(optional)_
|
||||||
|
|
||||||
|
**Field** | **Type** | **Required**| **Description**
|
||||||
|
--- | --- | --- | ---
|
||||||
|
**`hideForUsers`** | `string[]` | _Optional_ | Current item will be visible to all users, except for those specified in this list
|
||||||
|
**`showForUsers`** | `string[]` | _Optional_ | Current item will be hidden from all users, except for those specified in this list
|
||||||
|
**`hideForGuests`** | `boolean` | _Optional_ | Current item will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
|
||||||
|
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current item will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
|
||||||
|
**`showForKeycloakUsers`** | `object` | _Optional_ | Current item will be hidden from all keycloak users, except for those configured via these groups and roles. See `showForKeycloakUsers`
|
||||||
|
|
||||||
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
|
|
||||||
### `section.widget` _(optional)_
|
### `section.widget` _(optional)_
|
||||||
|
|
||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
|
@ -259,7 +276,7 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||||
**`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list
|
**`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list
|
||||||
**`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
|
**`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
|
||||||
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current section will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
|
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current section will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
|
||||||
**`showForKeycloakUsers`** | `object` | _Optional_ | Current section will be hidden from all keyclaok users, except for those configured via these groups and roles. See `showForKeycloakUsers`
|
**`showForKeycloakUsers`** | `object` | _Optional_ | Current section will be hidden from all keycloak users, except for those configured via these groups and roles. See `showForKeycloakUsers`
|
||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
|
@ -271,12 +288,12 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
### `section.displayData.hideForKeycloakUsers` and `section.displayData.showForKeycloakUsers`
|
### `section.displayData.hideForKeycloakUsers`, `section.displayData.showForKeycloakUsers`, `item.displayData.hideForKeycloakUsers` and `item.displayData.showForKeycloakUsers`
|
||||||
|
|
||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
--- |------------| --- | ---
|
--- |------------| --- | ---
|
||||||
**`groups`** | `string[]` | _Optional_ | Current Section will be hidden or shown based on the user having any of the groups in this list
|
**`groups`** | `string[]` | _Optional_ | Current Section or Item will be hidden or shown based on the user having any of the groups in this list
|
||||||
**`roles`** | `string[]` | _Optional_ | Current Section will be hidden or shown based on the user having any of the roles in this list
|
**`roles`** | `string[]` | _Optional_ | Current Section or Item will be hidden or shown based on the user having any of the roles in this list
|
||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<transition name="slide">
|
<transition name="slide">
|
||||||
<SideBarSection
|
<SideBarSection
|
||||||
v-if="isOpen[index]"
|
v-if="isOpen[index]"
|
||||||
:items="section.items"
|
:items="filterTiles(section.items)"
|
||||||
@launch-app="launchApp"
|
@launch-app="launchApp"
|
||||||
/>
|
/>
|
||||||
</transition>
|
</transition>
|
||||||
|
@ -36,6 +36,7 @@ import SideBarItem from '@/components/Workspace/SideBarItem.vue';
|
||||||
import SideBarSection from '@/components/Workspace/SideBarSection.vue';
|
import SideBarSection from '@/components/Workspace/SideBarSection.vue';
|
||||||
import IconHome from '@/assets/interface-icons/application-home.svg';
|
import IconHome from '@/assets/interface-icons/application-home.svg';
|
||||||
import IconMinimalView from '@/assets/interface-icons/application-minimal.svg';
|
import IconMinimalView from '@/assets/interface-icons/application-minimal.svg';
|
||||||
|
import { checkItemVisibility } from '@/utils/CheckItemVisibility';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SideBar',
|
name: 'SideBar',
|
||||||
|
@ -77,6 +78,13 @@ export default {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/* Return a list with visible items on a section to the user or guest */
|
||||||
|
filterTiles(allTiles) {
|
||||||
|
if (!allTiles) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return allTiles.filter((tile) => checkItemVisibility(tile));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.sections.length === 1) { // If only 1 section, go ahead and open it
|
if (this.sections.length === 1) { // If only 1 section, go ahead and open it
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import Defaults, { localStorageKeys, iconCdns } from '@/utils/defaults';
|
import Defaults, { localStorageKeys, iconCdns } from '@/utils/defaults';
|
||||||
import Keys from '@/utils/StoreMutations';
|
import Keys from '@/utils/StoreMutations';
|
||||||
import { searchTiles } from '@/utils/Search';
|
import { searchTiles } from '@/utils/Search';
|
||||||
|
import { checkItemVisibility } from '@/utils/CheckItemVisibility';
|
||||||
|
|
||||||
const HomeMixin = {
|
const HomeMixin = {
|
||||||
props: {
|
props: {
|
||||||
|
@ -64,8 +65,11 @@ const HomeMixin = {
|
||||||
},
|
},
|
||||||
/* Returns only the tiles that match the users search query */
|
/* Returns only the tiles that match the users search query */
|
||||||
filterTiles(allTiles) {
|
filterTiles(allTiles) {
|
||||||
if (!allTiles) return [];
|
if (!allTiles) {
|
||||||
return searchTiles(allTiles, this.searchValue);
|
return [];
|
||||||
|
}
|
||||||
|
const visibleTiles = allTiles.filter((tile) => checkItemVisibility(tile));
|
||||||
|
return searchTiles(visibleTiles, this.searchValue);
|
||||||
},
|
},
|
||||||
/* Checks if any sections or items use icons from a given CDN */
|
/* Checks if any sections or items use icons from a given CDN */
|
||||||
checkIfIconLibraryNeeded(prefix) {
|
checkIfIconLibraryNeeded(prefix) {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* A helper function that checks if an item is visible based on current users permissions
|
||||||
|
* Checks an item displayData for hideForUsers, showForUsers and hideForGuests
|
||||||
|
* Returns a boolean that determines if the user has the required permissions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Import helper functions from auth, to get current user, and check if guest
|
||||||
|
import { getCurrentUser, isLoggedInAsGuest } from '@/utils/Auth';
|
||||||
|
import { isVisibleToUser } from '@/utils/IsVisibleToUser';
|
||||||
|
|
||||||
|
/* Putting it all together, the function to export */
|
||||||
|
export const checkItemVisibility = (item) => {
|
||||||
|
const currentUser = getCurrentUser(); // Get current user object
|
||||||
|
const isGuest = isLoggedInAsGuest(); // Check if current user is a guest
|
||||||
|
const displayData = item.displayData || {};
|
||||||
|
return isVisibleToUser(displayData, currentUser, isGuest);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default checkItemVisibility;
|
|
@ -6,80 +6,15 @@
|
||||||
|
|
||||||
// Import helper functions from auth, to get current user, and check if guest
|
// Import helper functions from auth, to get current user, and check if guest
|
||||||
import { getCurrentUser, isLoggedInAsGuest } from '@/utils/Auth';
|
import { getCurrentUser, isLoggedInAsGuest } from '@/utils/Auth';
|
||||||
import { localStorageKeys } from '@/utils/defaults';
|
import { isVisibleToUser } from '@/utils/IsVisibleToUser';
|
||||||
|
|
||||||
/* Helper function, checks if a given testValue is found in the visibility list */
|
|
||||||
const determineVisibility = (visibilityList, testValue) => {
|
|
||||||
let isFound = false;
|
|
||||||
visibilityList.forEach((visibilityItem) => {
|
|
||||||
if (visibilityItem.toLowerCase() === testValue.toLowerCase()) isFound = true;
|
|
||||||
});
|
|
||||||
return isFound;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Helper function, determines if two arrays have any intersecting elements
|
|
||||||
(one or more items that are the same) */
|
|
||||||
const determineIntersection = (source = [], target = []) => {
|
|
||||||
const intersections = source.filter(item => target.indexOf(item) !== -1);
|
|
||||||
return intersections.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Returns false if this section should not be rendered for the current user/ guest */
|
|
||||||
const isSectionVisibleToUser = (displayData, currentUser, isGuest) => {
|
|
||||||
// Checks if user explicitly has access to a certain section
|
|
||||||
const checkVisibility = () => {
|
|
||||||
if (!currentUser) return true;
|
|
||||||
const hideForUsers = displayData.hideForUsers || [];
|
|
||||||
const cUsername = currentUser.user.toLowerCase();
|
|
||||||
return !determineVisibility(hideForUsers, cUsername);
|
|
||||||
};
|
|
||||||
// Checks if user is explicitly prevented from viewing a certain section
|
|
||||||
const checkHiddenability = () => {
|
|
||||||
if (!currentUser) return true;
|
|
||||||
const cUsername = currentUser.user.toLowerCase();
|
|
||||||
const showForUsers = displayData.showForUsers || [];
|
|
||||||
if (showForUsers.length < 1) return true;
|
|
||||||
return determineVisibility(showForUsers, cUsername);
|
|
||||||
};
|
|
||||||
const checkKeycloakVisibility = () => {
|
|
||||||
if (!displayData.hideForKeycloakUsers) return true;
|
|
||||||
|
|
||||||
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
|
|
||||||
const hideForGroups = displayData.hideForKeycloakUsers.groups || [];
|
|
||||||
const hideForRoles = displayData.hideForKeycloakUsers.roles || [];
|
|
||||||
|
|
||||||
return !(determineIntersection(hideForRoles, roles)
|
|
||||||
|| determineIntersection(hideForGroups, groups));
|
|
||||||
};
|
|
||||||
const checkKeycloakHiddenability = () => {
|
|
||||||
if (!displayData.showForKeycloakUsers) return true;
|
|
||||||
|
|
||||||
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
|
|
||||||
const showForGroups = displayData.showForKeycloakUsers.groups || [];
|
|
||||||
const showForRoles = displayData.showForKeycloakUsers.roles || [];
|
|
||||||
|
|
||||||
return determineIntersection(showForRoles, roles)
|
|
||||||
|| determineIntersection(showForGroups, groups);
|
|
||||||
};
|
|
||||||
// Checks if the current user is a guest, and if section allows for guests
|
|
||||||
const checkIfHideForGuest = () => {
|
|
||||||
const hideForGuest = displayData.hideForGuests;
|
|
||||||
return !(hideForGuest && isGuest);
|
|
||||||
};
|
|
||||||
return checkVisibility()
|
|
||||||
&& checkHiddenability()
|
|
||||||
&& checkIfHideForGuest()
|
|
||||||
&& checkKeycloakVisibility()
|
|
||||||
&& checkKeycloakHiddenability();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Putting it all together, the function to export */
|
/* Putting it all together, the function to export */
|
||||||
const checkSectionVisibility = (sections) => {
|
export const checkSectionVisibility = (sections) => {
|
||||||
const currentUser = getCurrentUser(); // Get current user object
|
const currentUser = getCurrentUser(); // Get current user object
|
||||||
const isGuest = isLoggedInAsGuest(); // Check if current user is a guest
|
const isGuest = isLoggedInAsGuest(); // Check if current user is a guest
|
||||||
return sections.filter((currentSection) => {
|
return sections.filter((currentSection) => {
|
||||||
const displayData = currentSection.displayData || {};
|
const displayData = currentSection.displayData || {};
|
||||||
return isSectionVisibleToUser(displayData, currentUser, isGuest);
|
return isVisibleToUser(displayData, currentUser, isGuest);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -778,6 +778,90 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The destination to navigate to when item is clicked, expressed as a valid URL, IP or hostname"
|
"description": "The destination to navigate to when item is clicked, expressed as a valid URL, IP or hostname"
|
||||||
},
|
},
|
||||||
|
"displayData": {
|
||||||
|
"title": "Display Data",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Optional meta data for customizing an item",
|
||||||
|
"properties": {
|
||||||
|
"hideForUsers": {
|
||||||
|
"title": "Hide for Users",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be visible to all users, except for those specified in this list",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Username for the user that will not be able to view this item"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"showForUsers": {
|
||||||
|
"title": "Show for Users",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be hidden from all users, except for those specified in this list",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Username for the user that will have access to this item"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hideForGuests": {
|
||||||
|
"title": "Hide for Guests?",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "If set to true, item will be visible for logged in users, but not for guests"
|
||||||
|
},
|
||||||
|
"showForKeycloakUsers": {
|
||||||
|
"title": "Show for select Keycloak groups or roles",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Configure the Keycloak groups or roles that will have access to this item",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"groups": {
|
||||||
|
"title": "Show for Groups",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be hidden from all users except those with one or more of these groups",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the group that will be able to view this item"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"title": "Show for Roles",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be hidden from all users except those with one or more of these roles",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the role that will be able to view this item"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hideForKeycloakUsers": {
|
||||||
|
"title": "Hide for select Keycloak groups or roles",
|
||||||
|
"type": "object",
|
||||||
|
"description": "Configure the Keycloak groups or roles that will not have access to this item",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"groups": {
|
||||||
|
"title": "Hide for Groups",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be hidden from users with any of these groups",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the group that will not be able to view this item"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"title": "Hide for Roles",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Item will be hidden from users with any of roles",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the role that will not be able to view this item"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"target": {
|
"target": {
|
||||||
"title": "Opening Method",
|
"title": "Opening Method",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* A helper function that filters all the sections or an item based on current users permissions
|
||||||
|
* Checks each sections displayData for hideForUsers, showForUsers and hideForGuests
|
||||||
|
* Returns an array of sections that the current logged in user has permissions for
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Import helper functions from auth, to get current user, and check if guest
|
||||||
|
import { localStorageKeys } from '@/utils/defaults';
|
||||||
|
|
||||||
|
/* Helper function, checks if a given testValue is found in the visibility list */
|
||||||
|
const determineVisibility = (visibilityList, testValue) => {
|
||||||
|
let isFound = false;
|
||||||
|
visibilityList.forEach((visibilityItem) => {
|
||||||
|
if (visibilityItem.toLowerCase() === testValue.toLowerCase()) isFound = true;
|
||||||
|
});
|
||||||
|
return isFound;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Helper function, determines if two arrays have any intersecting elements
|
||||||
|
(one or more items that are the same) */
|
||||||
|
const determineIntersection = (source = [], target = []) => {
|
||||||
|
const intersections = source.filter(item => target.indexOf(item) !== -1);
|
||||||
|
return intersections.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Returns false if the displayData of a section/item
|
||||||
|
should not be rendered for the current user/ guest */
|
||||||
|
export const isVisibleToUser = (displayData, currentUser, isGuest) => {
|
||||||
|
// Checks if user explicitly has access to a certain section
|
||||||
|
const checkVisibility = () => {
|
||||||
|
if (!currentUser) return true;
|
||||||
|
const hideForUsers = displayData.hideForUsers || [];
|
||||||
|
const cUsername = currentUser.user.toLowerCase();
|
||||||
|
return !determineVisibility(hideForUsers, cUsername);
|
||||||
|
};
|
||||||
|
// Checks if user is explicitly prevented from viewing a certain section/item
|
||||||
|
const checkHiddenability = () => {
|
||||||
|
if (!currentUser) return true;
|
||||||
|
const cUsername = currentUser.user.toLowerCase();
|
||||||
|
const showForUsers = displayData.showForUsers || [];
|
||||||
|
if (showForUsers.length < 1) return true;
|
||||||
|
return determineVisibility(showForUsers, cUsername);
|
||||||
|
};
|
||||||
|
const checkKeycloakVisibility = () => {
|
||||||
|
if (!displayData.hideForKeycloakUsers) return true;
|
||||||
|
|
||||||
|
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
|
||||||
|
const hideForGroups = displayData.hideForKeycloakUsers.groups || [];
|
||||||
|
const hideForRoles = displayData.hideForKeycloakUsers.roles || [];
|
||||||
|
|
||||||
|
return !(determineIntersection(hideForRoles, roles)
|
||||||
|
|| determineIntersection(hideForGroups, groups));
|
||||||
|
};
|
||||||
|
const checkKeycloakHiddenability = () => {
|
||||||
|
if (!displayData.showForKeycloakUsers) return true;
|
||||||
|
|
||||||
|
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
|
||||||
|
const showForGroups = displayData.showForKeycloakUsers.groups || [];
|
||||||
|
const showForRoles = displayData.showForKeycloakUsers.roles || [];
|
||||||
|
|
||||||
|
return determineIntersection(showForRoles, roles)
|
||||||
|
|| determineIntersection(showForGroups, groups);
|
||||||
|
};
|
||||||
|
// Checks if the current user is a guest, and if section/item allows for guests
|
||||||
|
const checkIfHideForGuest = () => {
|
||||||
|
const hideForGuest = displayData.hideForGuests;
|
||||||
|
return !(hideForGuest && isGuest);
|
||||||
|
};
|
||||||
|
return checkVisibility()
|
||||||
|
&& checkHiddenability()
|
||||||
|
&& checkIfHideForGuest()
|
||||||
|
&& checkKeycloakVisibility()
|
||||||
|
&& checkKeycloakHiddenability();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isVisibleToUser;
|
Loading…
Reference in New Issue