Add permissions
This commit is contained in:
@@ -37,7 +37,8 @@ module.exports = configure(function (/* ctx */) {
|
|||||||
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
||||||
boot: [
|
boot: [
|
||||||
'axios',
|
'axios',
|
||||||
'error-handler'
|
'error-handler',
|
||||||
|
'permissions'
|
||||||
],
|
],
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||||
|
|||||||
34
frontend/src/boot/permissions.ts
Normal file
34
frontend/src/boot/permissions.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// src/boot/permissions.ts
|
||||||
|
import { boot } from 'quasar/wrappers';
|
||||||
|
import { useAuthStore } from 'src/stores/useAuthStore';
|
||||||
|
import { DirectiveBinding } from 'vue';
|
||||||
|
|
||||||
|
export const MenuMapping = {
|
||||||
|
home: null,
|
||||||
|
app: null,
|
||||||
|
version: null,
|
||||||
|
user: 'user',
|
||||||
|
role: 'role',
|
||||||
|
domain: null,
|
||||||
|
userDomain: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = useAuthStore();
|
||||||
|
|
||||||
|
export default boot(({ app }) => {
|
||||||
|
app.directive('permissions', {
|
||||||
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
|
const { value } = binding;
|
||||||
|
if (!value || store.isSuperAdmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!store.permissions[value]) {
|
||||||
|
if (el.parentNode) {
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
} else {
|
||||||
|
el.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-item
|
<q-item
|
||||||
|
v-permissions="permission"
|
||||||
clickable
|
clickable
|
||||||
tag="a"
|
tag="a"
|
||||||
:target="target?target:'_blank'"
|
:target="target?target:'_blank'"
|
||||||
@@ -35,6 +36,7 @@ export interface EssentialLinkProps {
|
|||||||
isSeparator?: boolean;
|
isSeparator?: boolean;
|
||||||
target?:string;
|
target?:string;
|
||||||
disable?:boolean;
|
disable?:boolean;
|
||||||
|
permission?: string
|
||||||
}
|
}
|
||||||
withDefaults(defineProps<EssentialLinkProps>(), {
|
withDefaults(defineProps<EssentialLinkProps>(), {
|
||||||
caption: '',
|
caption: '',
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:actions="{ row }">
|
<template v-slot:actions="{ row }">
|
||||||
<q-btn round title="解除" flat color="primary" padding="xs" size="1em" :loading="row.isRemoving" icon="person_off" @click="removeShareTo(row)" />
|
<q-btn round title="解除" flat color="primary" :disable="isActionDisable && isActionDisable(row)" padding="xs" size="1em" :loading="row.isRemoving" icon="person_off" @click="removeShareTo(row)" />
|
||||||
</template>
|
</template>
|
||||||
</sharing-user-list>
|
</sharing-user-list>
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch, onMounted } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||||
import { IUser, IUserDisplay } from '../../types/UserTypes';
|
import { IUser, IUserDisplay } from '../../types/UserTypes';
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
@@ -76,6 +76,7 @@ import { useAuthStore } from 'stores/useAuthStore';
|
|||||||
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
|
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
|
||||||
import RoleLabel from 'components/ShareDomain/RoleLabel.vue';
|
import RoleLabel from 'components/ShareDomain/RoleLabel.vue';
|
||||||
import { Dialog } from 'quasar'
|
import { Dialog } from 'quasar'
|
||||||
|
import { IResponse } from 'src/types/BaseTypes';
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ interface Props {
|
|||||||
domain: IDomainOwnerDisplay;
|
domain: IDomainOwnerDisplay;
|
||||||
dialogTitle: string;
|
dialogTitle: string;
|
||||||
userListTitle: string;
|
userListTitle: string;
|
||||||
hideSelf: boolean;
|
isActionDisable?: (user: IUserDisplay) => boolean;
|
||||||
shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
||||||
removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
||||||
getSharedApi: (domain: IDomainOwnerDisplay) => Promise<any>;
|
getSharedApi: (domain: IDomainOwnerDisplay) => Promise<any>;
|
||||||
@@ -205,10 +206,6 @@ const loadShared = async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
sharedUsersIdSet.clear();
|
sharedUsersIdSet.clear();
|
||||||
|
|
||||||
if(props.hideSelf) {
|
|
||||||
sharedUsersIdSet.add((Number)(authStore.userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data } = await props.getSharedApi(props.domain);
|
const { data } = await props.getSharedApi(props.domain);
|
||||||
|
|
||||||
sharedUsers.value = data.data.reduce((arr: IUserDisplayWithShareRole[], item: IUser) => {
|
sharedUsers.value = data.data.reduce((arr: IUserDisplayWithShareRole[], item: IUser) => {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
:share-api="shareApi"
|
:share-api="shareApi"
|
||||||
:remove-shared-api="removeSharedApi"
|
:remove-shared-api="removeSharedApi"
|
||||||
:get-shared-api="getSharedApi"
|
:get-shared-api="getSharedApi"
|
||||||
|
:is-action-disable="(row) => row.id === authStore.userId"
|
||||||
:model-value="modelValue"
|
:model-value="modelValue"
|
||||||
hide-self
|
|
||||||
@update:modelValue="updateModelValue"
|
@update:modelValue="updateModelValue"
|
||||||
@close="close"
|
@close="close"
|
||||||
/>
|
/>
|
||||||
@@ -19,6 +19,10 @@ import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
|
|||||||
import { IUserDisplay } from '../../types/UserTypes';
|
import { IUserDisplay } from '../../types/UserTypes';
|
||||||
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
|
import { useAuthStore } from 'src/stores/useAuthStore';
|
||||||
|
import { IResponse } from 'src/types/BaseTypes';
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: boolean;
|
modelValue: boolean;
|
||||||
@@ -35,11 +39,11 @@ async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
||||||
return api.delete(`api/managedomain/${domain.id}/${user.id}`);
|
return api.delete<IResponse>(`api/managedomain/${domain.id}/${user.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSharedApi(domain: IDomainOwnerDisplay) {
|
async function getSharedApi(domain: IDomainOwnerDisplay) {
|
||||||
return api.get(`/api/managedomainuser/${domain.id}`);
|
return api.get<IResponse>(`/api/managedomainuser/${domain.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -19,10 +19,6 @@
|
|||||||
</q-item-label>
|
</q-item-label>
|
||||||
|
|
||||||
<EssentialLink v-for="link in essentialLinks" :key="link.title" v-bind="link" />
|
<EssentialLink v-for="link in essentialLinks" :key="link.title" v-bind="link" />
|
||||||
<div v-if="isAdmin()">
|
|
||||||
<EssentialLink v-for="link in adminLinks" :key="link.title" v-bind="link" />
|
|
||||||
</div>
|
|
||||||
<EssentialLink v-for="link in domainLinks" :key="link.title" v-bind="link" />
|
|
||||||
|
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
@@ -34,12 +30,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, reactive } from 'vue';
|
import { computed, onMounted, reactive, getCurrentInstance } from 'vue';
|
||||||
import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue';
|
import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue';
|
||||||
import DomainSelector from 'components/DomainSelector.vue';
|
import DomainSelector from 'components/DomainSelector.vue';
|
||||||
import UserInfoButton from 'components/UserInfoButton.vue';
|
import UserInfoButton from 'components/UserInfoButton.vue';
|
||||||
import { useAuthStore } from 'stores/useAuthStore';
|
import { useAuthStore } from 'stores/useAuthStore';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import { MenuMapping } from 'src/boot/permissions';
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -52,7 +49,8 @@ const essentialLinks: EssentialLinkProps[] = reactive([
|
|||||||
icon: 'home',
|
icon: 'home',
|
||||||
link: '/',
|
link: '/',
|
||||||
target: '_self',
|
target: '_self',
|
||||||
disable: noDomain
|
disable: noDomain,
|
||||||
|
permission: MenuMapping.home
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// title: 'フローエディター',
|
// title: 'フローエディター',
|
||||||
@@ -67,7 +65,8 @@ const essentialLinks: EssentialLinkProps[] = reactive([
|
|||||||
icon: 'widgets',
|
icon: 'widgets',
|
||||||
link: '/#/app',
|
link: '/#/app',
|
||||||
target: '_self',
|
target: '_self',
|
||||||
disable: noDomain
|
disable: noDomain,
|
||||||
|
permission: MenuMapping.app
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// title: '条件エディター',
|
// title: '条件エディター',
|
||||||
@@ -80,6 +79,41 @@ const essentialLinks: EssentialLinkProps[] = reactive([
|
|||||||
title: '',
|
title: '',
|
||||||
isSeparator: true
|
isSeparator: true
|
||||||
},
|
},
|
||||||
|
// ------------ユーザー-------------
|
||||||
|
{
|
||||||
|
title: 'ユーザー管理',
|
||||||
|
caption: 'ユーザーを管理する',
|
||||||
|
icon: 'manage_accounts',
|
||||||
|
link: '/#/user',
|
||||||
|
target: '_self',
|
||||||
|
permission: MenuMapping.user
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ロール管理',
|
||||||
|
caption: 'ロールを管理する',
|
||||||
|
icon: 'work',
|
||||||
|
link: '/#/role',
|
||||||
|
target: '_self',
|
||||||
|
permission: MenuMapping.role
|
||||||
|
},
|
||||||
|
// ------------ドメイン-------------
|
||||||
|
{
|
||||||
|
title: 'ドメイン管理',
|
||||||
|
caption: 'kintoneのドメイン設定',
|
||||||
|
icon: 'domain',
|
||||||
|
link: '/#/domain',
|
||||||
|
target: '_self',
|
||||||
|
permission: MenuMapping.domain
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ドメイン適用',
|
||||||
|
caption: 'ユーザー使用可能なドメインの設定',
|
||||||
|
icon: 'assignment_ind',
|
||||||
|
link: '/#/userDomain',
|
||||||
|
target: '_self',
|
||||||
|
id: 'userDomain',
|
||||||
|
permission: MenuMapping.userDomain
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// title:'Kintone ポータル',
|
// title:'Kintone ポータル',
|
||||||
// caption:'Kintone',
|
// caption:'Kintone',
|
||||||
@@ -100,40 +134,6 @@ const essentialLinks: EssentialLinkProps[] = reactive([
|
|||||||
// },
|
// },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const domainLinks: EssentialLinkProps[] = reactive([
|
|
||||||
{
|
|
||||||
title: 'ドメイン管理',
|
|
||||||
caption: 'kintoneのドメイン設定',
|
|
||||||
icon: 'domain',
|
|
||||||
link: '/#/domain',
|
|
||||||
target: '_self'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'ドメイン適用',
|
|
||||||
caption: 'ユーザー使用可能なドメインの設定',
|
|
||||||
icon: 'assignment_ind',
|
|
||||||
link: '/#/userDomain',
|
|
||||||
target: '_self'
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const adminLinks: EssentialLinkProps[] = reactive([
|
|
||||||
{
|
|
||||||
title: 'ユーザー管理',
|
|
||||||
caption: 'ユーザーを管理する',
|
|
||||||
icon: 'manage_accounts',
|
|
||||||
link: '/#/user',
|
|
||||||
target: '_self'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'ロール管理',
|
|
||||||
caption: 'ロールを管理する',
|
|
||||||
icon: 'work',
|
|
||||||
link: '/#/role',
|
|
||||||
target: '_self'
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
const version = process.env.version;
|
const version = process.env.version;
|
||||||
const productName = process.env.productName;
|
const productName = process.env.productName;
|
||||||
|
|
||||||
@@ -142,10 +142,8 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function toggleLeftDrawer() {
|
function toggleLeftDrawer() {
|
||||||
|
getCurrentInstance();
|
||||||
|
debugger;
|
||||||
authStore.toggleLeftMenu();
|
authStore.toggleLeftMenu();
|
||||||
}
|
}
|
||||||
function isAdmin(){
|
|
||||||
const permission = authStore.permissions;
|
|
||||||
return permission === 'admin'
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
:pagination="pagination" >
|
:pagination="pagination" >
|
||||||
|
|
||||||
<template v-slot:top>
|
<template v-slot:top>
|
||||||
<q-btn color="primary" :disable="allLoading || loading || selected?.id == -2" label="追加" @click="showAddRoleDialog" />
|
<q-btn color="primary" :disable="allLoading || loading || selected?.id == EMPTY_ROLE.id" label="追加" @click="showAddRoleDialog" />
|
||||||
<q-space />
|
<q-space />
|
||||||
<q-input borderless dense filled debounce="300" v-model="filter" placeholder="検索">
|
<q-input borderless dense filled debounce="300" v-model="filter" placeholder="検索">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
@@ -132,7 +132,12 @@ const statusFilterOptions = [
|
|||||||
|
|
||||||
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||||||
|
|
||||||
const roles = computed(() => userStore.roles.concat(EMPTY_ROLE));
|
const roles = computed(() => {
|
||||||
|
if (userStore.roles.length > 0) {
|
||||||
|
return userStore.roles.concat(EMPTY_ROLE);
|
||||||
|
}
|
||||||
|
return userStore.roles;
|
||||||
|
});
|
||||||
|
|
||||||
const selected = ref<IRolesDisplay>();
|
const selected = ref<IRolesDisplay>();
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,14 @@ const routerInstance = createRouter({
|
|||||||
|
|
||||||
export default route(function (/* { store, ssrContext } */) {
|
export default route(function (/* { store, ssrContext } */) {
|
||||||
|
|
||||||
routerInstance.beforeEach(async (to) => {
|
routerInstance.beforeEach(async (to, from) => {
|
||||||
// clear alert on route change
|
// clear alert on route change
|
||||||
//const alertStore = useAlertStore();
|
//const alertStore = useAlertStore();
|
||||||
//alertStore.clear();
|
//alertStore.clear();
|
||||||
|
|
||||||
// redirect to login page if not logged in and trying to access a restricted page
|
// redirect to login page if not logged in and trying to access a restricted page
|
||||||
const publicPages = ['/login'];
|
const loginPage = '/login';
|
||||||
|
const publicPages = [loginPage];
|
||||||
const authRequired = !publicPages.includes(to.path);
|
const authRequired = !publicPages.includes(to.path);
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
@@ -49,8 +50,12 @@ export default route(function (/* { store, ssrContext } */) {
|
|||||||
return '/login';
|
return '/login';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authStore.token && to.path === loginPage) {
|
||||||
|
return from.path == '/' ? '/' : false;
|
||||||
|
}
|
||||||
|
|
||||||
// redirect to domain setting page if no domain exist
|
// redirect to domain setting page if no domain exist
|
||||||
const domainPages = [...publicPages, '/domain', '/userDomain', '/user'];
|
const domainPages = [...publicPages, '/domain', '/userDomain', '/user', '/role'];
|
||||||
if (!authStore.hasDomain && !domainPages.includes(to.path)) {
|
if (!authStore.hasDomain && !domainPages.includes(to.path)) {
|
||||||
Dialog.create({
|
Dialog.create({
|
||||||
title: '注意',
|
title: '注意',
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ const routes: RouteRecordRaw[] = [
|
|||||||
children: [
|
children: [
|
||||||
{ path: '', component: () => import('pages/IndexPage.vue') },
|
{ path: '', component: () => import('pages/IndexPage.vue') },
|
||||||
{ path: 'ruleEditor', component: () => import('pages/RuleEditor.vue') },
|
{ path: 'ruleEditor', component: () => import('pages/RuleEditor.vue') },
|
||||||
{ path: 'test', component: () => import('pages/testQursar.vue') },
|
|
||||||
{ path: 'flow', component: () => import('pages/testFlow.vue') },
|
{ path: 'flow', component: () => import('pages/testFlow.vue') },
|
||||||
{ path: 'FlowChartTest', component: () => import('pages/FlowChartTest.vue') },
|
{ path: 'FlowChartTest', component: () => import('pages/FlowChartTest.vue') },
|
||||||
{ path: 'flowEditor', component: () => import('pages/FlowEditorPage.vue') },
|
{ path: 'flowEditor', component: () => import('pages/FlowEditorPage.vue') },
|
||||||
// { path: 'FlowChart', component: () => import('pages/FlowChart.vue') },
|
// { path: 'FlowChart', component: () => import('pages/FlowChart.vue') },
|
||||||
{ path: 'right', component: () => import('pages/testRight.vue') },
|
|
||||||
{ path: 'domain', component: () => import('pages/TenantDomain.vue') },
|
{ path: 'domain', component: () => import('pages/TenantDomain.vue') },
|
||||||
{ path: 'userdomain', component: () => import('pages/UserDomain.vue')},
|
{ path: 'userdomain', component: () => import('pages/UserDomain.vue')},
|
||||||
{ path: 'user', component: () => import('pages/UserManagement.vue')},
|
{ path: 'user', component: () => import('pages/UserManagement.vue')},
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
import { router } from 'src/router';
|
import { router } from 'src/router';
|
||||||
import { IDomainInfo } from '../types/DomainTypes';
|
import { IDomain, IDomainInfo } from '../types/DomainTypes';
|
||||||
import { jwtDecode } from 'jwt-decode';
|
import { jwtDecode } from 'jwt-decode';
|
||||||
import { useAppStore } from './useAppStore';
|
import { useAppStore } from './useAppStore';
|
||||||
import { useUserStore } from './useUserStore';
|
import { userToUserRolesDisplay, useUserStore } from './useUserStore';
|
||||||
|
import { IRolesDisplay, IUser, IUserRolesDisplay } from 'src/types/UserTypes';
|
||||||
|
import { IResponse } from 'src/types/BaseTypes';
|
||||||
|
|
||||||
interface UserInfo {
|
interface IPermission {
|
||||||
firstName: string;
|
id: number,
|
||||||
lastName: string;
|
menu: string,
|
||||||
fullName: string;
|
function: string,
|
||||||
email: string;
|
privilege: string,
|
||||||
|
link: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IPermissions = { [key: string]: string };
|
||||||
|
|
||||||
export interface IUserState {
|
export interface IUserState {
|
||||||
token?: string;
|
token?: string;
|
||||||
returnUrl: string;
|
returnUrl: string;
|
||||||
currentDomain: IDomainInfo;
|
currentDomain: IDomainInfo;
|
||||||
LeftDrawer: boolean;
|
LeftDrawer: boolean;
|
||||||
userId?: string;
|
userInfo: IUserRolesDisplay;
|
||||||
userInfo: UserInfo;
|
tenant: string;
|
||||||
roles:string,
|
permissions: IPermissions;
|
||||||
permissions: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', {
|
export const useAuthStore = defineStore('auth', {
|
||||||
@@ -30,17 +34,22 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
returnUrl: '',
|
returnUrl: '',
|
||||||
LeftDrawer: false,
|
LeftDrawer: false,
|
||||||
currentDomain: {} as IDomainInfo,
|
currentDomain: {} as IDomainInfo,
|
||||||
userId: '',
|
userInfo: {} as IUserRolesDisplay,
|
||||||
userInfo: {} as UserInfo,
|
tenant: '',
|
||||||
roles:'',
|
permissions: {} as IPermissions
|
||||||
permissions: '',
|
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
toggleLeftDrawer(): boolean {
|
userId(): number {
|
||||||
return this.LeftDrawer;
|
return this.userInfo.id;
|
||||||
},
|
},
|
||||||
hasDomain(): boolean {
|
hasDomain(): boolean {
|
||||||
return this.currentDomain.id !== undefined;
|
return this.currentDomain.id !== undefined;
|
||||||
|
},
|
||||||
|
getRoles(): IRolesDisplay[] {
|
||||||
|
return this.userInfo.roles;
|
||||||
|
},
|
||||||
|
isSuperAdmin(): boolean {
|
||||||
|
return this.userInfo.isSuperuser;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -56,15 +65,20 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
params.append('password', password);
|
params.append('password', password);
|
||||||
try {
|
try {
|
||||||
const result = await api.post(`api/token`, params);
|
const result = await api.post(`api/token`, params);
|
||||||
console.info(result);
|
// console.info(result);
|
||||||
this.token = result.data.access_token;
|
this.token = result.data.access_token;
|
||||||
const tokenJson = jwtDecode(result.data.access_token);
|
const tokenJson = jwtDecode<{sub: number, tenant: string, roles: string}>(result.data.access_token);
|
||||||
this.userId = tokenJson.sub;
|
this.tenant = tokenJson.tenant;
|
||||||
this.permissions = (tokenJson as any).permissions==='ALL' ? 'admin': 'user';
|
this.userInfo.id = tokenJson.sub;
|
||||||
|
this.userInfo.isSuperuser = tokenJson.roles === 'super';
|
||||||
api.defaults.headers['Authorization'] = 'Bearer ' + this.token;
|
api.defaults.headers['Authorization'] = 'Bearer ' + this.token;
|
||||||
await this.loadCurrentDomain();
|
await Promise.all([
|
||||||
this.userInfo = await this.getUserInfo();
|
this.loadCurrentDomain(),
|
||||||
router.push(this.returnUrl || '/');
|
this.loadUserInfo(),
|
||||||
|
this.loadPermission()
|
||||||
|
]);
|
||||||
|
await router.push(this.returnUrl || '/');
|
||||||
|
this.returnUrl = '';
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@@ -72,29 +86,40 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadCurrentDomain() {
|
async loadCurrentDomain() {
|
||||||
const resp = await api.get(`api/defaultdomain`);
|
const resp = await api.get<IResponse<IDomain>>(`api/defaultdomain`);
|
||||||
const activedomain = resp?.data?.data;
|
const activedomain = resp?.data?.data;
|
||||||
this.currentDomain = {
|
if (!activedomain) {
|
||||||
id: activedomain?.id,
|
this.currentDomain = {} as IDomainInfo;
|
||||||
domainName: activedomain?.name,
|
} else {
|
||||||
kintoneUrl: activedomain?.url,
|
this.currentDomain = {
|
||||||
};
|
id: activedomain.id,
|
||||||
},
|
domainName: activedomain.name,
|
||||||
async getUserInfo():Promise<UserInfo>{
|
kintoneUrl: activedomain.url,
|
||||||
const resp = (await api.get(`api/v1/users/me`)).data.data;
|
};
|
||||||
return {
|
|
||||||
firstName: resp.first_name,
|
|
||||||
lastName: resp.last_name,
|
|
||||||
fullName: resp.last_name + ' ' + resp.first_name,
|
|
||||||
email: resp.email,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logout() {
|
async loadUserInfo() {
|
||||||
|
const resp = (await api.get<IResponse<IUser>>(`api/v1/users/me`))?.data?.data;
|
||||||
|
this.userInfo = userToUserRolesDisplay(resp)
|
||||||
|
},
|
||||||
|
async loadPermission() {
|
||||||
|
this.permissions = {} as IPermissions;
|
||||||
|
if (this.isSuperAdmin) return;
|
||||||
|
const resp = (await api.get<IResponse<IPermission[]>>(`api/v1/userpermssions`)).data.data;
|
||||||
|
resp.forEach((permission) => {
|
||||||
|
this.permissions[permission.link] = permission.menu;
|
||||||
|
this.permissions[permission.privilege] = permission.function;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async logout() {
|
||||||
this.token = '';
|
this.token = '';
|
||||||
this.currentDomain = {} as IDomainInfo; // 清空当前域
|
this.currentDomain = {} as IDomainInfo; // 清空当前域
|
||||||
useAppStore().reset();
|
useAppStore().reset();
|
||||||
useUserStore().reset();
|
useUserStore().reset();
|
||||||
router.push('/login');
|
await router.push('/login');
|
||||||
|
this.tenant = '';
|
||||||
|
this.userInfo = {} as IUserRolesDisplay;
|
||||||
|
this.permissions = {} as IPermissions;
|
||||||
},
|
},
|
||||||
async setCurrentDomain(domain?: IDomainInfo) {
|
async setCurrentDomain(domain?: IDomainInfo) {
|
||||||
if (!domain) {
|
if (!domain) {
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ export function userToUserDisplay(user: IUser): IUserDisplay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function userToUserRolesDisplay(user: IUser): IUserRolesDisplay {
|
export function userToUserRolesDisplay(user: IUser): IUserRolesDisplay {
|
||||||
|
if (!user) return {} as IUserRolesDisplay;
|
||||||
const userRolesDisplay = userToUserDisplay(user) as IUserRolesDisplay;
|
const userRolesDisplay = userToUserDisplay(user) as IUserRolesDisplay;
|
||||||
const roles: IRolesDisplay[] = [];
|
const roles: IRolesDisplay[] = [];
|
||||||
const roleIds: number[] = [];
|
const roleIds: number[] = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user