From 79698ad562f8bb11391315e7b39338b5fb6a593d Mon Sep 17 00:00:00 2001 From: EdwinBetanc0urt Date: Tue, 10 Dec 2019 10:11:44 -0400 Subject: [PATCH] Redefine API to provider access. (#199) * Migrate login, get session, change role, logout. * Convert menu. --- src/api/user.js | 60 ++---- src/router/modules/ADempiere/menu.js | 262 ++++++++++--------------- src/store/modules/ADempiere/context.js | 26 +++ src/store/modules/user.js | 130 ++++++------ src/utils/ADempiere/dictionaryUtils.js | 30 +-- src/utils/ADempiere/index.js | 12 +- src/utils/ADempiere/valueUtils.js | 2 + src/views/login/index.vue | 3 +- 8 files changed, 232 insertions(+), 293 deletions(-) diff --git a/src/api/user.js b/src/api/user.js index cc11de27..60a04474 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -13,59 +13,25 @@ function Instance() { // Make login by UserName and password, this function can return user data for show export function login(loginValues) { - if (loginValues.role !== undefined && loginValues.role.trim() !== '') { - return Instance.call(this).requestLogin( - loginValues.userName, - loginValues.password, - loginValues.role, - null, - loginValues.language - ) + if (loginValues.role && loginValues.role.trim() !== '') { + return Instance.call(this).requestLogin({ + userName: loginValues.userName, + userPass: loginValues.password, + role: loginValues.role, + language: getLanguage() || 'en_US' + }) } else { - return Instance.call(this).requestLoginDefault( - loginValues.userName, - loginValues.password, - loginValues.language - ) + return Instance.call(this).requestLoginDefault({ + userName: loginValues.userName, + userPass: loginValues.password, + language: getLanguage() || 'en_US' + }) } } // Get User Info from session Uuid or token export function getInfo(token) { return Instance.call(this).requestUserInfoFromSession(token) - .then(session => { - var roles = [] - var rolesList = session.getRolesList().map(itemRol => { - roles.push(itemRol.getName()) - return { - id: itemRol.getId(), - uuid: itemRol.getUuid(), - name: itemRol.getName(), - description: itemRol.getDescription(), - clientId: itemRol.getClientid(), - clientName: itemRol.getClientname(), - organizationList: itemRol.getOrganizationsList() - } - }) - // TODO: Add user.id, user.level in request - const user = session.getUserinfo() - - const response = { - id: user.getId(), - uuid: user.getUuid(), - name: user.getName(), - comments: user.getComments(), - description: user.getDescription(), - // TODO: Add from ADempiere - avatar: 'https://avatars1.githubusercontent.com/u/1263359?s=200&v=4', - roles: roles, // rol list names, used from app (src/permission.js, src/utils/permission.js) - rolesList: rolesList, - responseGrpc: session - } - return response - }).catch(error => { - console.log(error) - }) } /** @@ -78,7 +44,7 @@ export function getSessionInfo(sessionUuid) { // Logout from server export function logout(sessionUuid) { - return Instance.call(this).requestLogout(sessionUuid) + return Instance.call(this).requestLogOut(sessionUuid) } // Get User menu from server diff --git a/src/router/modules/ADempiere/menu.js b/src/router/modules/ADempiere/menu.js index d9ebc0fd..7974a7bd 100644 --- a/src/router/modules/ADempiere/menu.js +++ b/src/router/modules/ADempiere/menu.js @@ -1,112 +1,121 @@ import { getMenu } from '@/api/user' import { getToken } from '@/utils/auth' +import { convertAction } from '@/utils/ADempiere/dictionaryUtils' /* Layout */ import Layout from '@/layout' +const staticRoutes = [ + { + path: '*', + redirect: '/404', + hidden: true + }, + { + path: '/ProcessActivity', + component: Layout, + meta: { + title: 'ProcessActivity', + icon: 'tree-table', + noCache: true, + breadcrumb: false + }, + redirect: '/ProcessActivity/index', + children: [ + { + path: 'index', + component: () => import('@/views/ADempiere/ProcessActivity'), + name: 'ProcessActivity', + meta: { + title: 'ProcessActivity', + icon: 'tree-table', + noCache: true, + isIndex: true + } + } + ] + }, + { + path: '/report-viewer', + component: Layout, + hidden: true, + redirect: 'report-viewer/:processId/:instanceUuid/:fileName', + children: [ + { + path: ':processId/:instanceUuid/:fileName', + component: () => import('@/views/ADempiere/ReportViewer'), + name: 'Report Viewer', + meta: { + title: 'ReportViewer' + } + } + ] + } +] + // Get Menu from server export function loadMainMenu() { return getMenu(getToken()).then(menu => { - const asyncRouterMap = [ - { - path: '*', - redirect: '/404', - hidden: true - }, - { - path: '/ProcessActivity', - component: Layout, - meta: { title: 'ProcessActivity', icon: 'tree-table', noCache: true, breadcrumb: false }, - redirect: '/ProcessActivity/index', - children: [ - { - path: 'index', - component: () => import('@/views/ADempiere/ProcessActivity'), - name: 'ProcessActivity', - meta: { title: 'ProcessActivity', icon: 'tree-table', noCache: true, isIndex: true } - } - ] - }, - { - path: '/report-viewer', - component: Layout, - hidden: true, - redirect: 'report-viewer/:processId/:instanceUuid/:fileName', - children: [ - { - path: ':processId/:instanceUuid/:fileName', - component: () => import('@/views/ADempiere/ReportViewer'), - name: 'Report Viewer', - meta: { - title: 'ReportViewer' - } - } - ] - } - ] - menu.getChildsList().forEach(menu => { + const asyncRoutesMap = [] + menu.childsList.forEach(menu => { const optionMenu = getRouteFromMenuItem(menu) - if (menu.getIssummary()) { - menu.getChildsList().forEach((menu, index) => { - optionMenu.children.push(getChildFromAction(menu, index = 0)) - optionMenu.children[0].meta.childs.push(getChildFromAction(menu, index = 0)) - optionMenu.meta.childs.push(getChildFromAction(menu, index = 0)) + if (menu.isSummary) { + menu.childsList.forEach(menu => { + const childsSumaryConverted = getChildFromAction(menu, 0) + + optionMenu.children.push(childsSumaryConverted) + optionMenu.children[0].meta.childs.push(childsSumaryConverted) + optionMenu.meta.childs.push(childsSumaryConverted) }) } else { - optionMenu.children.push(getChildFromAction(menu)) - optionMenu.meta.childs.push(getChildFromAction(menu)) + const childsConverted = getChildFromAction(menu) + + optionMenu.children.push(childsConverted) + optionMenu.meta.childs.push(childsConverted) } - asyncRouterMap.push(optionMenu) + asyncRoutesMap.push(optionMenu) }) - return asyncRouterMap + return staticRoutes.concat(asyncRoutesMap) }).catch(error => { - console.log('Error with Login: ' + error) + console.warn(`Error getting menu: ${error.message}. Code: ${error.code}`) }) } // Get Only Child function getChildFromAction(menu, index) { - const action = menu.getAction() - var actionAttributes = convertAction(action) - var routeIdentifier = actionAttributes.name + '/' + menu.getId() - let selectedComponent - if (action === 'W') { - selectedComponent = () => import('@/views/ADempiere/Window') - routeIdentifier = actionAttributes.name + '/' + menu.getId() - } else if (action === 'S') { - selectedComponent = () => import('@/views/ADempiere/Browser') - } else if (action === 'P' || action === 'R') { - selectedComponent = () => import('@/views/ADempiere/Process') - } else if (action === 'B' || action === 'F' || action === 'T' || action === 'X') { - selectedComponent = () => import('@/views/ADempiere/Unsupported') - } else { - selectedComponent = () => import('@/views/ADempiere/Summary') - routeIdentifier = '/' + menu.getId() + const action = menu.action + const actionAttributes = convertAction(action) + let routeIdentifier = actionAttributes.name + '/' + menu.id + if (menu.isSummary) { + routeIdentifier = '/' + menu.id } - var option = { + + const option = { path: routeIdentifier, - component: selectedComponent, - name: menu.getUuid(), + component: actionAttributes.component, + name: menu.uuid, hidden: index > 0, meta: { isIndex: actionAttributes.isIndex, - title: menu.getName(), - description: menu.getDescription(), - uuid: menu.getReferenceuuid(), + title: menu.name, + description: menu.description, + uuid: menu.referenceUuid, tabUuid: '', type: actionAttributes.name, - parentUuid: menu.getParentuuid(), + parentUuid: menu.parentUuid, icon: actionAttributes.icon, alwaysShow: true, noCache: false, childs: [] } } - if (option.meta.type === 'summary') { + + if (actionAttributes.isIndex || actionAttributes.name === 'summary') { option['children'] = [] - menu.getChildsList().forEach((child, index) => { - option.children.push(getChildFromAction(child, index = 1)) - option.meta.childs.push(getChildFromAction(child, index = 1)) + menu.childsList.forEach(child => { + const menuConverted = getChildFromAction(child, 1) + option.children.push(menuConverted) + option.meta.childs.push(menuConverted) }) } return option @@ -114,93 +123,38 @@ function getChildFromAction(menu, index) { // Convert menu item from server to Route function getRouteFromMenuItem(menu) { - const action = menu.getAction() - var actionAttributes = convertAction(action) - var optionMenu = [] - optionMenu = { - path: '/' + menu.getId(), - redirect: '/' + menu.getId() + '/index', + const action = menu.action + const actionAttributes = convertAction(action) + const optionMenu = { + path: '/' + menu.id, + redirect: '/' + menu.id + '/index', component: Layout, - name: menu.getUuid(), + name: menu.uuid, meta: { - title: menu.getName(), - description: menu.getDescription(), + title: menu.name, + description: menu.description, type: actionAttributes.name, icon: actionAttributes.icon, noCache: true, childs: [] }, - children: [ - { - path: 'index', - component: () => import('@/views/ADempiere/Summary'), - name: menu.getUuid() + '-index', - hidden: true, - meta: { - isIndex: actionAttributes.isIndex, - parentUuid: menu.getUuid(), - title: menu.getName(), - description: menu.getDescription(), - type: actionAttributes.name, - icon: actionAttributes.icon, - noCache: true, - breadcrumb: false, - childs: [] - } + children: [{ + path: 'index', + component: actionAttributes.component, + name: menu.uuid + '-index', + hidden: true, + meta: { + isIndex: actionAttributes.isIndex, + parentUuid: menu.uuid, + title: menu.name, + description: menu.description, + type: actionAttributes.name, + icon: actionAttributes.icon, + noCache: true, + breadcrumb: false, + childs: [] } - ] + }] } return optionMenu } - -// Convert action to action name for route -function convertAction(action) { - var actionAttributes = { - name: '', - icon: '', - hidden: false, - isIndex: false - } - switch (action) { - case 'B': - actionAttributes.name = 'workbech' - actionAttributes.icon = 'peoples' - break - case 'F': - actionAttributes.name = 'workflow' - actionAttributes.icon = 'example' - break - case 'P': - actionAttributes.name = 'process' - actionAttributes.icon = 'component' - break - case 'R': - actionAttributes.name = 'report' - actionAttributes.icon = 'skill' - break - case 'S': - actionAttributes.name = 'browser' - actionAttributes.icon = 'search' - break - case 'T': - actionAttributes.name = 'task' - actionAttributes.icon = 'size' - break - case 'W': - actionAttributes.name = 'window' - actionAttributes.icon = 'tab' - break - case 'X': - actionAttributes.name = 'form' - actionAttributes.icon = 'form' - - break - default: - actionAttributes.name = 'summary' - actionAttributes.icon = 'nested' - // actionAttributes.hidden = true - actionAttributes.isIndex = true - break - } - return actionAttributes -} diff --git a/src/store/modules/ADempiere/context.js b/src/store/modules/ADempiere/context.js index 2cc20d42..6424eb48 100644 --- a/src/store/modules/ADempiere/context.js +++ b/src/store/modules/ADempiere/context.js @@ -7,6 +7,13 @@ const context = { context: {} }, mutations: { + /** + * Set context in state + * @param {string} payload.parentUuid + * @param {string} payload.containerUuid + * @param {string} payload.columnName + * @param {mixed} payload.value + */ setContext(state, payload) { var key = '' if (payload.parentUuid && !isEmptyValue(payload.value)) { @@ -41,6 +48,25 @@ const context = { commit('setContext', itemToSetter) }) }, + setMultipleContextObject: ({ commit }, valuesToSetter) => { + Object.keys(valuesToSetter).forEach(key => { + commit('setContext', { + columnName: key, + value: valuesToSetter[key] + }) + }) + }, + setMultipleContextMap: ({ commit }, valuesToSetter) => { + return new Promise(resolve => { + valuesToSetter.forEach((value, key) => { + commit('setContext', { + columnName: key, + value: value + }) + }) + resolve() + }) + }, setInitialContext: ({ commit }, otherContext = {}) => { commit('setInitialContext', otherContext) } diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 647c65a9..9e4d097a 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,8 +1,7 @@ import { login, logout, getInfo, getSessionInfo, changeRole } from '@/api/user' -import { convertRoleFromGRPC } from '@/utils/ADempiere' import { getToken, setToken, removeToken, getCurrentRole, setCurrentRole, removeCurrentRole } from '@/utils/auth' import router, { resetRouter } from '@/router' -import { showMessage, convertMapToArrayPairs } from '@/utils/ADempiere' +import { showMessage } from '@/utils/ADempiere/notification' const state = { token: getToken(), @@ -56,22 +55,18 @@ const actions = { const { userName, password } = userInfo return new Promise((resolve, reject) => { login({ userName: userName.trim(), password: password }) - .then(response => { - var data = { - id: response.getId(), - token: response.getUuid(), - name: response.getUserinfo().getName(), - avatar: 'https://avatars1.githubusercontent.com/u/1263359?s=200&v=4', - currentRole: convertRoleFromGRPC(response.getRole()), - isProcessed: response.getProcessed() - } + .then(logInResponse => { + const { uuid: token } = logInResponse - commit('SET_TOKEN', data.token) - commit('SET_ROL', data.currentRole) + logInResponse.avatar = 'https://avatars1.githubusercontent.com/u/1263359?s=200&v=4' + logInResponse.name = logInResponse.userInfo.name - setToken(data.token) - setCurrentRole(data.currentRole.uuid) - resolve(data) + commit('SET_TOKEN', token) + commit('SET_ROL', logInResponse.role) + + setToken(token) + setCurrentRole(logInResponse.role.uuid) + resolve(logInResponse) }).catch(error => { reject(error) }) @@ -83,45 +78,36 @@ const actions = { sessionUuid = getToken() } return getSessionInfo(sessionUuid) - .then(response => { + .then(responseGetInfo => { commit('setIsSession', true) commit('setSessionInfo', { - id: response.getId(), - uuid: response.getUuid(), - name: response.getName(), - isProcessed: response.getProcessed() + id: responseGetInfo.id, + uuid: responseGetInfo.uuid, + name: responseGetInfo.name, + processed: responseGetInfo.processed }) - const userInfo = response.getUserinfo() - commit('SET_NAME', userInfo.getName()) - commit('SET_INTRODUCTION', userInfo.getDescription()) - commit('SET_USER_UUID', userInfo.getUuid()) + const userInfo = responseGetInfo.userInfo + commit('SET_NAME', responseGetInfo.name) + commit('SET_INTRODUCTION', userInfo.description) + commit('SET_USER_UUID', responseGetInfo.uuid) - var defaultContext = convertMapToArrayPairs({ - toConvert: response.getDefaultcontextMap() - }) - // TODO: return request #Date as long data type Date (5) - // join column names without duplicating it - defaultContext = Array.from(new Set([ - ...defaultContext, - ...[{ - columnName: '#Date', - value: new Date() - }] - ])) + // TODO: return 'Y' or 'N' string values as data type Booelan (4) + // TODO: return #Date as long data type Date (5) + responseGetInfo.defaultContextMap.set('#Date', new Date()) // set multiple context - dispatch('setMultipleContext', defaultContext, { + dispatch('setMultipleContextMap', responseGetInfo.defaultContextMap, { root: true }) const sessionResponse = { - name: response.getName(), - defaultContext: defaultContext + name: responseGetInfo.name, + defaultContext: responseGetInfo.defaultContextMap } return sessionResponse }) .catch(error => { - console.warn('Error gettin context', error.message) + console.warn(`Error getting context session ${error.message}`) }) .finally(() => { dispatch('getUserInfoValue', sessionUuid) @@ -133,25 +119,37 @@ const actions = { sessionUuid = getToken() } return new Promise((resolve, reject) => { - getInfo(sessionUuid).then(response => { - if (!response) { + getInfo(sessionUuid).then(responseGetInfo => { + if (!responseGetInfo) { reject('Verification failed, please Login again.') } // roles must be a non-empty array - if (!response.rolesList || response.rolesList.length <= 0) { + if (!responseGetInfo.rolesList || responseGetInfo.rolesList.length <= 0) { reject('getInfo: roles must be a non-null array!') } - var rol = response.rolesList.find(itemRol => { + const rol = responseGetInfo.rolesList.find(itemRol => { return itemRol.uuid === getCurrentRole() }) + const rolesName = responseGetInfo.rolesList.map(rolItem => { + return rolItem.name + }) - commit('SET_ROLES_LIST', response.rolesList) - commit('SET_ROLES', response.roles) + commit('SET_ROLES_LIST', responseGetInfo.rolesList) + commit('SET_ROLES', rolesName) commit('SET_ROL', rol) - commit('SET_AVATAR', response.avatar) - resolve(response) + + // TODO: Add support from ADempiere + const avatar = 'https://avatars1.githubusercontent.com/u/1263359?s=200&v=4' + commit('SET_AVATAR', avatar) + + resolve({ + ...responseGetInfo, + avatar: avatar, + roles: rolesName + }) }).catch(error => { + console.warn(`Error getting user info value ${error.message}`) reject(error) }) }) @@ -170,7 +168,7 @@ const actions = { root: true }) - // dispatch('tagsView/delAllViews', null, {root:true}) + // dispatch('tagsView/delAllViews', null, { root:true }) removeToken() removeCurrentRole() resetRouter() @@ -190,31 +188,25 @@ const actions = { }) }, // dynamically modify permissions - changeRoles({ commit, state, dispatch }, roleUuid) { - /** - * @param {string} attributes.sessionUuid - * @param {string} attributes.roleUuid - * @param {string} attributes.organizationUuid - * @param {string} attributes.warehouseUuid - */ + changeRoles({ commit, dispatch }, roleUuid) { return changeRole({ sessionUuid: getToken(), roleUuid: roleUuid, organizationUuid: null, warehouseUuid: null }) - .then(response => { - var rol = convertRoleFromGRPC(response.getRole()) - commit('SET_ROL', rol) - setCurrentRole(rol.uuid) - commit('SET_TOKEN', response.getUuid()) - setToken(response.getUuid()) + .then(changeRoleResponse => { + const { role } = changeRoleResponse + commit('SET_ROL', role) + setCurrentRole(role.uuid) + commit('SET_TOKEN', changeRoleResponse.uuid) + setToken(changeRoleResponse.uuid) // Update user info and context associated with session - dispatch('getInfo', response.getUuid()) + dispatch('getInfo', changeRoleResponse.uuid) .then(() => { - var route = router.app._route - var selectedTag = { + const route = router.app._route + const selectedTag = { fullPath: route.fullPath, hash: route.hash, matched: route.matched, @@ -235,8 +227,8 @@ const actions = { }) return { - ...rol, - sessionUuid: response.getUuid() + ...role, + sessionUuid: changeRoleResponse.uuid } }) .catch(error => { @@ -244,7 +236,7 @@ const actions = { message: error.message, type: 'error' }) - console.warn('Error change role:' + error.message + '. Code: ' + error.code) + console.warn(`Error change role: ${error.message}. Code: ${error.code}`) }) // return new Promise(async resolve => { // const token = role diff --git a/src/utils/ADempiere/dictionaryUtils.js b/src/utils/ADempiere/dictionaryUtils.js index 4d76d614..6d897d36 100644 --- a/src/utils/ADempiere/dictionaryUtils.js +++ b/src/utils/ADempiere/dictionaryUtils.js @@ -443,51 +443,59 @@ export function fieldIsDisplayed(field) { return field.isActive && isDisplayedView } +// Convert action to action name for route export function convertAction(action) { - var actionAttributes = { + const actionAttributes = { name: '', icon: '', hidden: false, - isIndex: false + isIndex: false, + component: () => import('@/views/ADempiere/Unsupported') } + switch (action) { case 'B': - actionAttributes.name = 'Workbench' + actionAttributes.name = 'workbech' actionAttributes.icon = 'peoples' break case 'F': - actionAttributes.name = 'Workflow' + actionAttributes.name = 'workflow' actionAttributes.icon = 'example' break case 'P': - actionAttributes.name = 'Process' + actionAttributes.name = 'process' actionAttributes.icon = 'component' + actionAttributes.component = () => import('@/views/ADempiere/Process') break case 'R': - actionAttributes.name = 'Report' + actionAttributes.name = 'report' actionAttributes.icon = 'skill' + actionAttributes.component = () => import('@/views/ADempiere/Process') break case 'S': - actionAttributes.name = 'SmartBrowser' + actionAttributes.name = 'browser' actionAttributes.icon = 'search' + actionAttributes.component = () => import('@/views/ADempiere/Browser') break case 'T': - actionAttributes.name = 'Task' + actionAttributes.name = 'task' actionAttributes.icon = 'size' break case 'W': - actionAttributes.name = 'Window' + actionAttributes.name = 'window' actionAttributes.icon = 'tab' + actionAttributes.component = () => import('@/views/ADempiere/Window') break case 'X': - actionAttributes.name = 'Form' + actionAttributes.name = 'form' actionAttributes.icon = 'form' - break default: actionAttributes.name = 'summary' actionAttributes.icon = 'nested' + // actionAttributes.hidden = true actionAttributes.isIndex = true + actionAttributes.component = () => import('@/views/ADempiere/Summary') break } return actionAttributes diff --git a/src/utils/ADempiere/index.js b/src/utils/ADempiere/index.js index 06759f4a..319e263d 100644 --- a/src/utils/ADempiere/index.js +++ b/src/utils/ADempiere/index.js @@ -1,17 +1,7 @@ -export function convertRoleFromGRPC(roleGRPC) { - return { - id: roleGRPC.getId(), - uuid: roleGRPC.getUuid(), - name: roleGRPC.getName(), - desctiption: roleGRPC.getDescription(), - clientId: roleGRPC.getClientid(), - clientName: roleGRPC.getClientname(), - organizationsList: roleGRPC.getOrganizationsList() - } -} export { default } from '@/utils/ADempiere/evaluator.js' export * from '@/utils/ADempiere/auth.js' +export * from '@/utils/ADempiere/auth.js' export * from '@/utils/ADempiere/notification.js' export * from '@/utils/ADempiere/valueUtils.js' export * from '@/utils/ADempiere/contextUtils.js' diff --git a/src/utils/ADempiere/valueUtils.js b/src/utils/ADempiere/valueUtils.js index c655dcb0..44eccb68 100644 --- a/src/utils/ADempiere/valueUtils.js +++ b/src/utils/ADempiere/valueUtils.js @@ -22,6 +22,8 @@ export function isEmptyValue(value) { return Boolean(!value.trim().length) } else if (typeof value === 'function' || typeof value === 'number' || typeof value === 'boolean' || Object.prototype.toString.call(value) === '[object Date]') { return false + } else if (Object.prototype.toString.call(value) === '[object Map]' && value.size === 0) { + return true } else if (Array.isArray(value)) { return Boolean(!value.length) } else if (typeof value === 'object') { diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 362641aa..84821526 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -182,7 +182,6 @@ export default { this.$store.dispatch('user/login', this.loginForm) .then(() => { this.$router.push({ path: this.redirect || '/' }) - // this.loading = false }) .catch(error => { if (error.code === 13) { @@ -190,6 +189,8 @@ export default { } else { this.$message.error(this.$t('login.unexpectedError')) } + }) + .finally(() => { this.loading = false }) } else {