Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented: support for app level permissions(#232) #233

Merged
merged 7 commits into from
Dec 21, 2023
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ VUE_APP_I18N_FALLBACK_LOCALE=en
VUE_APP_CACHE_MAX_AGE=3600
VUE_APP_VIEW_SIZE=10
VUE_APP_BASE_URL=
VUE_APP_PERMISSION_ID=
VUE_APP_PERMISSION_ID="INVCOUNT_APP_VIEW"
VUE_APP_ALIAS=
VUE_APP_DEFAULT_LOG_LEVEL="error"
VUE_APP_LOGIN_URL="http://launchpad.hotwax.io/login"
3 changes: 2 additions & 1 deletion src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { api, client, getConfig, initialise, logout, resetConfig, updateInstanceUrl, updateToken } from '@hotwax/oms-api'
import { api, client, getConfig, getUserFacilities, initialise, logout, resetConfig, updateInstanceUrl, updateToken } from '@hotwax/oms-api'

export {
api,
client,
getConfig,
getUserFacilities,
initialise,
logout,
resetConfig,
Expand Down
3 changes: 2 additions & 1 deletion src/authorization/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default {
"APP_SEARCH_VIEW": "APP_SEARCH_VIEW",
"APP_VARIANCE_LOG": "APP_VARIANCE_LOG",
"APP_INVNTRY_CNT_IMPORT": "APP_INVNTRY_CNT_IMPORT",
"APP_QOH_STNG_UPDATE": "APP_QOH_STNG_UPDATE"
"APP_QOH_STNG_UPDATE": "APP_QOH_STNG_UPDATE",
"INVCOUNT_APP_VIEW": "INVCOUNT_APP_VIEW"
}
4 changes: 3 additions & 1 deletion src/authorization/Rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export default {
"APP_SEARCH_VIEW": "",
"APP_VARIANCE_LOG": "FULFILL_INVCUNT_ADMIN OR INV_COUNT_ADMIN",
"APP_INVNTRY_CNT_IMPORT": "",
"APP_QOH_STNG_UPDATE": "COMMON_ADMIN"
"APP_QOH_STNG_UPDATE": "COMMON_ADMIN",
"APP_INVCUNT_ADMIN": "COMMON_ADMIN",
"INVCOUNT_APP_VIEW": "INVCOUNT_APP_VIEW"
} as any
5 changes: 5 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"App": "App",
"Are you sure you want to change the time zone to?": "Are you sure you want to change the time zone to {timeZoneId}?",
"Authenticating": "Authenticating",
"Back to Launchpad": "Back to Launchpad",
"Camera permission denied.": "Camera permission denied.",
"Cancel": "Cancel",
"Change": "Change",
Expand All @@ -16,6 +17,7 @@
"Enter the amount of stock that has changed.": "Enter the amount of stock that has changed.",
"Enter the count of stock on the shelf.": "Enter the count of stock on the shelf.",
"Enter the stock count for the product": "Enter the stock count for the product",
"Facility needs to be associated with a product store to change this configuration.": "Facility needs to be associated with a product store to change this configuration.",
"Facility": "Facility",
"Go to Launchpad": "Go to Launchpad",
"Go to OMS": "Go to OMS",
Expand All @@ -27,6 +29,7 @@
"Location": "Location",
"Log variance": "Log variance",
"Login": "Login",
"Login failed": "Login failed",
"Logging in": "Logging in",
"Logging out": "Logging out",
"Logout": "Logout",
Expand All @@ -37,6 +40,7 @@
"OMS": "OMS",
"OMS instance": "OMS instance",
"Password": "Password",
"Please contact the administrator.": "Please contact the administrator.",
"Quantity": "Quantity",
"Quantity on hand": "Quantity on hand",
"Remove": "Remove",
Expand Down Expand Up @@ -73,5 +77,6 @@
"Variance reason": "Variance reason",
"Variance updated successfully": "Variance updated successfully",
"View": "View",
"You do not have permission to access the app.": "You do not have permission to access the app.",
"You do not have permission to access this page": "You do not have permission to access this page"
}
12 changes: 8 additions & 4 deletions src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ const getUserProfile = async (token: any): Promise<any> => {
'Content-Type': 'application/json'
}
});
if(hasError(resp)) return Promise.reject("Error getting user profile: " + JSON.stringify(resp.data));
if(resp.data.facilities.length === 0 ) return Promise.reject("User is not associated with any facility: " + JSON.stringify(resp.data));
if(hasError(resp)) return Promise.reject("Error getting user profile");
return Promise.resolve(resp.data)
} catch(error: any) {
return Promise.reject(error)
Expand Down Expand Up @@ -58,6 +57,11 @@ const setUserTimeZone = async (payload: any): Promise <any> => {
});
}
const getQOHViewConfig = async (token: any, productStoreId: any): Promise<any> => {
// If the productStoreId is not provided, it may be case of facility not associated with any productStore
if (!productStoreId) {
return Promise.resolve({});
}

const baseURL = store.getters['user/getBaseUrl'];
try {
const params = {
Expand Down Expand Up @@ -212,11 +216,11 @@ const getCurrentEComStore = async (token: any, facilityId: any): Promise<any> =>
}
});
if (hasError(resp)) {
return Promise.reject(resp.data);
throw resp.data;
}
return Promise.resolve(resp.data.docs?.length ? resp.data.docs[0] : {});
} catch(error: any) {
return Promise.reject(error)
return Promise.resolve({})
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/store/modules/user/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as types from './mutation-types'
import { hasError, showToast } from '@/utils'
import { translate } from '@/i18n'
import { Settings } from 'luxon';
import { logout, updateInstanceUrl, updateToken, resetConfig } from '@/adapter'
import { getUserFacilities, logout, updateInstanceUrl, updateToken, resetConfig } from '@/adapter'
import {
getServerPermissionsFromRules,
prepareAppPermissions,
Expand All @@ -15,6 +15,7 @@ import {
} from '@/authorization'
import { useAuthStore } from '@hotwax/dxp-components'
import emitter from '@/event-bus'
import store from '@/store'

const actions: ActionTree<UserState, RootState> = {

Expand Down Expand Up @@ -43,9 +44,9 @@ const actions: ActionTree<UserState, RootState> = {
if (permissionId) {
// As the token is not yet set in the state passing token headers explicitly
// TODO Abstract this out, how token is handled should be part of the method not the callee
const hasPermission = appPermissions.some((appPermissionId: any) => appPermissionId === permissionId );
const hasPermission = appPermissions.some((appPermission: any) => appPermission.action === permissionId );
// If there are any errors or permission check fails do not allow user to login
if (hasPermission) {
if (!hasPermission) {
const permissionError = 'You do not have permission to access the app.';
showToast(translate(permissionError));
console.error("error", permissionError);
Expand All @@ -55,6 +56,15 @@ const actions: ActionTree<UserState, RootState> = {

const userProfile = await UserService.getUserProfile(token);

//fetching user facilities
const isAdminUser = appPermissions.some((appPermission: any) => appPermission?.action === "APP_INVCUNT_ADMIN" );
const baseURL = store.getters['user/getBaseUrl'];
const facilities = await getUserFacilities(token, baseURL, userProfile?.partyId, "", isAdminUser);

if (!facilities.length) throw 'Unable to login. User is not assocaited with any facility'

userProfile.facilities = facilities;

// removing duplicate records as a single user can be associated with a facility by multiple roles.
userProfile.facilities.reduce((uniqueFacilities: any, facility: any, index: number) => {
if(uniqueFacilities.includes(facility.facilityId)) userProfile.facilities.splice(index, 1);
Expand Down Expand Up @@ -86,7 +96,8 @@ const actions: ActionTree<UserState, RootState> = {
// TODO Check if handling of specific status codes is required.
showToast(translate('Something went wrong while login. Please contact administrator'));
console.error("error", err);
return Promise.reject(new Error(err))
// Added ternary check for serverResponse as in to correctly display the message on UI, need to remove this once all the service reject in same format
return Promise.reject(new Error(err?.serverResponse ? err.serverResponse : err))
}
},

Expand Down
7 changes: 4 additions & 3 deletions src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<ion-item lines="none">
<ion-label>{{ $t("Select facility") }}</ion-label>
<ion-select interface="popover" v-model="currentFacilityId" @ionChange="setFacility($event)">
<ion-select-option v-for="facility in (userProfile ? userProfile.facilities : [])" :key="facility.facilityId" :value="facility.facilityId" >{{ facility.name }}</ion-select-option>
<ion-select-option v-for="facility in (userProfile ? userProfile.facilities : [])" :key="facility.facilityId" :value="facility.facilityId" >{{ facility.facilityName }}</ion-select-option>
</ion-select>
</ion-item>
</ion-card>
Expand Down Expand Up @@ -84,10 +84,11 @@
</ion-card-header>
<ion-card-content>
{{ $t('Show the current physical quantity expected at locations while counting to help gauge inventory accuracy.') }}
<p>{{ $t('Facility needs to be associated with a product store to change this configuration.') }}</p>
</ion-card-content>
<ion-item lines="none">
<ion-label> {{ $t('Show systemic inventory') }} </ion-label>
<ion-toggle :disabled="!hasPermission(Actions.APP_QOH_STNG_UPDATE) || Object.keys(currentQOHViewConfig).length == 0" :checked="currentQOHViewConfig.settingValue" @ionChange="updateViewQOHConfig(currentQOHViewConfig, $event.detail.checked)" slot="end" />
<ion-toggle :disabled="!hasPermission(Actions.APP_QOH_STNG_UPDATE) || !currentEComStore?.productStoreId || Object.keys(currentQOHViewConfig).length == 0" :checked="currentQOHViewConfig.settingValue" @ionChange="updateViewQOHConfig(currentQOHViewConfig, $event.detail.checked)" slot="end" />
</ion-item>
</ion-card>
</section>
Expand Down Expand Up @@ -123,7 +124,7 @@ export default defineComponent({
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonLabel,
IonPage,
IonSelect,
IonSelectOption,
Expand Down
Loading