Compare commits

...
14 Commits
Author SHA1 Message Date
ssongliu 0ed5ae71c5 feat: OneDrive 授权码增加格式校验 (#2614)
Refs #2610
2023-10-22 08:43:44 +08:00
ssongliu a2bfa5acaa feat: 解决容器编辑内存限额失败的问题 (#2607)
Refs #2608
2023-10-22 08:43:27 +08:00
ssongliu 609aa04aba fix: 系统用户名、密码增加空格校验 (#2604)
Refs #2602
2023-10-22 08:43:07 +08:00
ssongliu 0b5b90d0c5 fix: 同步数据库时,忽略 recycle_bin (#2591)
Refs #2589
2023-10-22 08:42:41 +08:00
ssongliu 0449100e23 fix: 解决容器设置 host 网络失败的问题 (#2582)
Refs #2550
2023-10-22 08:42:13 +08:00
ssongliu 5f009152d3 feat: SSH 登陆日志适配 Debian12 (#2567)
Refs #2367
2023-10-22 08:41:22 +08:00
zhengkunwang 51ca89daba fix: 解决容器没有 entrypoint 无法打开编辑页面的问题 (#2554) 2023-10-14 10:55:51 -05:00
zhengkunwang 99951029c8 feat: 容器编辑提示增加判断条件 (#2553) 2023-10-14 10:53:57 -05:00
wanghe-fit2cloud 2d2869d184 chore: 更新 README 2023-10-14 09:29:38 +08:00
zhengkunwang 9d85d52005 fix: 解决证书详情页其他域名一直为空的问题 (#2542)
Refs https://github.com/1Panel-dev/1Panel/issues/2539
2023-10-13 10:14:11 +00:00
wanghe b2ce2c86fb feat: add sonar cloud scan (#2540) 2023-10-13 04:44:14 -05:00
ssongliu 1f92324a45 feat: 容器编辑增加提示信息 (#2529) 2023-10-12 13:58:32 +00:00
zhengkunwang 2031295ba4 feat: Node.js 环境增加下载统计 (#2528) 2023-10-12 10:00:38 +00:00
zhengkunwang f079050545 fix: 解决反向代理网站在 firefox 浏览器打开失败的问题 (#2525)
Refs https://github.com/1Panel-dev/1Panel/issues/1465
2023-10-12 09:58:38 +00:00
21 changed files with 279 additions and 100 deletions
+20
View File
@@ -0,0 +1,20 @@
name: Build
on:
push:
branches:
- dev
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+5
View File
@@ -867,6 +867,10 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
config.Tty = req.Tty
if len(req.Network) != 0 {
switch req.Network {
case "host", "none", "bridge":
hostConf.NetworkMode = container.NetworkMode(req.Network)
}
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
} else {
networkConf = network.NetworkingConfig{}
@@ -881,6 +885,7 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
}
hostConf.NanoCPUs = int64(req.NanoCPUs * 1000000000)
hostConf.Memory = int64(req.Memory * 1024 * 1024)
hostConf.MemorySwap = 0
hostConf.PortBindings = portMap
hostConf.Binds = []string{}
config.Volumes = make(map[string]struct{})
+10
View File
@@ -13,6 +13,7 @@ import (
"github.com/pkg/errors"
"github.com/subosito/gotenv"
"io"
"net/http"
"os"
"os/exec"
"path"
@@ -45,7 +46,16 @@ func handleNode(create request.RuntimeCreate, runtime *model.Runtime, fileOp fil
runtime.Status = constant.RuntimeCreating
runtime.CodeDir = create.CodeDir
nodeDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID))
if err != nil {
return err
}
go func() {
_, _ = http.Get(nodeDetail.DownloadCallBackUrl)
}()
go startRuntime(runtime)
return
}
+92 -36
View File
@@ -287,9 +287,9 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
case constant.StatusSuccess:
commandItem = fmt.Sprintf("cat %s | grep -a Accepted %s", file.Name, command)
case constant.StatusFailed:
commandItem = fmt.Sprintf("cat %s | grep -a 'Connection closed by authenticating user' | grep -a 'preauth' %s", file.Name, command)
commandItem = fmt.Sprintf("cat %s | grep -aE 'Failed password for|Connection closed by authenticating user' | grep -a 'preauth' %s", file.Name, command)
default:
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Connection closed by authenticating user|Accepted)\" | grep -v 'invalid' %s", file.Name, command)
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Failed password for|Connection closed by authenticating user|Accepted)\" | grep -v 'invalid' %s", file.Name, command)
}
}
dataItem, successCount, failedCount := loadSSHData(commandItem, showCountFrom, showCountTo, file.Year, qqWry, nyc)
@@ -466,7 +466,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
if len(itemData.Address) != 0 {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
itemData.Area = qqWry.Find(itemData.Address).Area
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
}
failedCount++
@@ -476,7 +476,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
if len(itemData.Address) != 0 {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
itemData.Area = qqWry.Find(itemData.Address).Area
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
}
failedCount++
@@ -486,7 +486,7 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
if len(itemData.Address) != 0 {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
itemData.Area = qqWry.Find(itemData.Address).Area
itemData.Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, itemData.DateStr), nyc)
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
}
successCount++
@@ -540,16 +540,31 @@ func loadSSHDataForAnalysis(analysisMap map[string]dto.SSHLogAnalysis, commandIt
func loadSuccessDatas(line string) dto.SSHHistory {
var data dto.SSHHistory
parts := strings.Fields(line)
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[6],
User: parts[8],
Address: parts[10],
Port: parts[12],
Status: constant.StatusSuccess,
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
if err != nil {
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[6],
User: parts[8],
Address: parts[10],
Port: parts[12],
Status: constant.StatusSuccess,
}
} else {
if len(parts) < 12 {
return data
}
data = dto.SSHHistory{
DateStr: t.Format("2006 Jan 2 15:04:05"),
AuthMode: parts[4],
User: parts[6],
Address: parts[8],
Port: parts[10],
Status: constant.StatusSuccess,
}
}
return data
}
@@ -557,16 +572,31 @@ func loadSuccessDatas(line string) dto.SSHHistory {
func loadFailedAuthDatas(line string) dto.SSHHistory {
var data dto.SSHHistory
parts := strings.Fields(line)
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[8],
User: parts[10],
Address: parts[11],
Port: parts[13],
Status: constant.StatusFailed,
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
if err != nil {
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[8],
User: parts[10],
Address: parts[11],
Port: parts[13],
Status: constant.StatusFailed,
}
} else {
if len(parts) < 12 {
return data
}
data = dto.SSHHistory{
DateStr: t.Format("2006 Jan 2 15:04:05"),
AuthMode: parts[6],
User: parts[7],
Address: parts[9],
Port: parts[11],
Status: constant.StatusFailed,
}
}
if strings.Contains(line, ": ") {
data.Message = strings.Split(line, ": ")[1]
@@ -577,21 +607,39 @@ func loadFailedAuthDatas(line string) dto.SSHHistory {
func loadFailedSecureDatas(line string) dto.SSHHistory {
var data dto.SSHHistory
parts := strings.Fields(line)
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[6],
User: parts[8],
Address: parts[10],
Port: parts[12],
Status: constant.StatusFailed,
t, err := time.Parse("2006-01-02T15:04:05.999999-07:00", parts[0])
if err != nil {
if len(parts) < 14 {
return data
}
data = dto.SSHHistory{
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
AuthMode: parts[6],
User: parts[8],
Address: parts[10],
Port: parts[12],
Status: constant.StatusFailed,
}
} else {
if len(parts) < 12 {
return data
}
index := 0
if strings.Contains("line", " invalid user") {
index = 2
}
data = dto.SSHHistory{
DateStr: t.Format("2006 Jan 2 15:04:05"),
AuthMode: parts[4],
User: parts[index+6],
Address: parts[index+8],
Port: parts[index+10],
Status: constant.StatusFailed,
}
}
if strings.Contains(line, ": ") {
data.Message = strings.Split(line, ": ")[1]
}
return data
}
@@ -610,3 +658,11 @@ func loadServiceName() (string, error) {
}
return "", errors.New("The ssh or sshd service is unavailable")
}
func loadDate(currentYear int, DateStr string, nyc *time.Location) time.Time {
itemDate, err := time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", currentYear, DateStr), nyc)
if err != nil {
itemDate, _ = time.ParseInLocation("2006 Jan 2 15:04:05", DateStr, nyc)
}
return itemDate
}
+1 -1
View File
@@ -269,7 +269,7 @@ func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) {
if len(parts) != 2 {
continue
}
if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" {
if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" || parts[0] == "recycle_bin" {
continue
}
dataItem := SyncDBInfo{
+1 -1
View File
@@ -279,7 +279,7 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) {
if err = rows.Scan(&dbName, &charsetName); err != nil {
return datas, err
}
if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" {
if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" || dbName == "recycle_bin" {
continue
}
dataItem := SyncDBInfo{
+2
View File
@@ -8,3 +8,5 @@ ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
proxy_set_header X-Forwarded-Proto https;
ssl_stapling on;
ssl_stapling_verify on;
+2 -1
View File
@@ -15,7 +15,8 @@
- **Quick website building**: Deeply integrated with Wordpress and [Halo](https://github.com/halo-dev/halo/), with one-click solutions for domain name binding, SSL certificate configuration, and more;
- **Efficient management**: Easily manage Linux servers through the web interface, including application management, host monitoring, file management, database management, container management, and more;
- **Secure and reliable**: Minimal vulnerability exposure, with firewall and security audit functions provided;
- **One-click backup**: Support for one-click backup and restore, with backup data stored in the cloud and never lost.
- **One-click backup**: Support for one-click backup and restore, with backup data stored in the cloud and never lost;
- **App Store**: Curate a variety of high-quality open-source tools and application software, enabling you to easily install and upgrade them.
## UI Display
+2 -1
View File
@@ -15,7 +15,8 @@
- **素早いウェブサイト構築**: Wordpress および [Halo](https://github.com/halo-dev/halo/) と深く統合されており、ドメイン名のバインディング、SSL 証明書の設定など、ワンクリックで解決できます;
- **効率的なマネジメント**: アプリケーション管理、ホスト監視、ファイル管理、データベース管理、コンテナ管理など、web インターフェイスを通じて Linux サーバーを簡単に管理できます;
- **安全性と信頼性**: ファイアウォールとセキュリティ監査機能により、脆弱性の露出を最小限に抑えます;
- **ワンクリックバックアップ**: ワンクリックでのバックアップと復元をサポートし、バックアップデータはクラウドに保存され、失われることはありません。
- **ワンクリックバックアップ**: ワンクリックでのバックアップと復元をサポートし、バックアップデータはクラウドに保存され、失われることはありません;
- **アプリストア**: さまざまな種類の高品質なオープンソースツールとアプリケーションソフトウェアを厳選し、インストールとアップグレードを容易にサポートします。
## UI ディスプレイ
+2 -1
View File
@@ -16,7 +16,8 @@
- **快速建站**:深度集成 Wordpress 和 [Halo](https://github.com/halo-dev/halo/),域名綁定、SSL 證書配置等一鍵搞定;
- **高效管理**:通過 Web 端輕鬆管理 Linux 服務器,包括主機監控、文件管理、數據庫管理、容器管理等;
- **安全可靠**:基於容器來管理和部署應用,最小漏洞暴露面,提供防火牆和日誌審計等功能;
- **一鍵備份**:支持一鍵備份和恢復,備份數據到各類雲端存儲,永不丟失。
- **一鍵備份**:支持一鍵備份和恢復,備份數據到各類雲端存儲,永不丟失;
- **應用商店**:精選各類高質量開源工具和應用軟件,助力您輕鬆安裝和升級。
## UI 展示
+13
View File
@@ -1,6 +1,13 @@
import i18n from '@/lang';
import { FormItemRule } from 'element-plus';
const checkNoSpace = (rule: any, value: any, callback: any) => {
if (value.indexOf(' ') !== -1) {
return callback(new Error(i18n.global.t('setting.noSpace')));
}
callback();
};
const checkIp = (rule: any, value: any, callback: any) => {
if (value === '' || typeof value === 'undefined' || value == null) {
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
@@ -431,6 +438,7 @@ interface CommonRule {
requiredInput: FormItemRule;
requiredSelect: FormItemRule;
requiredSelectBusiness: FormItemRule;
noSpace: FormItemRule;
name: FormItemRule;
userName: FormItemRule;
simpleName: FormItemRule;
@@ -484,6 +492,11 @@ export const Rules: CommonRule = {
message: i18n.global.t('commons.rule.requiredSelect'),
trigger: 'change',
},
noSpace: {
required: true,
validator: checkNoSpace,
trigger: 'blur',
},
simpleName: {
required: true,
validator: checkSimpleName,
+4
View File
@@ -546,6 +546,8 @@ const message = {
cpuShareHelper:
'The default CPU share for a container is 1024, which can be increased to give the container more CPU time.',
containerFromAppHelper:
'Detected that this container originates from the app store. App operations may cause current edits to be invalidated.',
command: 'Command',
console: 'Console Interaction',
tty: 'TTY (-t)',
@@ -1048,6 +1050,7 @@ const message = {
oldPassword: 'Original password',
newPassword: 'New password',
retryPassword: 'Confirm password',
noSpace: 'Input information cannot include space characters',
duplicatePassword: 'The new password cannot be the same as the original password, please re-enter!',
diskClean: 'Cache Clean',
@@ -1062,6 +1065,7 @@ const message = {
SFTP: 'SFTP',
OneDrive: 'Microsoft OneDrive',
backupDir: 'Backup dir',
codeWarning: 'The current authorization code format is incorrect, please confirm again!',
isCN: 'Domestic version',
code: 'Auth code',
codeHelper:
+3
View File
@@ -532,6 +532,7 @@ const message = {
cpuShare: 'CPU 權重',
cpuShareHelper: '容器默認份額為 1024 個 CPU,增大可使當前容器獲得更多的 CPU 時間',
containerFromAppHelper: '檢測到該容器來源於應用商店,應用操作可能會導致當前編輯失效',
command: '命令',
console: '控製臺交互',
tty: '偽終端 ( -t )',
@@ -1005,6 +1006,7 @@ const message = {
oldPassword: '原密碼',
newPassword: '新密碼',
retryPassword: '確認密碼',
noSpace: '輸入信息不能包括空格符號',
duplicatePassword: '新密碼不能與原始密碼一致,請重新輸入!',
diskClean: '缓存清理',
@@ -1018,6 +1020,7 @@ const message = {
MINIO: 'MINIO',
SFTP: 'SFTP',
OneDrive: '微軟 OneDrive',
codeWarning: '當前授權碼格式錯誤,請重新確認!',
backupDir: '備份路徑',
isCN: '國內版',
code: '授權碼',
+3
View File
@@ -532,6 +532,7 @@ const message = {
cpuShare: 'CPU 权重',
cpuShareHelper: '容器默认份额为 1024 个 CPU,增大可使当前容器获得更多的 CPU 时间',
containerFromAppHelper: '检测到该容器来源于应用商店,应用操作可能会导致当前编辑失效',
command: '命令',
console: '控制台交互',
tty: '伪终端 ( -t )',
@@ -1005,6 +1006,7 @@ const message = {
oldPassword: '原密码',
newPassword: '新密码',
retryPassword: '确认密码',
noSpace: '输入信息不能包含空格符',
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
diskClean: '缓存清理',
@@ -1018,6 +1020,7 @@ const message = {
MINIO: 'MINIO',
SFTP: 'SFTP',
OneDrive: '微软 OneDrive',
codeWarning: '当前授权码格式错误,请重新确认!',
backupDir: '备份路径',
isCN: '国内版',
code: '授权码',
@@ -24,6 +24,13 @@
>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-alert
v-if="dialogData.title === 'edit' && isFromApp(dialogData.rowData!)"
:title="$t('container.containerFromAppHelper')"
class="common-prompt"
:closable="false"
type="error"
/>
<el-form-item :label="$t('commons.table.name')" prop="name">
<el-input clearable v-model.trim="dialogData.rowData!.name" />
</el-form-item>
@@ -171,7 +178,7 @@
<el-form-item label="Command" prop="cmdStr">
<el-input v-model="dialogData.rowData!.cmdStr" :placeholder="$t('container.cmdHelper')" />
</el-form-item>
<el-form-item label="Entrypoint" prop="entrypoint">
<el-form-item label="Entrypoint" prop="entrypointStr">
<el-input
v-model="dialogData.rowData!.entrypointStr"
:placeholder="$t('container.entrypointHelper')"
@@ -295,9 +302,17 @@ const acceptParams = (params: DialogProps): void => {
itemCmd += `'${item}' `;
}
dialogData.value.rowData.cmdStr = itemCmd ? itemCmd.substring(0, itemCmd.length - 1) : '';
if (dialogData.value.rowData.entrypoint) {
dialogData.value.rowData.entrypointStr = dialogData.value.rowData.entrypoint.join(' ');
let itemEntrypoint = '';
if (dialogData.value.rowData?.entrypoint) {
for (const item of dialogData.value.rowData.entrypoint) {
itemEntrypoint += `'${item}' `;
}
}
dialogData.value.rowData.entrypointStr = itemEntrypoint
? itemEntrypoint.substring(0, itemEntrypoint.length - 1)
: '';
dialogData.value.rowData.labels = dialogData.value.rowData.labels || [];
dialogData.value.rowData.env = dialogData.value.rowData.env || [];
dialogData.value.rowData.labelsStr = dialogData.value.rowData.labels.join('\n');
@@ -435,8 +450,21 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
}
}
}
if (dialogData.value.rowData!.entrypointStr) {
dialogData.value.rowData!.entrypoint = dialogData.value.rowData!.entrypointStr.split(' ');
dialogData.value.rowData!.entrypoint = [];
if (dialogData.value.rowData?.entrypointStr) {
if (dialogData.value.rowData?.entrypointStr.indexOf(`'`) !== -1) {
let itemEntrypoint = dialogData.value.rowData!.entrypointStr.split(`'`);
for (const entry of itemEntrypoint) {
if (entry && entry !== ' ') {
dialogData.value.rowData!.entrypoint.push(entry);
}
}
} else {
let itemEntrypoint = dialogData.value.rowData!.entrypointStr.split(` `);
for (const entry of itemEntrypoint) {
dialogData.value.rowData!.entrypoint.push(entry);
}
}
}
if (dialogData.value.rowData!.publishAllPorts) {
dialogData.value.rowData!.exposedPorts = [];
@@ -554,6 +582,13 @@ const checkPortValid = () => {
}
return true;
};
const isFromApp = (rowData: Container.ContainerHelper) => {
if (rowData && rowData.labels) {
return rowData.labels.indexOf('createdBy=Apps') > -1;
}
return false;
};
defineExpose({
acceptParams,
});
@@ -52,7 +52,7 @@
v-if="dialogData.rowData!.type === 'OneDrive'"
:label="$t('setting.code')"
prop="varsJson.code"
:rules="Rules.requiredInput"
:rules="rules.driveCode"
>
<el-input clearable v-model.trim="dialogData.rowData!.varsJson['code']">
<template #append>
@@ -247,7 +247,7 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { reactive, ref } from 'vue';
import { Rules } from '@/global/form-rules';
import FileList from '@/components/file-list/index.vue';
import i18n from '@/lang';
@@ -265,6 +265,16 @@ const buckets = ref();
const errBuckets = ref();
const endpoints = ref('http');
const rules = reactive({
driveCode: [{ validator: checkDriveCode, required: true, trigger: 'blur' }],
});
function checkDriveCode(rule: any, value: any, callback: any) {
const reg = /^[A-Za-z0-9_.-]{32,60}$/;
if (!reg.test(value)) {
return callback(new Error(i18n.global.t('setting.codeWarning')));
}
callback();
}
const emit = defineEmits<{ (e: 'search'): void }>();
+27 -36
View File
@@ -16,30 +16,22 @@
label-position="left"
label-width="160px"
>
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
<el-form-item :label="$t('setting.oldPassword')" prop="oldPass">
<el-input type="password" show-password clearable v-model.trim="passForm.oldPass" />
</el-form-item>
<el-form-item
v-if="settingForm?.complexityVerification === 'disable'"
:label="$t('setting.newPassword')"
prop="newPassword"
>
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
<el-form-item v-if="!isComplexity" :label="$t('setting.newPassword')" prop="newPass">
<el-input type="password" show-password clearable v-model.trim="passForm.newPass" />
</el-form-item>
<el-form-item
v-if="settingForm?.complexityVerification === 'enable'"
:label="$t('setting.newPassword')"
prop="newPasswordComplexity"
>
<el-form-item v-if="isComplexity" :label="$t('setting.newPassword')" prop="newPassComplexity">
<el-input
type="password"
show-password
clearable
v-model="passForm.newPasswordComplexity"
v-model.trim="passForm.newPassComplexity"
/>
</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 :label="$t('setting.retryPassword')" prop="rePass">
<el-input type="password" show-password clearable v-model.trim="passForm.rePass" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitChangePassword(passFormRef)">
@@ -61,30 +53,31 @@ import i18n from '@/lang';
import { Rules } from '@/global/form-rules';
import router from '@/routers';
import { MsgError, MsgSuccess } from '@/utils/message';
let settingForm = ref();
let isComplexity = ref(false);
type FormInstance = InstanceType<typeof ElForm>;
const passFormRef = ref<FormInstance>();
const passRules = reactive({
oldPassword: [Rules.requiredInput],
newPassword: [
oldPass: [Rules.noSpace, Rules.requiredInput],
newPass: [
Rules.requiredInput,
Rules.noSpace,
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
],
newPasswordComplexity: [Rules.requiredInput, Rules.password],
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
newPassComplexity: [Rules.requiredInput, Rules.noSpace, Rules.password],
rePass: [Rules.requiredInput, Rules.noSpace, { validator: checkPasswordSame, trigger: 'blur' }],
});
const passForm = reactive({
oldPassword: '',
newPassword: '',
newPasswordComplexity: '',
retryPassword: '',
oldPass: '',
newPass: '',
newPassComplexity: '',
rePass: '',
});
function checkPassword(rule: any, value: any, callback: any) {
let password =
settingForm.value.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
if (password !== passForm.retryPassword) {
function checkPasswordSame(rule: any, value: any, callback: any) {
let password = !isComplexity.value ? passForm.newPass : passForm.newPassComplexity;
if (password !== passForm.rePass) {
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
}
callback();
@@ -94,22 +87,20 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let password =
settingForm.value.complexityVerification === 'disable'
? passForm.newPassword
: passForm.newPasswordComplexity;
if (password === passForm.oldPassword) {
let password = !isComplexity.value ? passForm.newPass : passForm.newPassComplexity;
if (password === passForm.oldPass) {
MsgError(i18n.global.t('setting.duplicatePassword'));
return;
}
await handleExpired({ oldPassword: passForm.oldPassword, newPassword: password });
await handleExpired({ oldPassword: passForm.oldPass, newPassword: password });
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
router.push({ name: 'home' });
});
};
const search = async () => {
const res = await getSettingInfo();
settingForm.value = res.data;
let settingForm = res.data;
isComplexity.value = settingForm?.complexityVerification === 'enable';
};
onMounted(() => {
@@ -8,14 +8,14 @@
<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-input type="password" show-password clearable v-model.trim="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-input type="password" show-password clearable v-model.trim="passForm.newPassword" />
</el-form-item>
<el-form-item
v-if="complexityVerification === 'enable'"
@@ -26,11 +26,11 @@
type="password"
show-password
clearable
v-model="passForm.newPasswordComplexity"
v-model.trim="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-input type="password" show-password clearable v-model.trim="passForm.retryPassword" />
</el-form-item>
</el-col>
</el-row>
@@ -64,14 +64,16 @@ import { logOutApi } from '@/api/modules/auth';
const globalStore = GlobalStore();
const passFormRef = ref<FormInstance>();
const passRules = reactive({
oldPassword: [Rules.requiredInput],
oldPassword: [Rules.noSpace, Rules.requiredInput],
newPassword: [
Rules.requiredInput,
Rules.noSpace,
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
],
newPasswordComplexity: [Rules.requiredInput, Rules.password],
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
newPasswordComplexity: [Rules.requiredInput, Rules.noSpace, Rules.password],
retryPassword: [Rules.requiredInput, Rules.noSpace, { validator: checkPassword, trigger: 'blur' }],
});
const loading = ref(false);
const passwordVisible = ref<boolean>(false);
const passForm = reactive({
@@ -4,11 +4,18 @@
<template #header>
<DrawerHeader :header="$t('commons.login.username')" :back="handleClose" />
</template>
<el-form ref="formRef" label-position="top" :model="form" @submit.prevent v-loading="loading">
<el-form
ref="formRef"
label-position="top"
:model="form"
@submit.prevent
v-loading="loading"
:rules="rules"
>
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('commons.login.username')" prop="userName" :rules="Rules.userName">
<el-input clearable v-model="form.userName" />
<el-form-item :label="$t('commons.login.username')" prop="userName">
<el-input clearable v-model.trim="form.userName" />
</el-form-item>
</el-col>
</el-row>
@@ -46,7 +53,9 @@ const loading = ref();
const form = reactive({
userName: '',
});
const rules = reactive({
userName: [Rules.userName, Rules.noSpace],
});
const formRef = ref<FormInstance>();
const acceptParams = (params: DialogProps): void => {
@@ -17,7 +17,7 @@
{{ ssl.primaryDomain }}
</el-descriptions-item>
<el-descriptions-item :label="$t('website.otherDomains')">
{{ ssl.otherDomains }}
{{ ssl.domains }}
</el-descriptions-item>
<el-descriptions-item :label="$t('ssl.provider')">
{{ getProvider(ssl.provider) }}
@@ -71,10 +71,10 @@ import useClipboard from 'vue-clipboard3';
import { MsgError, MsgSuccess } from '@/utils/message';
const { toClipboard } = useClipboard();
let open = ref(false);
let id = ref(0);
let curr = ref('detail');
let ssl = ref<any>({});
const open = ref(false);
const id = ref(0);
const curr = ref('detail');
const ssl = ref<any>({});
const handleClose = () => {
open.value = false;
+13
View File
@@ -0,0 +1,13 @@
sonar.projectKey=1Panel-dev_1Panel
sonar.organization=1panel-dev
# This is the name and version displayed in the SonarCloud UI.
#sonar.projectName=1Panel
#sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
#sonar.sources=.
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8