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

feat: permission-related actions #38

Merged
merged 6 commits into from
May 20, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/boot/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$utils: {
copyToClipboard: (text: string | undefined) => void;
refreshPage: () => void;
};
}
}
Expand Down Expand Up @@ -33,8 +34,7 @@ export default boot(({ app }) => {
await navigator.clipboard.writeText(text);
Notify.create({
message: '复制成功',
color: 'info',
textColor: 'primary',
color: 'grey-8',
position: 'top',
classes: 'text-caption',
timeout: 1000,
Expand All @@ -44,5 +44,9 @@ export default boot(({ app }) => {
throw e;
}
},

refreshPage() {
window.location.reload();
},
};
});
2 changes: 1 addition & 1 deletion src/components/OrgTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@
<div>
<field-label
name="部门 Code"
hint="部门分支的唯一标识符,同一企业机构下唯一,可用户获取部门信息"
hint="部门分支的唯一标识符,同一企业机构下唯一,可用于获取部门信息"
/>
<q-input
v-model="departmentFormData.code"
Expand Down
142 changes: 142 additions & 0 deletions src/components/permission/PermOperations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { api } from 'boot/axios';
import { Dialog } from 'quasar';

import ConfirmDialog from 'components/dialog/ConfirmDialog.vue';
import { Permission } from 'pages/permission/type';
import { Role } from 'pages/role/type';

import { PermOperationsType } from './type';

export const PermOperationsMixin: PermOperationsType = {
methods: {
togglePermissionsStatus(
permissions: Permission[],
isDeleted: boolean,
handler?: (...args: [string]) => void
) {
const permissionDesc = `【${permissions[0].name}】${
permissions.length > 1 ? `等 ${permissions.length} 个权限` : ''
}`;
const content = isDeleted
? `您正在请求禁用${permissionDesc}。操作后,该权限对应资源将无法被外界所获取,即使是已经关联了该权限的主体。`
: `您正在请求启用${permissionDesc}。操作后,拥有该权限的主体将重新获取该权限所对应的资源。`;

Dialog.create({
component: ConfirmDialog,
componentProps: {
title: isDeleted ? '禁用权限' : '启用权限',
content: content,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
label: isDeleted ? '禁用' : '启用',
actionType: 'toggle',
class: 'accent-btn',
},
],
},
}).onOk(async ({ type }) => {
if (type === 'toggle') {
try {
await api.put(
'/permissions/status',
{
ids: permissions.map((p: Permission) => p.id),
is_deleted: isDeleted,
},
{ successMsg: `${isDeleted ? '禁用' : '启用'}权限成功` }
);
} finally {
if (handler) {
handler(isDeleted ? 'disable' : 'enable');
}
}
}
});
},

deletePermissions(
permissions: Permission[],
handler?: (...args: [string]) => void
) {
const permissionDesc = `【${permissions[0].name}】${
permissions.length > 1 ? `等 ${permissions.length} 个权限` : ''
}`;

Dialog.create({
component: ConfirmDialog,
componentProps: {
title: '删除权限',
content: `您正在请求删除${permissionDesc}。数据删除后将无法进行恢复,您确认要继续删除吗?`,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
label: '删除',
actionType: 'delete',
class: 'accent-btn',
},
],
},
}).onOk(async ({ type }) => {
if (type === 'delete') {
try {
await api.request({
method: 'DELETE',
url: '/permissions',
data: { ids: permissions.map((u: Permission) => u.id) },
successMsg: '删除权限成功',
});
} finally {
if (handler) {
handler('delete');
}
}
}
});
},

unbindRoles(
permission: Permission,
roles: Role[],
handler?: (...args: [string]) => void
) {
const roleDesc = `【${roles[0].name}】${
roles.length > 1 ? `等 ${roles.length} 个角色` : ''
}`;

Dialog.create({
component: ConfirmDialog,
componentProps: {
title: '移除角色',
content: `您正在请求解除角色${roleDesc}与当前权限的关联,该操作不会影响角色与其他权限的关联。`,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
label: '解除关系',
actionType: 'unbind',
class: 'accent-btn',
},
],
},
}).onOk(async ({ type }) => {
if (type === 'unbind') {
try {
await api.request({
method: 'POST',
url: '/permissions/unbind_roles',
data: {
role_ids: roles.map((r: Role) => r.id),
permission_ids: [permission.id],
},
successMsg: '移除角色成功',
});
} finally {
if (handler) {
handler('unbind');
}
}
}
});
},
},
};
21 changes: 21 additions & 0 deletions src/components/permission/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Permission } from 'pages/permission/type';
import { Role } from 'pages/role/type';

