feat: add tenant login IP whitelist management
This commit is contained in:
@@ -16,3 +16,7 @@ export const MemberAdd = (params) =>
|
||||
http.request({ url: '/imUserPolicyGroup/memberAdd', method: 'POST', params });
|
||||
export const MemberRemove = (params) =>
|
||||
http.request({ url: '/imUserPolicyGroup/memberRemove', method: 'POST', params });
|
||||
export const LoginIPWhitelist = (params) =>
|
||||
http.request({ url: '/imUserPolicyGroup/loginIPWhitelist', method: 'GET', params });
|
||||
export const LoginIPWhitelistSave = (params) =>
|
||||
http.request({ url: '/imUserPolicyGroup/loginIPWhitelistSave', method: 'POST', params });
|
||||
|
||||
@@ -9,6 +9,17 @@
|
||||
@reset="reloadTable"
|
||||
@keyup.enter="reloadTable"
|
||||
/>
|
||||
<n-alert type="info" :show-icon="true" class="whitelist-summary">
|
||||
租户渠道 IP 白名单 APP:{{
|
||||
whitelistSummary.appList.length
|
||||
? `已配置 ${whitelistSummary.appList.length} 条`
|
||||
: '未配置'
|
||||
}} Web:{{
|
||||
whitelistSummary.webList.length
|
||||
? `已配置 ${whitelistSummary.webList.length} 条`
|
||||
: '未配置'
|
||||
}}
|
||||
</n-alert>
|
||||
<BasicTable
|
||||
ref="actionRef"
|
||||
:columns="columns"
|
||||
@@ -18,17 +29,67 @@
|
||||
:scroll-x="scrollX"
|
||||
:resizeHeightOffset="-10000"
|
||||
>
|
||||
<template #tableTitle
|
||||
><n-button
|
||||
type="primary"
|
||||
:disabled="!hasPermission(['/imUserPolicyGroup/edit'])"
|
||||
@click="openEdit()"
|
||||
>新增分组</n-button
|
||||
></template
|
||||
>
|
||||
<template #tableTitle>
|
||||
<n-space>
|
||||
<n-button
|
||||
type="primary"
|
||||
:disabled="!hasPermission(['/imUserPolicyGroup/edit'])"
|
||||
@click="openEdit()"
|
||||
>新增分组</n-button
|
||||
>
|
||||
<n-button
|
||||
:disabled="!hasPermission(['/imUserPolicyGroup/loginIPWhitelist'])"
|
||||
@click="openLoginIPWhitelist"
|
||||
>
|
||||
<template #icon
|
||||
><n-icon><ShieldCheckmarkOutline /></n-icon
|
||||
></template>
|
||||
IP 白名单
|
||||
</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</n-card>
|
||||
|
||||
<n-modal
|
||||
v-model:show="loginIPVisible"
|
||||
preset="dialog"
|
||||
title="租户渠道 IP 白名单"
|
||||
:show-icon="false"
|
||||
:style="{ width: whitelistDialogWidth }"
|
||||
>
|
||||
<n-form label-placement="top">
|
||||
<n-form-item label="APP 登录白名单">
|
||||
<n-input
|
||||
v-model:value="loginIPForm.appText"
|
||||
type="textarea"
|
||||
:rows="7"
|
||||
placeholder="每行一个 IPv4、IPv6 或 CIDR,例如 203.0.113.10"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Web 登录白名单">
|
||||
<n-input
|
||||
v-model:value="loginIPForm.webText"
|
||||
type="textarea"
|
||||
:rows="7"
|
||||
placeholder="每行一个 IPv4、IPv6 或 CIDR,例如 198.51.100.0/24"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<template #action>
|
||||
<n-space>
|
||||
<n-button @click="loginIPVisible = false">取消</n-button>
|
||||
<n-button
|
||||
type="primary"
|
||||
:disabled="!hasPermission(['/imUserPolicyGroup/loginIPWhitelistSave'])"
|
||||
:loading="submitting"
|
||||
@click="saveLoginIPWhitelist"
|
||||
>确定</n-button
|
||||
>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<n-modal
|
||||
v-model:show="editVisible"
|
||||
preset="dialog"
|
||||
@@ -160,6 +221,7 @@
|
||||
import { useDictStore } from '@/store/modules/dict';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { ShieldCheckmarkOutline } from '@vicons/ionicons5';
|
||||
import { adaModalWidth, adaTableScrollX } from '@/utils/hotgo';
|
||||
import {
|
||||
Delete,
|
||||
@@ -168,6 +230,8 @@
|
||||
MemberAdd,
|
||||
MemberList,
|
||||
MemberRemove,
|
||||
LoginIPWhitelist,
|
||||
LoginIPWhitelistSave,
|
||||
Status,
|
||||
} from '@/api/imUserPolicyGroup';
|
||||
import { columns, defaultPolicy, loadOptions, schemas } from './model';
|
||||
@@ -184,10 +248,18 @@
|
||||
memberTableRef = ref();
|
||||
const editVisible = ref(false),
|
||||
memberVisible = ref(false),
|
||||
loginIPVisible = ref(false),
|
||||
submitting = ref(false),
|
||||
memberUserId = ref<number | null>(null),
|
||||
activeGroupId = ref(0);
|
||||
const dialogWidth = computed(() => adaModalWidth(820));
|
||||
const whitelistDialogWidth = computed(() => adaModalWidth(760));
|
||||
const whitelistSummary = reactive({
|
||||
tenantId: 0,
|
||||
appList: [] as string[],
|
||||
webList: [] as string[],
|
||||
});
|
||||
const loginIPForm = reactive({ appText: '', webText: '' });
|
||||
const statusOptions = dict.getOption('sys_normal_disable');
|
||||
const emptyForm = () => ({
|
||||
id: 0,
|
||||
@@ -214,7 +286,11 @@
|
||||
schemas,
|
||||
});
|
||||
const loadDataTable = (res) => List({ ...searchFormRef.value?.formModel, ...res });
|
||||
const reloadTable = () => actionRef.value?.reload();
|
||||
const currentTenantId = () => Number(searchFormRef.value?.formModel?.tenantId || 0);
|
||||
const reloadTable = () => {
|
||||
actionRef.value?.reload();
|
||||
refreshLoginIPSummary();
|
||||
};
|
||||
const actionColumn = reactive({
|
||||
width: 300,
|
||||
title: '操作',
|
||||
@@ -252,6 +328,52 @@
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
async function fetchLoginIPWhitelist() {
|
||||
const tenantId = currentTenantId();
|
||||
if (userStore.isCompanyDept && tenantId <= 0) {
|
||||
return null;
|
||||
}
|
||||
return await LoginIPWhitelist({ tenantId });
|
||||
}
|
||||
async function refreshLoginIPSummary() {
|
||||
const result = await fetchLoginIPWhitelist();
|
||||
if (!result) {
|
||||
Object.assign(whitelistSummary, { tenantId: 0, appList: [], webList: [] });
|
||||
return;
|
||||
}
|
||||
Object.assign(whitelistSummary, {
|
||||
tenantId: Number(result.tenantId || 0),
|
||||
appList: result.appList || [],
|
||||
webList: result.webList || [],
|
||||
});
|
||||
}
|
||||
async function openLoginIPWhitelist() {
|
||||
const result = await fetchLoginIPWhitelist();
|
||||
if (!result) {
|
||||
message.warning('请先选择具体租户');
|
||||
return;
|
||||
}
|
||||
Object.assign(loginIPForm, {
|
||||
appText: (result.appList || []).join('\n'),
|
||||
webText: (result.webList || []).join('\n'),
|
||||
});
|
||||
loginIPVisible.value = true;
|
||||
}
|
||||
async function saveLoginIPWhitelist() {
|
||||
submitting.value = true;
|
||||
try {
|
||||
await LoginIPWhitelistSave({
|
||||
tenantId: currentTenantId(),
|
||||
appList: lines(loginIPForm.appText),
|
||||
webList: lines(loginIPForm.webText),
|
||||
});
|
||||
message.success('租户渠道 IP 白名单保存成功');
|
||||
loginIPVisible.value = false;
|
||||
await refreshLoginIPSummary();
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
function openEdit(row?: any) {
|
||||
editForm.value = row
|
||||
? {
|
||||
@@ -361,4 +483,7 @@
|
||||
.member-toolbar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.whitelist-summary {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user