mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ed5ae71c5 | ||
|
|
a2bfa5acaa | ||
|
|
609aa04aba | ||
|
|
0b5b90d0c5 | ||
|
|
0449100e23 | ||
|
|
5f009152d3 | ||
|
|
51ca89daba | ||
|
|
99951029c8 | ||
|
|
2d2869d184 | ||
|
|
9d85d52005 | ||
|
|
b2ce2c86fb | ||
|
|
1f92324a45 | ||
|
|
2031295ba4 | ||
|
|
f079050545 |
@@ -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 }}
|
||||
@@ -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{})
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
@@ -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
@@ -15,7 +15,8 @@
|
||||
- **素早いウェブサイト構築**: Wordpress および [Halo](https://github.com/halo-dev/halo/) と深く統合されており、ドメイン名のバインディング、SSL 証明書の設定など、ワンクリックで解決できます;
|
||||
- **効率的なマネジメント**: アプリケーション管理、ホスト監視、ファイル管理、データベース管理、コンテナ管理など、web インターフェイスを通じて Linux サーバーを簡単に管理できます;
|
||||
- **安全性と信頼性**: ファイアウォールとセキュリティ監査機能により、脆弱性の露出を最小限に抑えます;
|
||||
- **ワンクリックバックアップ**: ワンクリックでのバックアップと復元をサポートし、バックアップデータはクラウドに保存され、失われることはありません。
|
||||
- **ワンクリックバックアップ**: ワンクリックでのバックアップと復元をサポートし、バックアップデータはクラウドに保存され、失われることはありません;
|
||||
- **アプリストア**: さまざまな種類の高品質なオープンソースツールとアプリケーションソフトウェアを厳選し、インストールとアップグレードを容易にサポートします。
|
||||
|
||||
## UI ディスプレイ
|
||||
|
||||
|
||||
+2
-1
@@ -16,7 +16,8 @@
|
||||
- **快速建站**:深度集成 Wordpress 和 [Halo](https://github.com/halo-dev/halo/),域名綁定、SSL 證書配置等一鍵搞定;
|
||||
- **高效管理**:通過 Web 端輕鬆管理 Linux 服務器,包括主機監控、文件管理、數據庫管理、容器管理等;
|
||||
- **安全可靠**:基於容器來管理和部署應用,最小漏洞暴露面,提供防火牆和日誌審計等功能;
|
||||
- **一鍵備份**:支持一鍵備份和恢復,備份數據到各類雲端存儲,永不丟失。
|
||||
- **一鍵備份**:支持一鍵備份和恢復,備份數據到各類雲端存儲,永不丟失;
|
||||
- **應用商店**:精選各類高質量開源工具和應用軟件,助力您輕鬆安裝和升級。
|
||||
|
||||
## UI 展示
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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: '授權碼',
|
||||
|
||||
@@ -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 }>();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user