1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 22:18:07 +08:00

fix: 密码放到面板设置界面

This commit is contained in:
ssongliu 2023-02-14 18:15:10 +08:00 committed by ssongliu
parent eb2bfb80cf
commit 97c4410227
11 changed files with 176 additions and 143 deletions

View File

@ -131,7 +131,7 @@ const getTitle = (key: string) => {
case 'nginx': case 'nginx':
return i18n.global.t('website.website'); return i18n.global.t('website.website');
case 'mysql': case 'mysql':
return 'Mysql ' + i18n.global.t('menu.database'); return 'MySQL ' + i18n.global.t('menu.database');
case 'redis': case 'redis':
return 'Redis ' + i18n.global.t('menu.database'); return 'Redis ' + i18n.global.t('menu.database');
} }

View File

@ -256,7 +256,7 @@ export default {
backupList: 'Backup list', backupList: 'Backup list',
backList: 'Return', backList: 'Return',
loadBackup: 'Import the backup', loadBackup: 'Import the backup',
setting: 'Mysql Settings', setting: 'MySQL Settings',
remoteAccess: 'Remote access', remoteAccess: 'Remote access',
changePassword: 'Password change', changePassword: 'Password change',
changePasswordHelper: changePasswordHelper:

View File

@ -19,7 +19,7 @@ const databaseRouter = {
children: [ children: [
{ {
path: 'mysql', path: 'mysql',
name: 'Mysql', name: 'MySQL',
component: () => import('@/views/database/mysql/index.vue'), component: () => import('@/views/database/mysql/index.vue'),
hidden: true, hidden: true,
meta: { meta: {

View File

@ -61,7 +61,7 @@ const toPage = (key: string) => {
router.push({ name: 'Website' }); router.push({ name: 'Website' });
} }
if (key === 'database') { if (key === 'database') {
router.push({ name: 'Mysql' }); router.push({ name: 'MySQL' });
} }
}; };

View File

@ -13,7 +13,7 @@ import RouterButton from '@/components/router-button/index.vue';
const buttons = [ const buttons = [
{ {
label: 'Mysql', label: 'MySQL',
path: '/databases/mysql', path: '/databases/mysql',
}, },
{ {

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<LayoutContent :title="'Mysql ' + $t('menu.database')"> <LayoutContent :title="'MySQL ' + $t('menu.database')">
<template #app> <template #app>
<AppStatus <AppStatus
:app-key="'mysql'" :app-key="'mysql'"
@ -112,7 +112,7 @@
v-if="mysqlStatus != 'Running' && !isOnSetting && mysqlIsExist && !loading" v-if="mysqlStatus != 'Running' && !isOnSetting && mysqlIsExist && !loading"
class="mask-prompt" class="mask-prompt"
> >
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Mysql']) }}</span> <span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['MySQL']) }}</span>
</el-card> </el-card>
<Setting ref="settingRef" style="margin-top: 20px" /> <Setting ref="settingRef" style="margin-top: 20px" />

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-show="onSetting"> <div v-show="onSetting">
<LayoutContent :title="'Mysql ' + $t('database.setting')" :reload="true"> <LayoutContent :title="'MySQL ' + $t('database.setting')" :reload="true">
<template #buttons> <template #buttons>
<el-button type="primary" :plain="activeName !== 'conf'" @click="changeTab('conf')"> <el-button type="primary" :plain="activeName !== 'conf'" @click="changeTab('conf')">
{{ $t('database.confChange') }} {{ $t('database.confChange') }}

View File

@ -19,6 +19,16 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('setting.passwd')" :rules="Rules.requiredInput" prop="password">
<el-input type="password" clearable disabled v-model="form.password">
<template #append>
<el-button icon="Setting" @click="onChangePassword">
{{ $t('commons.button.set') }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="theme"> <el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="theme">
<el-radio-group <el-radio-group
@change="onSave(panelFormRef, 'Theme', form.theme)" @change="onSave(panelFormRef, 'Theme', form.theme)"
@ -96,6 +106,7 @@
</el-form> </el-form>
</template> </template>
</LayoutContent> </LayoutContent>
<Password ref="passwordRef" />
</div> </div>
</template> </template>
@ -109,6 +120,7 @@ import { GlobalStore } from '@/store';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useTheme } from '@/hooks/use-theme'; import { useTheme } from '@/hooks/use-theme';
import { MsgError, MsgSuccess } from '@/utils/message'; import { MsgError, MsgSuccess } from '@/utils/message';
import Password from '@/views/setting/panel/password/index.vue';
const loading = ref(false); const loading = ref(false);
const i18n = useI18n(); const i18n = useI18n();
@ -120,6 +132,7 @@ type FormInstance = InstanceType<typeof ElForm>;
const form = reactive({ const form = reactive({
userName: '', userName: '',
password: '',
email: '', email: '',
sessionTimeout: 0, sessionTimeout: 0,
localTime: '', localTime: '',
@ -134,9 +147,12 @@ const TIME_COUNT = ref(10);
const count = ref(); const count = ref();
const show = ref(); const show = ref();
const passwordRef = ref();
const search = async () => { const search = async () => {
const res = await getSettingInfo(); const res = await getSettingInfo();
form.userName = res.data.userName; form.userName = res.data.userName;
form.password = '******';
form.sessionTimeout = Number(res.data.sessionTimeout); form.sessionTimeout = Number(res.data.sessionTimeout);
form.localTime = res.data.localTime; form.localTime = res.data.localTime;
form.panelName = res.data.panelName; form.panelName = res.data.panelName;
@ -146,6 +162,10 @@ const search = async () => {
}; };
const panelFormRef = ref<FormInstance>(); const panelFormRef = ref<FormInstance>();
const onChangePassword = () => {
passwordRef.value.acceptParams({ complexityVerification: form.complexityVerification });
};
const onSave = async (formEl: FormInstance | undefined, key: string, val: any) => { const onSave = async (formEl: FormInstance | undefined, key: string, val: any) => {
if (!formEl) return; if (!formEl) return;
const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback); const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback);

View File

@ -0,0 +1,134 @@
<template>
<div v-loading="loading">
<el-drawer v-model="passwordVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('setting.changePassword')" :back="handleClose" />
</template>
<el-form ref="passFormRef" label-position="top" :model="passForm" :rules="passRules">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
</el-form-item>
<el-form-item
v-if="complexityVerification === 'disable'"
:label="$t('setting.newPassword')"
prop="newPassword"
>
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
</el-form-item>
<el-form-item
v-if="complexityVerification === 'enable'"
:label="$t('setting.newPassword')"
prop="newPasswordComplexity"
>
<el-input
type="password"
show-password
clearable
v-model="passForm.newPasswordComplexity"
/>
</el-form-item>
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="passwordVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="submitChangePassword(passFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import router from '@/routers';
import { MsgError, MsgSuccess } from '@/utils/message';
import { FormInstance } from 'element-plus';
import { GlobalStore } from '@/store';
import { reactive, ref } from 'vue';
import { updatePassword } from '@/api/modules/setting';
const globalStore = GlobalStore();
const passFormRef = ref<FormInstance>();
const passRules = reactive({
oldPassword: [Rules.requiredInput],
newPassword: [
Rules.requiredInput,
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
],
newPasswordComplexity: [Rules.requiredInput, Rules.password],
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
});
const loading = ref(false);
const passwordVisiable = ref<boolean>(false);
const passForm = reactive({
oldPassword: '',
newPassword: '',
newPasswordComplexity: '',
retryPassword: '',
});
const complexityVerification = ref();
interface DialogProps {
complexityVerification: string;
}
const acceptParams = (params: DialogProps): void => {
complexityVerification.value = params.complexityVerification;
passForm.oldPassword = '';
passForm.newPassword = '';
passForm.newPasswordComplexity = '';
passForm.retryPassword = '';
passwordVisiable.value = true;
};
function checkPassword(rule: any, value: any, callback: any) {
let password = complexityVerification.value === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
if (password !== passForm.retryPassword) {
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
}
callback();
}
const submitChangePassword = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let password =
complexityVerification.value === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
if (password === passForm.oldPassword) {
MsgError(i18n.global.t('setting.duplicatePassword'));
return;
}
loading.value = true;
await updatePassword({ oldPassword: passForm.oldPassword, newPassword: password })
.then(() => {
loading.value = false;
passwordVisiable.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
router.push({ name: 'login', params: { code: '' } });
globalStore.setLogStatus(false);
})
.catch(() => {
loading.value = false;
});
});
};
const handleClose = () => {
passwordVisiable.value = false;
};
defineExpose({
acceptParams,
});
</script>

View File

@ -6,16 +6,6 @@
<el-row> <el-row>
<el-col :span="1"><br /></el-col> <el-col :span="1"><br /></el-col>
<el-col :span="10"> <el-col :span="10">
<el-form-item :label="$t('setting.passwd')" :rules="Rules.requiredInput" prop="password">
<el-input type="password" clearable disabled v-model="form.password">
<template #append>
<el-button icon="Setting" @click="onChangePassword">
{{ $t('commons.button.set') }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('setting.panelPort')" :rules="Rules.port" prop="serverPort"> <el-form-item :label="$t('setting.panelPort')" :rules="Rules.port" prop="serverPort">
<el-input clearable v-model.number="form.serverPort"> <el-input clearable v-model.number="form.serverPort">
<template #append> <template #append>
@ -118,14 +108,11 @@
</el-form> </el-form>
</template> </template>
</LayoutContent> </LayoutContent>
<el-dialog <el-drawer v-model="timeoutVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
v-model="timeoutVisiable" <template #header>
:destroy-on-close="true" <DrawerHeader :header="$t('setting.expirationTime')" :back="handleClose" />
:close-on-click-modal="false" </template>
:title="$t('setting.expirationTime')" <el-form ref="timeoutFormRef" label-position="top" :model="timeoutForm">
width="30%"
>
<el-form ref="timeoutFormRef" label-width="80px" label-position="left" :model="timeoutForm">
<el-form-item :label="$t('setting.days')" prop="days" :rules="Rules.number"> <el-form-item :label="$t('setting.days')" prop="days" :rules="Rules.number">
<el-input clearable v-model.number="timeoutForm.days" /> <el-input clearable v-model.number="timeoutForm.days" />
<span class="input-help">{{ $t('setting.expirationHelper') }}</span> <span class="input-help">{{ $t('setting.expirationHelper') }}</span>
@ -139,54 +126,7 @@
</el-button> </el-button>
</span> </span>
</template> </template>
</el-dialog> </el-drawer>
<el-dialog
v-model="passwordVisiable"
:destroy-on-close="true"
:close-on-click-modal="false"
:title="$t('setting.changePassword')"
width="30%"
>
<el-form
v-loading="dialogLoading"
ref="passFormRef"
label-width="80px"
label-position="left"
:model="passForm"
:rules="passRules"
>
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
</el-form-item>
<el-form-item
v-if="form.complexityVerification === 'disable'"
:label="$t('setting.newPassword')"
prop="newPassword"
>
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
</el-form-item>
<el-form-item
v-if="form.complexityVerification === 'enable'"
:label="$t('setting.newPassword')"
prop="newPasswordComplexity"
>
<el-input type="password" show-password clearable v-model="passForm.newPasswordComplexity" />
</el-form-item>
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="dialogLoading" @click="passwordVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="dialogLoading" type="primary" @click="submitChangePassword(passFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</div> </div>
</template> </template>
@ -195,37 +135,15 @@ import { ref, reactive, onMounted } from 'vue';
import { ElForm, ElMessageBox } from 'element-plus'; import { ElForm, ElMessageBox } from 'element-plus';
import { Setting } from '@/api/interface/setting'; import { Setting } from '@/api/interface/setting';
import LayoutContent from '@/layout/layout-content.vue'; import LayoutContent from '@/layout/layout-content.vue';
import { updatePassword, updateSetting, getMFA, bindMFA, getSettingInfo, updatePort } from '@/api/modules/setting'; import DrawerHeader from '@/components/drawer-header/index.vue';
import { updateSetting, getMFA, bindMFA, getSettingInfo, updatePort } from '@/api/modules/setting';
import i18n from '@/lang'; import i18n from '@/lang';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import { dateFormatSimple } from '@/utils/util'; import { dateFormatSimple } from '@/utils/util';
import { GlobalStore } from '@/store'; import { MsgSuccess } from '@/utils/message';
import router from '@/routers';
import { MsgError, MsgSuccess } from '@/utils/message';
const loading = ref(false); const loading = ref(false);
const globalStore = GlobalStore();
const passFormRef = ref<FormInstance>();
const passRules = reactive({
oldPassword: [Rules.requiredInput],
newPassword: [
Rules.requiredInput,
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
],
newPasswordComplexity: [Rules.requiredInput, Rules.password],
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
});
const dialogLoading = ref(false);
const passwordVisiable = ref<boolean>(false);
const passForm = reactive({
oldPassword: '',
newPassword: '',
newPasswordComplexity: '',
retryPassword: '',
});
const form = reactive({ const form = reactive({
password: '',
serverPort: 9999, serverPort: 9999,
securityEntrance: '', securityEntrance: '',
expirationDays: 0, expirationDays: 0,
@ -243,7 +161,6 @@ const timeoutForm = reactive({
const search = async () => { const search = async () => {
const res = await getSettingInfo(); const res = await getSettingInfo();
form.password = '******';
form.serverPort = Number(res.data.serverPort); form.serverPort = Number(res.data.serverPort);
form.securityEntrance = res.data.securityEntrance; form.securityEntrance = res.data.securityEntrance;
form.expirationDays = Number(res.data.expirationDays); form.expirationDays = Number(res.data.expirationDays);
@ -292,14 +209,6 @@ function callback(error: any) {
return; return;
} }
} }
function checkPassword(rule: any, value: any, callback: any) {
let password = form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
if (password !== passForm.retryPassword) {
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
}
callback();
}
const onSavePort = async (formEl: FormInstance | undefined, key: string, val: any) => { const onSavePort = async (formEl: FormInstance | undefined, key: string, val: any) => {
if (!formEl) return; if (!formEl) return;
const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback); const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback);
@ -328,40 +237,6 @@ const onSavePort = async (formEl: FormInstance | undefined, key: string, val: an
}); });
}); });
}; };
const onChangePassword = async () => {
passForm.oldPassword = '';
passForm.newPassword = '';
passForm.newPasswordComplexity = '';
passForm.retryPassword = '';
passwordVisiable.value = true;
};
const submitChangePassword = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let password =
form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
if (password === passForm.oldPassword) {
MsgError(i18n.global.t('setting.duplicatePassword'));
return;
}
dialogLoading.value = true;
await updatePassword({ oldPassword: passForm.oldPassword, newPassword: password })
.then(() => {
dialogLoading.value = false;
passwordVisiable.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
router.push({ name: 'login', params: { code: '' } });
globalStore.setLogStatus(false);
})
.catch(() => {
dialogLoading.value = false;
});
});
};
const handleMFA = async () => { const handleMFA = async () => {
console.log('dawdwda'); console.log('dawdwda');
if (form.mfaStatus === 'enable') { if (form.mfaStatus === 'enable') {
@ -384,6 +259,10 @@ const handleMFA = async () => {
} }
}; };
const handleClose = () => {
timeoutVisiable.value = false;
};
const onBind = async () => { const onBind = async () => {
loading.value = true; loading.value = true;
await bindMFA({ code: mfaCode.value, secret: otp.secret }) await bindMFA({ code: mfaCode.value, secret: otp.secret })

2
go.mod
View File

@ -5,6 +5,7 @@ go 1.18
require ( require (
gitee.com/openeuler/go-gitee v0.0.0-20220530104019-3af895bc380c gitee.com/openeuler/go-gitee v0.0.0-20220530104019-3af895bc380c
github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible
github.com/antihax/optional v1.0.0
github.com/aws/aws-sdk-go v1.44.99 github.com/aws/aws-sdk-go v1.44.99
github.com/compose-spec/compose-go v1.6.0 github.com/compose-spec/compose-go v1.6.0
github.com/creack/pty v1.1.18 github.com/creack/pty v1.1.18
@ -63,7 +64,6 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/antihax/optional v1.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect