|
|
@@ -1,5 +1,6 @@
|
|
|
<template>
|
|
|
- <Navbar title="新建认证源" :is-go-back="true" />
|
|
|
+ <Navbar v-if="isEdit" title="编辑认证源" :is-go-back="true" />
|
|
|
+ <Navbar v-else title="新建认证源" :is-go-back="true" />
|
|
|
<a-card
|
|
|
:bordered="false"
|
|
|
style="margin-top: 20px; box-shadow: 0 2px 4px 0 rgba(54, 58, 80, 0.32)"
|
|
|
@@ -13,11 +14,14 @@
|
|
|
<div class="box">
|
|
|
<div style="display: flex">
|
|
|
<label class="labelStyle">选择认证源 <span style="color: red">*</span></label>
|
|
|
- <ul class="selectUl">
|
|
|
+ <ul class="selectUl" :class="{ notAllowed: isEdit }">
|
|
|
<li
|
|
|
v-for="(item, index) in selectedItem"
|
|
|
:key="index"
|
|
|
- :class="{ active: activeIndex === index }"
|
|
|
+ :class="{
|
|
|
+ active: activeIndex === index,
|
|
|
+ disabled: isEdit,
|
|
|
+ }"
|
|
|
@click="setActiveItem(index)"
|
|
|
>
|
|
|
<img class="picture" :src="item.imgSrc" />
|
|
|
@@ -37,8 +41,10 @@
|
|
|
<div v-else-if="steps[current].contentTemplate === 'Second'">
|
|
|
<a-form
|
|
|
:model="identityInfo"
|
|
|
- :label-col="labelCol"
|
|
|
- :wrapper-col="wrapperCol"
|
|
|
+ :label-col="{ style: { width: '120px' } }"
|
|
|
+ :wrapper-col="{
|
|
|
+ span: 8,
|
|
|
+ }"
|
|
|
autocomplete="off"
|
|
|
>
|
|
|
<a-form-item
|
|
|
@@ -88,180 +94,22 @@
|
|
|
</a-form>
|
|
|
</div>
|
|
|
<div v-else-if="steps[current].contentTemplate === 'Third'">
|
|
|
- <a-form
|
|
|
- name="basic"
|
|
|
- :label-col="labelCol"
|
|
|
- :wrapper-col="wrapperCol"
|
|
|
- :model="identitySetting"
|
|
|
- autocomplete="off"
|
|
|
- >
|
|
|
- <a-form-item
|
|
|
- has-feedback
|
|
|
- label="身份提供商 id"
|
|
|
- name="entityID"
|
|
|
- :rules="[{ required: true, message: '请输入身份提供商 id!' }]"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.entityID"
|
|
|
- placeholder="必填,请输入身份提供商 id"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- has-feedback
|
|
|
- label="SSO 地址"
|
|
|
- name="ssoUrl"
|
|
|
- :rules="[{ required: true, message: '请输入 SSO 地址' }]"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.ssoUrl"
|
|
|
- placeholder="必填,请输入 SSO 地址"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- has-feedback
|
|
|
- label="证书"
|
|
|
- name="certificate"
|
|
|
- :rules="[{ required: true, message: '请输入证书' }]"
|
|
|
- >
|
|
|
- <a-textarea
|
|
|
- v-model:value="identitySetting.certificate"
|
|
|
- :rows="4"
|
|
|
- placeholder="必填,请输入证书"
|
|
|
- @blur="certificateBlur"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- label="退出 URL"
|
|
|
- name="loginOutUrl"
|
|
|
- style="margin-top: 10px"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.loginOutUrl"
|
|
|
- placeholder="非必填,请输入退出 URL"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-form>
|
|
|
+ <BasicConfiguration
|
|
|
+ :form-data="identitySetting"
|
|
|
+ @get-datas="getDatas"
|
|
|
+ />
|
|
|
</div>
|
|
|
<div v-else>
|
|
|
- <div class="proDog-setting">
|
|
|
- <a-form
|
|
|
- name="basic"
|
|
|
- :label-col="{ style: { width: '186px' } }"
|
|
|
- :wrapper-col="wrapperCol"
|
|
|
- :rules="rules"
|
|
|
- :model="identitySetting"
|
|
|
- autocomplete="off"
|
|
|
- >
|
|
|
- <h4>字段配置</h4>
|
|
|
- <a-divider />
|
|
|
- <a-form-item
|
|
|
- label="uid(用户ID)" name="uid"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.uid"
|
|
|
- placeholder="必填,IDP 中用户ID"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- label="userName(用户姓名)" name="userName"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.userName"
|
|
|
- placeholder="必填,IDP 中用户姓名"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- label="userNo(员工编号)" name="userNo"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.userNo"
|
|
|
- placeholder="必填,IDP 中员工编号"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item label="nickName(员工昵称)" name="nickName">
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.nickName"
|
|
|
- placeholder="选填,IDP 中员工昵称"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item label="email(员工邮箱)" name="email">
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.email"
|
|
|
- placeholder="选填,IDP 中员工邮箱"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item label="phoneNumber(员工电话)" name="phoneNumber">
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.phoneNumber"
|
|
|
- placeholder="选填,IDP 中员工电话"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-divider />
|
|
|
- <h4>
|
|
|
- 权限配置
|
|
|
-
|
|
|
-
|
|
|
- <a-button type="link" @click="queryTokenClient">查看登录公司</a-button>
|
|
|
- </h4>
|
|
|
- <a-divider />
|
|
|
- <a-form-item
|
|
|
- label="clientId(公司ID)" name="clientId"
|
|
|
- >
|
|
|
- <a-input-number
|
|
|
- v-model:value="identitySetting.clientId"
|
|
|
- :controls="false"
|
|
|
- style="width: 100%"
|
|
|
- placeholder="必填,IDP 中公司ID"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- label="roleTemplateNo(角色模板)" name="roleTemplateNo"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.roleTemplateNo"
|
|
|
- placeholder="必填,如果有多个角色模板编号,使用逗号分隔"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
-
|
|
|
-
|
|
|
- <a-divider />
|
|
|
- <h4>断言解析配置</h4>
|
|
|
- <a-divider />
|
|
|
- <a-form-item has-feedback label="Prodog 实体ID" name="spEntityID">
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.spEntityID"
|
|
|
- placeholder="必填, Prodog 实体 ID "
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- has-feedback
|
|
|
- label="Prodog断言解析地址"
|
|
|
- name="spAssertionConsumeService"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="identitySetting.spAssertionConsumeService"
|
|
|
- placeholder="必填,Prodog 断言解析地址"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- <a-form-item
|
|
|
- has-feedback
|
|
|
- label="Prodog断言解析成功跳转地址"
|
|
|
- name="spAssertionConsumeSuccessRedirectService"
|
|
|
- >
|
|
|
- <a-input
|
|
|
- v-model:value="
|
|
|
- identitySetting.spAssertionConsumeSuccessRedirectService
|
|
|
- "
|
|
|
- placeholder="必填,Prodog 断言解析成功跳转地址"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-form>
|
|
|
- </div>
|
|
|
+ <AccountAssociation
|
|
|
+ :form-data="identitySetting"
|
|
|
+ :identity-info="identityInfo"
|
|
|
+ @get-datas="getDatas"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="steps-action">
|
|
|
- <a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
|
|
|
<a-button v-if="current === 0" disabled @click="prev"> 上一步 </a-button>
|
|
|
+ <a-button v-if="current === 1" @click="prev"> 上一步 </a-button>
|
|
|
<a-button
|
|
|
v-if="current === 0"
|
|
|
type="primary"
|
|
|
@@ -284,66 +132,33 @@
|
|
|
>
|
|
|
下一步
|
|
|
</a-button>
|
|
|
- <a-button
|
|
|
- v-if="current === 2"
|
|
|
- type="primary"
|
|
|
- style="margin-left: 8px"
|
|
|
- :disabled="
|
|
|
- !identitySetting.entityID ||
|
|
|
- !identitySetting.ssoUrl ||
|
|
|
- !identitySetting.certificate
|
|
|
- ? true
|
|
|
- : false
|
|
|
- "
|
|
|
- @click="next"
|
|
|
- >
|
|
|
- 下一步
|
|
|
- </a-button>
|
|
|
- <a-button
|
|
|
- v-if="current == steps.length - 1"
|
|
|
- type="primary"
|
|
|
- :disabled="
|
|
|
- !identitySetting.spEntityID ||
|
|
|
- !identitySetting.uid ||
|
|
|
- !identitySetting.userName ||
|
|
|
- !identitySetting.userNo ||
|
|
|
- !identitySetting.clientId ||
|
|
|
- !identitySetting.roleTemplateNo ||
|
|
|
- !identitySetting.spEntityID ||
|
|
|
- !identitySetting.spAssertionConsumeService ||
|
|
|
- !identitySetting.spAssertionConsumeSuccessRedirectService ||
|
|
|
- service || redirect ? true : false
|
|
|
- "
|
|
|
- style="margin-left: 8px"
|
|
|
- @click="createIdentity"
|
|
|
- >
|
|
|
- 完成
|
|
|
- </a-button>
|
|
|
</div>
|
|
|
</a-card>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import Common from '../common/Common';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
import { message } from 'ant-design-vue';
|
|
|
import { ref, reactive, onMounted } from 'vue';
|
|
|
-import { useRoute, useRouter } from 'vue-router';
|
|
|
import { getImageSrc } from '../common/image-src';
|
|
|
+import BasicConfiguration from './BasicConfiguration.vue';
|
|
|
+import AccountAssociation from './AccountAssociation.vue';
|
|
|
import {
|
|
|
getBase64,
|
|
|
imageToBase64,
|
|
|
base64toFile,
|
|
|
- saveUpdateAuth,
|
|
|
queryById,
|
|
|
} from './configData.js';
|
|
|
|
|
|
-import TokenClientResource from '../api/base/TokenClientResource.js';
|
|
|
-
|
|
|
-
|
|
|
const route = useRoute();
|
|
|
-const router = useRouter();
|
|
|
const current = ref(0); // 当前步骤
|
|
|
+const logoName = ref(''); // logo 名称
|
|
|
+const isEdit = ref(true); // 是否为编辑
|
|
|
const activeIndex = ref(0); // 所选认证源
|
|
|
+const logoClassName = ref(''); // logo 类名
|
|
|
+const isImage = ref(false); // logo 类型限制
|
|
|
+const isLt300k = ref(false); // logo 大小限制
|
|
|
const logoUrl = ref('/static/assets/client-base-v4/image/logo.png'); // logo地址
|
|
|
// 步骤一步骤二数据
|
|
|
const identityInfo = reactive({
|
|
|
@@ -375,105 +190,20 @@ const identitySetting = ref({
|
|
|
'http://xxxx:xx/index.html#/samlLogin',
|
|
|
});
|
|
|
|
|
|
-const service = ref(false);
|
|
|
-const redirect = ref(false);
|
|
|
-const logoName = ref('');
|
|
|
-const logoClassName = ref('');
|
|
|
-// 设置form样式
|
|
|
-const labelCol = ref({
|
|
|
- style: {
|
|
|
- width: '120px',
|
|
|
- },
|
|
|
-});
|
|
|
-const wrapperCol = ref({
|
|
|
- span: 8,
|
|
|
-});
|
|
|
-// 验证断言解析地址结束字符是否正确
|
|
|
-let validateService = async (_rule, value) => {
|
|
|
- if (!value) {
|
|
|
- return Promise.reject('请输入 Prodog 断言解析地址');
|
|
|
- }
|
|
|
- if (!value.endsWith('/api/saml/sso/${id}')) {
|
|
|
- service.value = true;
|
|
|
- return Promise.reject('断言解析地址必须以/api/saml/sso/${ id }结束');
|
|
|
- } else {
|
|
|
- service.value = false;
|
|
|
- }
|
|
|
-};
|
|
|
-// 验证断言解析成功跳转地址结束字符是否正确
|
|
|
-let redirectService = async (_rule, value) => {
|
|
|
- if (!value) {
|
|
|
- return Promise.reject('请输入 Prodog 断言解析成功跳转地址');
|
|
|
- }
|
|
|
- if (!value.endsWith('index.html#/samlLogin')) {
|
|
|
- redirect.value = true;
|
|
|
- return Promise.reject(
|
|
|
- '断言解析成功跳转地址必须以index.html#/samlLogin结束',
|
|
|
- );
|
|
|
- } else {
|
|
|
- redirect.value = false;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-const rules = {
|
|
|
- uid: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入"用户ID"对应的字段名称',
|
|
|
- },
|
|
|
- ],
|
|
|
- userName: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入"用户姓名"对应的字段名称',
|
|
|
- },
|
|
|
- ],
|
|
|
- userNo: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入"员工编号"对应的字段名称',
|
|
|
- },
|
|
|
- ],
|
|
|
- clientId: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入公司Id',
|
|
|
- },
|
|
|
- ],
|
|
|
- roleTemplateNo: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入角色模板编号',
|
|
|
- },
|
|
|
- ],
|
|
|
- spEntityID: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请输入 Prodog 实体 ID',
|
|
|
- },
|
|
|
- ],
|
|
|
- spAssertionConsumeService: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- validator: validateService,
|
|
|
- trigger: 'change',
|
|
|
- },
|
|
|
- ],
|
|
|
- spAssertionConsumeSuccessRedirectService: [
|
|
|
- {
|
|
|
- required: true,
|
|
|
- validator: redirectService,
|
|
|
- trigger: 'change',
|
|
|
- },
|
|
|
- ],
|
|
|
+const getDatas = datas => {
|
|
|
+ current.value = datas.current;
|
|
|
+ identitySetting.value = datas.formData;
|
|
|
};
|
|
|
|
|
|
// 获取更新Id
|
|
|
onMounted(() => {
|
|
|
const { identityId } = route.query;
|
|
|
if (identityId) {
|
|
|
+ isEdit.value = true;
|
|
|
identityInfo.id = identityId;
|
|
|
queryAuthById(identityId);
|
|
|
+ } else {
|
|
|
+ isEdit.value = false;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
@@ -528,38 +258,17 @@ const imgToBase64 = () => {
|
|
|
identityInfo.file = base64toFile(base64, logoName.value); //base64转File
|
|
|
};
|
|
|
};
|
|
|
-// 新建或更新认证源
|
|
|
-const createIdentity = () => {
|
|
|
- const jsonStr = JSON.stringify(identitySetting.value);
|
|
|
- const formData = new FormData();
|
|
|
- formData.append('attribute', jsonStr);
|
|
|
- formData.append('id', identityInfo.id);
|
|
|
- formData.append('name', identityInfo.name);
|
|
|
- formData.append('logo', identityInfo.file);
|
|
|
- formData.append('active', identityInfo.active);
|
|
|
- formData.append('authType', identityInfo.authType);
|
|
|
- formData.append('description', identityInfo.description);
|
|
|
- saveUpdateAuth(formData).then(
|
|
|
- success => {
|
|
|
- if (success.errorCode === 0) {
|
|
|
- if (!identityInfo.id) {
|
|
|
- message.success('新建认证源成功!');
|
|
|
- } else {
|
|
|
- message.success('更新认证源成功!');
|
|
|
- }
|
|
|
- router.push('/desktop/identityManager');
|
|
|
- } else {
|
|
|
- message.error(success.errorMessage);
|
|
|
- }
|
|
|
- },
|
|
|
- error => {
|
|
|
- Common.processException(error);
|
|
|
- },
|
|
|
- );
|
|
|
-};
|
|
|
|
|
|
// 获取logo文件
|
|
|
const logoFileChange = async e => {
|
|
|
+ if(!isImage.value){
|
|
|
+ message.warning('请上传图片类型的logo!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!isLt300k.value) {
|
|
|
+ message.warning('logo大小不得超过300KB,请重新选择logo!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
identityInfo.file = e.file;
|
|
|
logoUrl.value = await getBase64(e.fileList[0].originFileObj);
|
|
|
};
|
|
|
@@ -572,13 +281,10 @@ const deleteLogo = () => {
|
|
|
message.warning('请上传logo!');
|
|
|
};
|
|
|
|
|
|
-// 证书base64格式失去焦点后清除空格换行、回车
|
|
|
-const certificateBlur = e => {
|
|
|
- identitySetting.value.certificate = e.target.value.replace(/[\s\n\r]+/g, '');
|
|
|
-};
|
|
|
-
|
|
|
// 禁用antd自动上传
|
|
|
-const beforeUpload = () => {
|
|
|
+const beforeUpload = file => {
|
|
|
+ isImage.value = file.type.includes('image');
|
|
|
+ isLt300k.value = file.size / 1024 < 300;
|
|
|
return false;
|
|
|
};
|
|
|
|
|
|
@@ -633,22 +339,6 @@ const setActiveItem = index => {
|
|
|
identityInfo.authType = 'SAML';
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * 查询设置的公司
|
|
|
- */
|
|
|
-const queryTokenClient = function () {
|
|
|
- TokenClientResource.queryTokenClient().then(baseObjectResponse => {
|
|
|
- if (baseObjectResponse.errorCode == 0) {
|
|
|
- message.success('当前登录公司id:'+ baseObjectResponse.data.clientId + '。公司名称:' + baseObjectResponse.data.clientName);
|
|
|
- }
|
|
|
- }, errorData => {
|
|
|
- Common.processException(errorData);
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
@@ -748,8 +438,16 @@ const queryTokenClient = function () {
|
|
|
.ant-form-item {
|
|
|
margin-bottom: 4px;
|
|
|
}
|
|
|
-.proDog-setting > h3 {
|
|
|
- font-size: 14px !important;
|
|
|
- font-weight: 700;
|
|
|
+.ant-divider-horizontal {
|
|
|
+ margin: 0 0 5px 0 !important;
|
|
|
+}
|
|
|
+.notAllowed {
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+.disabled {
|
|
|
+ color: gray;
|
|
|
+ background: #e6eaeb;
|
|
|
+ /* cursor: not-allowed; */
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
</style>
|