Skip to content

Commit

Permalink
Merge pull request #5 from k2maan/user-management/#3
Browse files Browse the repository at this point in the history
Implemented: UI for user details page (#3)
  • Loading branch information
ravilodhi authored Oct 27, 2023
2 parents bff7672 + abff3eb commit 1cb94f4
Show file tree
Hide file tree
Showing 33 changed files with 8,785 additions and 5,041 deletions.
11,456 changes: 6,586 additions & 4,870 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,30 @@
"i18n:report": "vue-cli-service i18n:report --src \"./src/**/*.?(js|vue)\" --locales \"./src/locales/**/*.json\""
},
"dependencies": {
"boon-js": "^2.0.3",
"@capacitor/android": "^2.4.7",
"@capacitor/core": "^2.4.7",
"@casl/ability": "^6.0.0",
"@hotwax/app-version-info": "^1.0.0",
"@hotwax/apps-theme": "^1.1.0",
"@hotwax/oms-api": "^1.6.0",
"@hotwax/dxp-components": "^1.9.1",
"@hotwax/oms-api": "^1.11.0",
"@ionic/core": "6.7.5",
"@ionic/vue": "6.7.5",
"@ionic/vue-router": "6.7.5",
"core-js": "^3.6.5",
"luxon": "^3.2.0",
"mitt": "^2.1.0",
"register-service-worker": "^1.7.1",
"vue": "^3.2.26",
"vue-i18n": "~9.1.6",
"vue-logger-plugin": "^2.2.3",
"vue-router": "^4.0.12",
"vuex": "^4.0.1",
"vuex-persistedstate": "^4.0.0-beta.3"
},
"devDependencies": {
"@capacitor/cli": "^2.4.7",
"@intlify/vue-i18n-loader": "^2.1.0",
"@types/jest": "^27.5.0",
"@types/luxon": "^3.2.0",
"@typescript-eslint/eslint-plugin": "~5.26.0",
"@typescript-eslint/parser": "~5.26.0",
"@vue/cli-plugin-babel": "~4.5.0",
Expand All @@ -53,7 +55,6 @@
"eslint-plugin-vue": "^8.0.3",
"jest": "^28.1.0",
"ts-jest": "^28.0.8",
"typescript": "~4.7.4",
"vue-cli-plugin-i18n": "^1.0.1"
"typescript": "~4.7.4"
}
}
5 changes: 3 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import emitter from "@/event-bus"
import { mapGetters, useStore } from 'vuex';
import { initialise, resetConfig } from '@/adapter'
import { useRouter } from 'vue-router';
import { translate } from '@hotwax/dxp-components';
export default defineComponent({
name: 'App',
Expand All @@ -33,7 +34,7 @@ export default defineComponent({
if (!this.loader) {
this.loader = await loadingController
.create({
message: this.$t("Click the backdrop to dismiss."),
message: translate("Click the backdrop to dismiss."),
translucent: true,
backdropDismiss: true
});
Expand Down Expand Up @@ -77,7 +78,7 @@ export default defineComponent({
async mounted() {
this.loader = await loadingController
.create({
message: this.$t("Click the backdrop to dismiss."),
message: translate("Click the backdrop to dismiss."),
translucent: true,
backdropDismiss: true
});
Expand Down
14 changes: 8 additions & 6 deletions src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import {
api,
client,
fetchProducts,
getConfig,
hasError,
initialise,
isError,
Product,
logout,
resetConfig,
setUserLocale,
updateToken,
updateInstanceUrl
} from '@hotwax/oms-api'

export {
api,
client,
fetchProducts,
getConfig,
hasError,
initialise,
isError,
Product,
logout,
resetConfig,
setUserLocale,
updateToken,
updateInstanceUrl
}
1 change: 1 addition & 0 deletions src/authorization/Actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {}
1 change: 1 addition & 0 deletions src/authorization/Rules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {} as any
124 changes: 124 additions & 0 deletions src/authorization/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { AbilityBuilder, PureAbility } from '@casl/ability';
import { getEvaluator, parse } from 'boon-js';
import { Tokens } from 'boon-js/lib/types'

// TODO Improve this
// We will move this code to an external plugin and use below Actions and Rules accordlingly
let Actions = {} as any;
let Rules = {} as any;

// We are using CASL library to define permissions.
// Instead of using Action-Subject based authorisation we are going with Claim based Authorization.
// We would be defining the permissions for each action and case, map with server permissiosn based upon certain rules.
// https://casl.js.org/v5/en/cookbook/claim-authorization
// Following the comment of Sergii Stotskyi, author of CASL
// https://github.com/stalniy/casl/issues/525
// We are defining a PureAbility and creating an instance with AbilityBuilder.
type ClaimBasedAbility = PureAbility<string>;
const { build } = new AbilityBuilder<ClaimBasedAbility>(PureAbility);
const ability = build();

/**
* The method returns list of permissions required for the rules. We are having set of rules,
* through which app permissions are defined based upon the server permissions.
* When getting server permissions, as all the permissions are not be required.
* Specific permissions used defining the rules are extracted and sent to server.
* @returns permissions
*/
const getServerPermissionsFromRules = () => {
// Iterate for each rule
const permissions = Object.keys(Rules).reduce((permissions: any, rule: any) => {
const permissionRule = Rules[rule];
// some rules may be empty, no permission is required from server
if (permissionRule) {
// Each rule may have multiple permissions along with operators
// Boon js parse rules into tokens, each token may be operator or server permission
// permissionId will have token name as identifier.
const permissionTokens = parse(permissionRule);
permissions = permissionTokens.reduce((permissions: any, permissionToken: any) => {
// Token object with name as identifier has permissionId
if (Tokens.IDENTIFIER === permissionToken.name) {
permissions.add(permissionToken.value);
}
return permissions;
}, permissions)
}
return permissions;
}, new Set())
return [...permissions];
}

/**
* The method is used to prepare app permissions from the server permissions.
* Rules could be defined such that each app permission could be defined based upon certain one or more server permissions.
* @param serverPermissions
* @returns appPermissions
*/
const prepareAppPermissions = (serverPermissions: any) => {
const serverPermissionsInput = serverPermissions.reduce((serverPermissionsInput: any, permission: any) => {
serverPermissionsInput[permission] = true;
return serverPermissionsInput;
}, {})
// Boonjs evaluator needs server permissions as object with permissionId and boolean value
// Each rule is passed to evaluator along with the server permissions
// if the server permissions and rule matches, app permission is added to list
const permissions = Object.keys(Rules).reduce((permissions: any, rule: any) => {
const permissionRule = Rules[rule];
// If for any app permission, we have empty rule we user is assigned the permission
// If rule is not defined, the app permisions is still evaluated or provided to all the users.
if (!permissionRule || (permissionRule && getEvaluator(permissionRule)(serverPermissionsInput))) {
permissions.push(rule);
}
return permissions;
}, [])
const { can, rules } = new AbilityBuilder<ClaimBasedAbility>(PureAbility);
permissions.map((permission: any) => {
can(permission);
})
return rules;
}

/**
*
* Sets the current app permissions. This should be used after perparing the app permissions from the server permissions
* @param permissions
* @returns
*/
const setPermissions = (permissions: any) => {
// If the user has passed undefined or null, it should not break the code
if (!permissions) permissions = [];
ability.update(permissions)
return true;
};

/**
* Resets the permissions list. Used for cases like logout
*/
const resetPermissions = () => setPermissions([]);

/**
*
* @param permission
* @returns
*/
const hasPermission = (permission: string) => ability.can(permission);

export { Actions, getServerPermissionsFromRules, hasPermission, prepareAppPermissions, resetPermissions, setPermissions};

// TODO Move this code to an external plugin, to be used across the apps
export default {
install(app: any, options: any) {

// Rules and Actions could be app and OMS package specific
Rules = options.rules;
Actions = options.actions;

// TODO Check why global properties is not working and apply across.
app.config.globalProperties.$permission = this;
},
getServerPermissionsFromRules,
hasPermission,
prepareAppPermissions,
resetPermissions,
setPermissions
}
Loading

0 comments on commit 1cb94f4

Please sign in to comment.