export interface PermOperationsType {
methods: {
togglePermissionsStatus: (
permissions: Permission[],
isDeleted: boolean,
handler?: (...args: [string]) => void
) => void;
deletePermissions: (
permissions: Permission[],
handler?: (...args: [string]) => void
) => void;
unbindRoles: (
permission: Permission,
roles: Role[],
handler?: (...args: [string]) => void
) => void;
};
}
8 changes: 4 additions & 4 deletions src/components/role/RoleOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const RoleOperationsMixin: RoleOperationsType = {
handler?: (...args: [string]) => void
) {
const roleDesc = `【${roles[0].name}】${
roles.length > 1 ? `等 ${roles.length} 角色` : ''
roles.length > 1 ? `等 ${roles.length} 个角色` : ''
}`;
const content = isDeleted
? `您正在请求禁用${roleDesc}。操作后,角色主体(关联用户)将不再具有角色关联的资源权限,但不会改变角色与角色主体的关联关系。`
Expand All @@ -41,7 +41,7 @@ export const RoleOperationsMixin: RoleOperationsType = {
await api.put(
'/roles/status',
{ ids: roles.map((r: Role) => r.id), is_deleted: isDeleted },
{ successMsg: `${isDeleted ? '禁用' : '启用'}用户成功` }
{ successMsg: `${isDeleted ? '禁用' : '启用'}角色成功` }
);
} finally {
if (handler) {
Expand All @@ -54,7 +54,7 @@ export const RoleOperationsMixin: RoleOperationsType = {

deleteRoles(roles: Role[], handler?: (...args: [string]) => void) {
const roleDesc = `【${roles[0].name}】${
roles.length > 1 ? `等 ${roles.length} 角色` : ''
roles.length > 1 ? `等 ${roles.length} 个角色` : ''
}`;

Dialog.create({
Expand Down Expand Up @@ -102,7 +102,7 @@ export const RoleOperationsMixin: RoleOperationsType = {
component: ConfirmDialog,
componentProps: {
title: '移除用户',
content: `您正在请求解除用户${userDesc}与当前角色的关系,该操作不会影响用户与其他角色的关联。`,
content: `您正在请求解除用户${userDesc}与当前角色的关联,该操作不会影响用户与其他角色的关联。`,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
Expand Down
90 changes: 90 additions & 0 deletions src/components/user/UserOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { api } from 'boot/axios';
import { Dialog } from 'quasar';

import ConfirmDialog from 'components/dialog/ConfirmDialog.vue';
import { Role } from 'pages/role/type';
import { Organization } from 'pages/type';
import { User } from 'pages/user/type';

import { UserOperationsType } from './type';
Expand Down Expand Up @@ -142,5 +144,93 @@ export const UserOperationsMixin: UserOperationsType = {
}
});
},

unbindRoles(
user: User,
roles: Role[],
handler?: (...args: [string]) => void
) {
const roleDesc = `【${roles[0].name}】${
roles.length > 1 ? `等 ${roles.length} 个角色` : '角色'
}`;

Dialog.create({
component: ConfirmDialog,
componentProps: {
title: '移除用户',
content: `您正在请求对该用户移除${roleDesc}。操作后,用户不在拥有角色关联的权限,但若权限仍然被该用户关联的其他角色所涵盖,该用户仍然具有对应权限。`,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
label: '解除关系',
actionType: 'unbind',
class: 'accent-btn',
},
],
},
}).onOk(async ({ type }) => {
if (type === 'unbind') {
try {
await api.request({
method: 'POST',
url: '/roles/unbind_users',
data: {
user_ids: [user.id],
role_ids: roles.map((r: Role) => r.id),
},
successMsg: '移除角色成功',
});
} finally {
if (handler) {
handler('unbind');
}
}
}
});
},

unbindOrgs(
user: User,
organizations: Organization[],
handler?: (...args: [string]) => void
) {
const orgDesc = `【${organizations[0].name}】${
organizations.length > 1 ? `等 ${organizations.length} 个组织` : ''
}`;

Dialog.create({
component: ConfirmDialog,
componentProps: {
title: '移除用户',
content: `您正在请求将该用户从${orgDesc}中移除。操作后,若该用户不再归属原组织类型下的任何企业或部门,则原组织类型下与该用户绑定的角色也会自动解绑。`,
buttons: [
{ label: '取消', class: 'secondary-btn' },
{
label: '解除关系',
actionType: 'unbind',
class: 'accent-btn',
},
],
},
}).onOk(async ({ type }) => {
if (type === 'unbind') {
try {
await api.request({
method: 'POST',
url: '/organizations/unbind_users',
data: {
user_ids: [user.id],
organization_ids: organizations.map((o: Organization) => o.id),
},
successMsg: '成功移出组织',
});
} finally {
if (handler) {
handler('unbind');
}
}
}
});
},
},
};
12 changes: 12 additions & 0 deletions src/components/user/type.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Role } from 'pages/role/type';
import { Organization } from 'pages/type';
import { User } from 'pages/user/type';

export interface UserOperationsType {
Expand All @@ -9,6 +11,16 @@ export interface UserOperationsType {
) => void;
deleteUsers: (users: User[], handler?: (...args: [string]) => void) => void;
resignUsers: (users: User[], handler?: (...args: [string]) => void) => void;
unbindRoles: (
user: User,
roles: Role[],
handler?: (...args: [string]) => void
) => void;
unbindOrgs: (
user: User,
organizations: Organization[],
handler?: (...args: [string]) => void
) => void;
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/css/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
--q-secondary: rgba(255, 255, 255, 0.07);
--q-positive: #4ea161;
--q-negative: #c95b5b;
--q-info: #e9effd;
--q-info: #474a53;

.secondary-btn {
background-color: rgba(255, 255, 255, 0.07);
Expand Down
8 changes: 8 additions & 0 deletions src/pages/AuditLogs.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<template>
<q-page class="full-width q-pa-md">
<q-btn
unelevated
dense
class="no-hover-btn hint-label"
@click="$utils.refreshPage"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use $router.go(0) to reload the router-view(page component) without refreshing the entire page.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 0e0b4fc

>
<q-icon size="18px" class="q-pr-xs" name="subject" />审计日志
</q-btn>
<data-table
ref="table"
:columns="columns"
Expand Down
1 change: 0 additions & 1 deletion src/pages/LoginSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<q-page class="full-width q-pa-md">
<q-splitter
v-model="splitterModel"
class="q-py-sm"
disable
style="height: calc(100vh - 82px)"
>
Expand Down
Loading