mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 08:00:27 +00:00
Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
193b0f3cd4 | ||
|
|
67c1bf2924 | ||
|
|
b1373ff77e | ||
|
|
55d0e27212 | ||
|
|
1c052b7c13 | ||
|
|
6c8d48c2dc | ||
|
|
b61dae638b | ||
|
|
872a93aa07 | ||
|
|
b1f337020c | ||
|
|
56858dd74c | ||
|
|
358415f737 | ||
|
|
5e73260103 | ||
|
|
e169f46784 | ||
|
|
39416abd47 | ||
|
|
640a0ca815 | ||
|
|
8e54cd5162 | ||
|
|
0f0099accb |
@@ -33,7 +33,7 @@
|
||||
|
||||
1Panel is an open-source, modern web-based control panel for Linux server management.
|
||||
|
||||
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, and container management.
|
||||
- **Efficient Management**: Through a user-friendly web graphical interface, 1Panel enables users to effortlessly manage their Linux servers. Key features include host monitoring, file management, database administration, container management, LLMs management.
|
||||
- **Rapid Website Deployment**: With deep integration of the popular open-source website building software WordPress, 1Panel streamlines the process of domain binding and SSL certificate configuration, all achievable with just one click.
|
||||
- **Application Store**: 1Panel curates a wide range of high-quality open-source tools and applications, facilitating easy installation and updates for its users.
|
||||
- **Security and Reliability**: By leveraging containerization and secure application deployment practices, 1Panel minimizes vulnerability exposure. It further enhances security through integrated firewall management and log auditing capabilities.
|
||||
|
||||
@@ -391,7 +391,7 @@ func (b *BaseApi) ContainerOperation(c *gin.Context) {
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Container stats
|
||||
// @Param id path integer true "container id"
|
||||
// @Param id path string true "container id"
|
||||
// @Success 200 {object} dto.ContainerStats
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
|
||||
@@ -66,6 +66,10 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
if req.Key == "SecurityEntrance" {
|
||||
entranceValue := base64.StdEncoding.EncodeToString([]byte(req.Value))
|
||||
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,10 @@ type OllamaBindDomainReq struct {
|
||||
}
|
||||
|
||||
type OllamaBindDomainRes struct {
|
||||
Domain string `json:"domain"`
|
||||
SSLID uint `json:"sslID"`
|
||||
AllowIPs []string `json:"allowIPs"`
|
||||
WebsiteID uint `json:"websiteID"`
|
||||
ConnUrl string `json:"connUrl"`
|
||||
Domain string `json:"domain"`
|
||||
SSLID uint `json:"sslID"`
|
||||
AcmeAccountID uint `json:"acmeAccountID"`
|
||||
AllowIPs []string `json:"allowIPs"`
|
||||
WebsiteID uint `json:"websiteID"`
|
||||
ConnUrl string `json:"connUrl"`
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ type PortRuleOperate struct {
|
||||
}
|
||||
|
||||
type ForwardRuleOperate struct {
|
||||
Rules []struct {
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
Rules []struct {
|
||||
Operation string `json:"operation" validate:"required,oneof=add remove"`
|
||||
Num string `json:"num"`
|
||||
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
|
||||
|
||||
@@ -245,6 +245,15 @@ func (u *AIToolService) BindDomain(req dto.OllamaBindDomain) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ssl.Pem == "" {
|
||||
return buserr.New("ErrSSL")
|
||||
}
|
||||
}
|
||||
createWebsiteReq := request.WebsiteCreate{
|
||||
PrimaryDomain: req.Domain,
|
||||
Alias: strings.ToLower(req.Domain),
|
||||
@@ -297,6 +306,8 @@ func (u *AIToolService) GetBindDomain(req dto.OllamaBindDomainReq) (*dto.OllamaB
|
||||
res.Domain = website.PrimaryDomain
|
||||
if website.WebsiteSSLID > 0 {
|
||||
res.SSLID = website.WebsiteSSLID
|
||||
ssl, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID))
|
||||
res.AcmeAccountID = ssl.AcmeAccountID
|
||||
}
|
||||
res.ConnUrl = fmt.Sprintf("%s://%s", strings.ToLower(website.Protocol), website.PrimaryDomain)
|
||||
res.AllowIPs = GetAllowIps(website)
|
||||
@@ -318,6 +329,15 @@ func (u *AIToolService) UpdateBindDomain(req dto.OllamaBindDomain) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.SSLID > 0 {
|
||||
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ssl.Pem == "" {
|
||||
return buserr.New("ErrSSL")
|
||||
}
|
||||
}
|
||||
websiteService := NewIWebsiteService()
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
|
||||
@@ -2,13 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -169,8 +170,9 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
} else {
|
||||
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
}
|
||||
global.LOG.Infof("rollback mysql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
} else {
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
@@ -186,6 +188,7 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover mysql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
||||
@@ -2,13 +2,14 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
pgclient "github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
|
||||
@@ -157,8 +158,9 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback postgresql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
} else {
|
||||
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
}
|
||||
global.LOG.Infof("rollback postgresql db %s from %s successful", req.DetailName, rollbackFile)
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
} else {
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
@@ -171,6 +173,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, isRollback bool) error {
|
||||
Username: dbInfo.Username,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover postgresql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
|
||||
@@ -1262,12 +1262,12 @@ func loadContainerPortForInfo(itemPorts []types.Port) []dto.PortHelper {
|
||||
var exposedPorts []dto.PortHelper
|
||||
samePortMap := make(map[string]dto.PortHelper)
|
||||
ports := transPortToStr(itemPorts)
|
||||
var itemPort dto.PortHelper
|
||||
for _, item := range ports {
|
||||
itemStr := strings.Split(item, "->")
|
||||
if len(itemStr) < 2 {
|
||||
continue
|
||||
}
|
||||
var itemPort dto.PortHelper
|
||||
lastIndex := strings.LastIndex(itemStr[0], ":")
|
||||
if lastIndex == -1 {
|
||||
itemPort.HostPort = itemStr[0]
|
||||
|
||||
@@ -381,6 +381,10 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
|
||||
TargetIP: r.TargetIP,
|
||||
TargetPort: r.TargetPort,
|
||||
}, r.Operation); err != nil {
|
||||
if req.ForceDelete {
|
||||
global.LOG.Error(err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +287,7 @@ SystemMode: "mode: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Please install Openresty first'
|
||||
ErrSSL: "Certificate content is empty, please check the certificate!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Token verification error, please reset and scan again.'
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#cmd
|
||||
AppVersion: "Lotfan noskhe-ye barname ra vared konid"
|
||||
AppCommands: "Dasturat-e marbut be barname"
|
||||
AppInit: "Barname ra shoru' konid"
|
||||
AppKeyVal: "Kelid-e barname (faghat az zabane englisi poshtibani mikonad)"
|
||||
AppCreateFileErr: "Khalgh-e file {{ .name }} namovaffagh bud {{ .err }}"
|
||||
AppCreateDirErr: "Khalgh-e folder {{ .name }} namovaffagh bud {{ .err }}"
|
||||
AppMissKey: "Kelid-e barname mojood nist, az -k estefade konid"
|
||||
AppMissVersion: "Noskhe-ye barname mojood nist, az -v estefade konid"
|
||||
AppVersionExist: "Noskhe ghablan mojood ast!"
|
||||
AppCreateSuccessful: "Khalgh ba movaffaghiat anjam shod!"
|
||||
AppWriteErr: "Neveshtan file {{ .name }} namovaffagh bud {{ .err }}"
|
||||
SudoHelper: "Lotfan in eskript ra be onvane karbare root ya ba mojavez sudo ejra konid"
|
||||
ListenIPCommands: "IP goosh dadan ra taghir dahid"
|
||||
ListenIPv4: "Goosh dadan bar IPv4"
|
||||
ListenIPv6: "Goosh dadan bar IPv6"
|
||||
ListenChangeSuccessful: "Taghir movaffagh! Hala bar {{ .value }} goosh midahad"
|
||||
ResetCommands: "E'ade setadad etela'at-e system"
|
||||
ResetMFA: "Fa'al-sazi do marhale'i 1Panel ra laghv konid"
|
||||
ResetHttps: "Voroud HTTPS baraye 1Panel ra laghv konid"
|
||||
ResetEntrance: "Voroud amin 1Panel ra laghv konid"
|
||||
ResetIPs: "Mahdudiyat IP-haye mojaz 1Panel ra laghv konid"
|
||||
ResetDomain: "Sazgari domain 1Panel ra laghv konid"
|
||||
RestoreCommands: "Bargasht be khadamate 1Panel va data"
|
||||
RestoreNoSuchFile: "Hich file mojood baraye bargasht nist"
|
||||
RestoreStep1: "(1/5) Shoru' bargasht be khadamate 1Panel va data az directory {{ .name }} ..."
|
||||
RestoreStep2: "(2/5) Bargasht be binary 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep3: "(3/5) Bargasht be script 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep4: "(4/5) Bargasht be khadamat 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreStep5: "(5/5) Bargasht be data 1Panel ba movaffaghiat anjam shod"
|
||||
RestoreSuccessful: "Bargasht ba movaffaghiat anjam shod! Khadamat dar hale restart ast, lotfan montazer bashid..."
|
||||
UpdateCommands: "Be'rooz resani etela'at-e panel"
|
||||
UpdateUser: "Be'rooz resani karbare panel"
|
||||
UpdatePassword: "Be'rooz resani ramz-e panel"
|
||||
UpdatePort: "Be'rooz resani port-e panel"
|
||||
UpdateUserNull: "Khatta: karbare panel khalist!"
|
||||
UpdateUserBlank: "Khatta: karbare panel shamel faseleh ast!"
|
||||
UpdateUserFormat: "Khatta: format-e karbare panel na dorost ast! Faghat az englisi, chine'i, adad va _, ba tool-e 3-30 poshtibani mikonad"
|
||||
UpdateUserErr: "Khatta: be'rooz resani karbare panel namovaffagh bud, {{ .err }}"
|
||||
UpdateSuccessful: "Be'rooz resani ba movaffaghiat anjam shod!"
|
||||
UpdateUserResult: "Karbare panel: {{ .name }}"
|
||||
UpdatePasswordRead: "Khatta: khatayi dar khandan etela'at-e ramz-e panel, {{ .err }}"
|
||||
UpdatePasswordNull: "Khatta: ramz-e panel khalist!"
|
||||
UpdateUPasswordBlank: "Khatta: ramz-e panel shamel faseleh ast!"
|
||||
UpdatePasswordFormat: "Khatta: ramz-e panel faghat az harf, adad, karakter-haye vizhe !@#$%*_,.? ba tool-e 8-30 poshtibani mikonad!"
|
||||
UpdatePasswordLen: "Khatta: lotfan ramzi bishtar az 6 karakter vared konid!"
|
||||
UpdatePasswordRe: "Teyid-e ramz:"
|
||||
UpdatePasswordErr: "Khatta: be'rooz resani ramz-e panel namovaffagh bud, {{ .err }}"
|
||||
UpdatePasswordSame: "Khatta: do ramz ba ham yeksan nistand, lotfan barrasi konid va dobare talash konid!"
|
||||
UpdatePasswordResult: "Ramz-e panel: {{ .name }}"
|
||||
UpdatePortFormat: "Khatta: shomareye port bayad bein 1 ta 65535 bashad!"
|
||||
UpdatePortUsed: "Khatta: shomareye port ghablan estefade shode ast, lotfan barrasi konid va dobare talash konid!"
|
||||
UpdatePortErr: "Khatta: be'rooz resani port-e panel namovaffagh bud, {{ .err }}"
|
||||
UpdatePortResult: "Port-e panel: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "Ezafe kardane ghanoun-e port firewall namovaffagh bud, {{ .err }}, lotfan port {{ .name }} ra be dast az qavaneen firewall ezafe konid."
|
||||
UpdatePortFirewallDel: "Khatta: hazf-e port firewall namovaffagh bud, {{ .err }}"
|
||||
UpdatePortFirewallReload: "Reload firewall namovaffagh bud, {{ .err }}, lotfan firewall ra be dast reload konid."
|
||||
UserInfo: "Daryaft etela'at-e panel"
|
||||
UserInfoAddr: "Address-e panel: "
|
||||
UserInfoPassHelp: "Nokte: baraye taghiri ramz, mitavanid dastur zir ra anjam dahid: "
|
||||
DBConnErr: "Khatta: etesal be database namovaffagh bud, {{ .err }}"
|
||||
SystemVersion: "noskhe: "
|
||||
SystemMode: "halat: "
|
||||
+41
-39
@@ -1,17 +1,17 @@
|
||||
ErrInvalidParams: "リクエストパラメーターエラー:{{.Detail}}"
|
||||
ErrTokenParse: "トークン生成エラー:{{.Detail}}"
|
||||
ErrInvalidParams: "リクエストパラメーターエラー: {{.Detail}}"
|
||||
ErrTokenParse: "トークン生成エラー: {{.Detail}}"
|
||||
ErrInitialPassword: "初期パスワードエラー"
|
||||
ErrInternalServer: "サービス内部エラー:{{.Detail}}"
|
||||
ErrInternalServer: "サービス内部エラー: {{.Detail}}"
|
||||
ErrRecordExist: "レコードはすでに存在します"
|
||||
ErrRecordNotFound: "記録が見つかりません"
|
||||
ErrStructTransform: "タイプ変換障害:{{.Detail}}"
|
||||
ErrNotLogin: "ユーザーはログインしません:{{.Detail}}"
|
||||
ErrPasswordExpired: "現在のパスワードが期限切れになっています:{{.Detail}}"
|
||||
ErrNotSupportType: "システムは現在のタイプをサポートしていません:{{.Detail}}"
|
||||
ErrApiConfigStatusInvalid: "APIインターフェイスアクセス禁止:{{.Detail}}"
|
||||
ErrApiConfigKeyInvalid: "APIインターフェイスキーエラー:{{.Detail}}"
|
||||
ErrApiConfigIPInvalid: "APIインターフェイスIPはホワイトリストにありません:{{.Detail}}"
|
||||
ErrApiConfigDisable: "このインターフェイスは、APIインターフェイスコールの使用を禁止しています:{{.Detail}}"
|
||||
ErrStructTransform: "タイプ変換障害: {{.Detail}}"
|
||||
ErrNotLogin: "ユーザーはログインしません: {{.Detail}}"
|
||||
ErrPasswordExpired: "現在のパスワードが期限切れになっています: {{.Detail}}"
|
||||
ErrNotSupportType: "システムは現在のタイプをサポートしていません: {{.Detail}}"
|
||||
ErrApiConfigStatusInvalid: "APIインターフェイスアクセス禁止: {{.Detail}}"
|
||||
ErrApiConfigKeyInvalid: "APIインターフェイスキーエラー: {{.Detail}}"
|
||||
ErrApiConfigIPInvalid: "APIインターフェイスIPはホワイトリストにありません: {{.Detail}}"
|
||||
ErrApiConfigDisable: "このインターフェイスは、APIインターフェイスコールの使用を禁止しています: {{.Detail}}"
|
||||
|
||||
#common
|
||||
ErrNameIsExist: "名前はすでに存在しています"
|
||||
@@ -92,10 +92,10 @@ ErrDomainIsExist: "ドメインはすでに存在しています"
|
||||
ErrAliasIsExist: "エイリアスはすでに存在しています"
|
||||
ErrAppDelete: '他のウェブサイトはこのアプリを使用します'
|
||||
ErrGroupIsUsed: "グループは使用されており、削除することはできません"
|
||||
ErrBackupMatch: "バックアップファイルは、ウェブサイトの現在の部分的なデータと一致しません:{{.Detail}}"
|
||||
ErrBackupMatch: "バックアップファイルは、ウェブサイトの現在の部分的なデータと一致しません: {{.Detail}}"
|
||||
ErrBackupExist: 'バックアップファイルは、存在しない元のデータの一部に対応しています。{{.Detail}}'
|
||||
ErrPHPResource: 'ローカルランタイムはスイッチングをサポートしません!'
|
||||
ErrPathPermission: 'インデックスディレクトリで1000:1000以外のアクセス許可を持つフォルダーが検出されたため、Webサイトにアクセスするとアクセスが拒否された場合があります。上の[保存]ボタンをクリックしてください'
|
||||
ErrPathPermission: 'インデックスディレクトリで1000: 1000以外のアクセス許可を持つフォルダーが検出されたため、Webサイトにアクセスするとアクセスが拒否された場合があります。上の[保存]ボタンをクリックしてください'
|
||||
ErrDomainIsUsed: "ドメインはすでにWebサイトで使用されています{{.Name}}"
|
||||
ErrDomainFormat: "{{.name}}ドメイン形式エラー"
|
||||
ErrDefaultAlias: "デフォルトは予約済みのコード名です。別のコード名を使用してください"
|
||||
@@ -124,7 +124,7 @@ ErrDeleteCAWithSSL: "現在の組織の下に発行された証明書があり
|
||||
ErrDeleteWithPanelSSL: "パネルSSL構成はこの証明書を使用しており、削除できません"
|
||||
ErrDefaultCA: "デフォルトの証明書当局は削除できません"
|
||||
ApplyWebSiteSSLLog: "{{.name}} Webサイト証明書の更新を開始します"
|
||||
ErrUpdateWebsiteSSL: "{{.name}}ウェブサイトは証明書の更新に失敗しました:{{.err}}"
|
||||
ErrUpdateWebsiteSSL: "{{.name}}ウェブサイトは証明書の更新に失敗しました: {{.err}}"
|
||||
ApplyWebSiteSSLSuccess: "ウェブサイトの証明書を正常に更新します"
|
||||
ErrExecShell: "スクリプトの実行に失敗した{{.err}}"
|
||||
ExecShellStart: "スクリプトの実行を開始します"
|
||||
@@ -146,7 +146,7 @@ ErrTypeOfRedis: "回復ファイルのタイプは、現在の永続性モード
|
||||
ErrInUsed: "{{.Detail}}が使用されており、削除できません"
|
||||
ErrObjectInUsed: "このオブジェクトは使用されており、削除することはできません"
|
||||
ErrPortRules: "ポートの数が一致しません。再入力してください!"
|
||||
ErrPgImagePull: "画像プルタイムアウト。画像の加速を構成するか、Postgres:16.0-Alpine画像を手動で引いて、再試行してください"
|
||||
ErrPgImagePull: "画像プルタイムアウト。画像の加速を構成するか、Postgres: 16.0-Alpine画像を手動で引いて、再試行してください"
|
||||
|
||||
#runtime
|
||||
ErrDirNotFound: "ビルドフォルダーは存在しません!ファイルの整合性を確認してください!"
|
||||
@@ -253,37 +253,39 @@ UpdateCommands: "パネル情報を更新します"
|
||||
UpdateUser: "パネルユーザーを更新します"
|
||||
UpdatePassword: "パスワードを更新します"
|
||||
UpdatePort: "パネルポートを更新します"
|
||||
UpdateUserNull: "エラー:パネルユーザーは空です!"
|
||||
UpdateUserBlank: "エラー:パネルユーザーにはスペースが含まれています!"
|
||||
UpdateUserFormat: "エラー:無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています"
|
||||
UpdateUserErr: "エラー:パネルユーザーの更新に失敗しました{{.err}}"
|
||||
UpdateUserNull: "エラー: パネルユーザーは空です!"
|
||||
UpdateUserBlank: "エラー: パネルユーザーにはスペースが含まれています!"
|
||||
UpdateUserFormat: "エラー: 無効なパネルユーザー形式!英語、中国語、数字、_、長さ3〜30のみをサポートしています"
|
||||
UpdateUserErr: "エラー: パネルユーザーの更新に失敗しました{{.err}}"
|
||||
UpdateSuccessful: "更新成功!"
|
||||
UpdateUserResult: "パネルユーザー:{{.name}}"
|
||||
UpdatePasswordRead: "エラー:パネルパスワード情報の読み取りに失敗しました、{{.err}}"
|
||||
UpdatePasswordNull: "エラー:パネルパスワードは空です!"
|
||||
UpdateUPasswordBlank: "エラー:パスワードにはスペースが含まれています!"
|
||||
UpdatePasswordFormat: "エラー:パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!"
|
||||
UpdatePasswordLen: "エラー:6文字より長くパスワードを入力してください!"
|
||||
UpdatePasswordRe: "パスワードを認証する:"
|
||||
UpdatePasswordErr: "エラー:{{.err}}のパスワードの更新に失敗しました"
|
||||
UpdatePasswordSame: "エラー:2つのパスワードが一致しません。チェックして再試行してください!"
|
||||
UpdatePasswordResult: "パネルパスワード:{{.name}}"
|
||||
UpdatePortFormat: "エラー:入力ポート番号は1〜65535でなければなりません!"
|
||||
UpdatePortUsed: "エラー:ポート番号はすでに使用されています。チェックして再試行してください!"
|
||||
UpdatePortErr: "エラー:パネルポートの更新に失敗しました{{.err}}"
|
||||
UpdatePortResult: "パネルポート:{{.name}}"
|
||||
UpdateUserResult: "パネルユーザー: {{.name}}"
|
||||
UpdatePasswordRead: "エラー: パネルパスワード情報の読み取りに失敗しました、{{.err}}"
|
||||
UpdatePasswordNull: "エラー: パネルパスワードは空です!"
|
||||
UpdateUPasswordBlank: "エラー: パスワードにはスペースが含まれています!"
|
||||
UpdatePasswordFormat: "エラー: パネルパスワードは、文字、数字、特殊文字のみをサポートします!@#$%*_、。、、長さ8-30!"
|
||||
UpdatePasswordLen: "エラー: 6文字より長くパスワードを入力してください!"
|
||||
UpdatePasswordRe: "パスワードを認証する: "
|
||||
UpdatePasswordErr: "エラー: {{.err}}のパスワードの更新に失敗しました"
|
||||
UpdatePasswordSame: "エラー: 2つのパスワードが一致しません。チェックして再試行してください!"
|
||||
UpdatePasswordResult: "パネルパスワード: {{.name}}"
|
||||
UpdatePortFormat: "エラー: 入力ポート番号は1〜65535でなければなりません!"
|
||||
UpdatePortUsed: "エラー: ポート番号はすでに使用されています。チェックして再試行してください!"
|
||||
UpdatePortErr: "エラー: パネルポートの更新に失敗しました{{.err}}"
|
||||
UpdatePortResult: "パネルポート: {{.name}}"
|
||||
UpdatePortFirewallAdd: "ファイアウォールポートルールの追加に失敗した{{.err}}、ファイアウォールルールに{{.name}}ポートを手動で追加してください。"
|
||||
UpdatePortFirewallDel: "エラー:ファイアウォールポートの削除に失敗しました、{{.err}}"
|
||||
UpdatePortFirewallDel: "エラー: ファイアウォールポートの削除に失敗しました、{{.err}}"
|
||||
UpdatePortFirewallReload: "ファイアウォールのリロードに失敗しました{{.err}}、ファイアウォールを手動でリロードしてください。"
|
||||
UserInfo: "パネル情報を取得します"
|
||||
UserInfoAddr: "パネルアドレス:"
|
||||
UserInfoPassHelp: "ヒント:パスワードを変更するには、コマンドを実行できます。"
|
||||
DBConnErr: "エラー:データベース接続の初期化に失敗しました、{{.err}}"
|
||||
SystemVersion: "バージョン:"
|
||||
SystemMode: "モード:"
|
||||
UserInfoAddr: "パネルアドレス: "
|
||||
UserInfoPassHelp: "ヒント: パスワードを変更するには、コマンドを実行できます。"
|
||||
DBConnErr: "エラー: データベース接続の初期化に失敗しました、{{.err}}"
|
||||
SystemVersion: "バージョン: "
|
||||
SystemMode: "モード: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'まず Openresty をインストールしてください'
|
||||
ErrSSL: "証明書の内容が空です。証明書を確認してください!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'トークンの検証エラーです。リセット後、再度QRコードをスキャンしてください。'
|
||||
|
||||
@@ -287,6 +287,8 @@ SystemMode: "모드: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: '먼저 Openresty를 설치하세요'
|
||||
ErrSSL: "인증서 내용이 비어 있습니다. 인증서를 확인하세요!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '토큰 검증 오류가 발생했습니다. 재설정 후 다시 스캔해 주세요.'
|
||||
|
||||
@@ -286,6 +286,8 @@ SystemMode: "Mod: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Sila pasang Openresty terlebih dahulu'
|
||||
ErrSSL: "Kandungan sijil kosong, sila periksa sijil!"
|
||||
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Ralat pengesahan token, sila tetapkan semula dan imbas semula.'
|
||||
|
||||
@@ -284,6 +284,7 @@ SystemMode: "modo: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: 'Por favor, instale o Openresty primeiro'
|
||||
ErrSSL: "O conteúdo do certificado está vazio, por favor, verifique o certificado!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'Erro de verificação do token, por favor, reinicie e escaneie novamente.'
|
||||
|
||||
@@ -286,7 +286,8 @@ SystemVersion: "версия: "
|
||||
SystemMode: "режим: "
|
||||
|
||||
#ai-tool
|
||||
"ErrOpenrestyInstall": "Пожалуйста, установите Openresty сначала"
|
||||
ErrOpenrestyInstall: "Пожалуйста, установите Openresty сначала"
|
||||
ErrSSL: "Содержимое сертификата пустое, пожалуйста, проверьте сертификат!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: 'шибка проверки токена, пожалуйста, сбросьте и отсканируйте снова.'
|
||||
|
||||
@@ -8,7 +8,7 @@ ErrStructTransform: "類型轉換失敗: {{ .detail }}"
|
||||
ErrNotLogin: "用戶未登入: {{ .detail }}"
|
||||
ErrPasswordExpired: "目前密碼已過期: {{ .detail }}"
|
||||
ErrNotSupportType: "系統暫不支援目前類型: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 介面禁止訪問: {{ .detail }}"
|
||||
ErrApiConfigStatusInvalid: "API 介面禁止瀏覽: {{ .detail }}"
|
||||
ErrApiConfigKeyInvalid: "API 介面金鑰錯誤: {{ .detail }}"
|
||||
ErrApiConfigIPInvalid: "呼叫 API 介面 IP 不在白名單: {{ .detail }}"
|
||||
ErrApiConfigDisable: "此介面禁止使用 API 介面呼叫: {{ .detail }}"
|
||||
@@ -243,7 +243,7 @@ ResetMFA: "取消 1Panel 兩步驗證"
|
||||
ResetHttps: "取消 1Panel https 方式登入"
|
||||
ResetEntrance: "取消 1Panel 安全入口"
|
||||
ResetIPs: "取消 1Panel 授權 IP 限制"
|
||||
ResetDomain: "取消 1Panel 訪問域名綁定"
|
||||
ResetDomain: "取消 1Panel 瀏覽域名綁定"
|
||||
RestoreCommands: "轉返 1Panel 服務及資料"
|
||||
RestoreNoSuchFile: "暫無可轉返文件"
|
||||
RestoreStep1: "(1/5)開始從 {{ .name }} 目錄轉返 1Panel 服務及資料... "
|
||||
@@ -256,37 +256,38 @@ UpdateCommands: "修改面板資訊"
|
||||
UpdateUser: "修改面板用戶"
|
||||
UpdatePassword: "修改面板密碼"
|
||||
UpdatePort: "修改面板埠"
|
||||
UpdateUserNull: "錯誤:輸入面板用戶為空!"
|
||||
UpdateUserBlank: "錯誤:輸入面板用戶中包含空格字元!"
|
||||
UpdateUserFormat: "錯誤:輸入面板用戶錯誤!僅支援英文、中文、數字和_,長度3-30"
|
||||
UpdateUserErr: "錯誤:面板用戶修改失敗,{{ .err }}"
|
||||
UpdateUserNull: "錯誤: 輸入面板用戶為空!"
|
||||
UpdateUserBlank: "錯誤: 輸入面板用戶中包含空格字元!"
|
||||
UpdateUserFormat: "錯誤: 輸入面板用戶錯誤!僅支援英文、中文、數字和_,長度3-30"
|
||||
UpdateUserErr: "錯誤: 面板用戶修改失敗,{{ .err }}"
|
||||
UpdateSuccessful: "修改成功!"
|
||||
UpdateUserResult: "面板用戶:{{ .name }}"
|
||||
UpdatePasswordRead: "錯誤:面板密碼資訊讀取錯誤,{{ .err }}"
|
||||
UpdatePasswordNull: "錯誤:輸入面板密碼為空!"
|
||||
UpdateUPasswordBlank: "錯誤:輸入面板密碼中包含空格字元!"
|
||||
UpdatePasswordFormat: "錯誤:面板密碼僅支援字母、數字、特殊字元(!@#$%*_,.?),長度 8-30 位!"
|
||||
UpdatePasswordLen: "錯誤:請輸入 6 位以上密碼!"
|
||||
UpdatePasswordRe: "確認密碼:"
|
||||
UpdatePasswordErr: "錯誤:面板密碼修改失敗,{{ .err }}"
|
||||
UpdatePasswordSame: "錯誤:兩次密碼不匹配,請檢查後重試!"
|
||||
UpdatePasswordResult: "面板密碼:{{ .name }}"
|
||||
UpdatePortFormat: "錯誤:輸入的埠號必須在 1 到 65535 之間!"
|
||||
UpdatePortUsed: "錯誤:該埠號正被佔用,請檢查後重試!"
|
||||
UpdatePortErr: "錯誤:面板埠修改失敗,{{ .err }}"
|
||||
UpdatePortResult: "面板埠:{{ .name }}"
|
||||
UpdateUserResult: "面板用戶: {{ .name }}"
|
||||
UpdatePasswordRead: "錯誤: 面板密碼資訊讀取錯誤,{{ .err }}"
|
||||
UpdatePasswordNull: "錯誤: 輸入面板密碼為空!"
|
||||
UpdateUPasswordBlank: "錯誤: 輸入面板密碼中包含空格字元!"
|
||||
UpdatePasswordFormat: "錯誤: 面板密碼僅支援字母、數字、特殊字元(!@#$%*_,.?),長度 8-30 位!"
|
||||
UpdatePasswordLen: "錯誤: 請輸入 6 位以上密碼!"
|
||||
UpdatePasswordRe: "確認密碼: "
|
||||
UpdatePasswordErr: "錯誤: 面板密碼修改失敗,{{ .err }}"
|
||||
UpdatePasswordSame: "錯誤: 兩次密碼不匹配,請檢查後重試!"
|
||||
UpdatePasswordResult: "面板密碼: {{ .name }}"
|
||||
UpdatePortFormat: "錯誤: 輸入的埠號必須在 1 到 65535 之間!"
|
||||
UpdatePortUsed: "錯誤: 該埠號正被佔用,請檢查後重試!"
|
||||
UpdatePortErr: "錯誤: 面板埠修改失敗,{{ .err }}"
|
||||
UpdatePortResult: "面板埠: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "新增防火牆埠規則失敗,{{ .err }},請您手動將 {{ .name }} 埠新增至防火牆規則中。"
|
||||
UpdatePortFirewallDel: "錯誤:防火牆埠刪除失敗,{{ .err }}"
|
||||
UpdatePortFirewallDel: "錯誤: 防火牆埠刪除失敗,{{ .err }}"
|
||||
UpdatePortFirewallReload: "防火牆重載失敗,{{ .err }},請您手動重載防火牆。"
|
||||
UserInfo: "取得面板資訊"
|
||||
UserInfoAddr: "面板地址:"
|
||||
UserInfoPassHelp: "提示:修改密碼可執行指令:"
|
||||
DBConnErr: "錯誤:初始化資料庫連線失敗,{{ .err }}"
|
||||
SystemVersion: "版本:"
|
||||
SystemMode: "模式:"
|
||||
UserInfoAddr: "面板地址: "
|
||||
UserInfoPassHelp: "提示: 修改密碼可執行指令: "
|
||||
DBConnErr: "錯誤: 初始化資料庫連線失敗,{{ .err }}"
|
||||
SystemVersion: "版本: "
|
||||
SystemMode: "模式: "
|
||||
|
||||
#ai-tool
|
||||
"ErrOpenrestyInstall": "請先安裝 Openresty"
|
||||
ErrOpenrestyInstall: "請先安裝 Openresty"
|
||||
ErrSSL: "證書內容為空,請檢查證書!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '令牌驗證錯誤,請重置後再次掃碼'
|
||||
|
||||
+25
-24
@@ -256,37 +256,38 @@ UpdateCommands: "修改面板信息"
|
||||
UpdateUser: "修改面板用户"
|
||||
UpdatePassword: "修改面板密码"
|
||||
UpdatePort: "修改面板端口"
|
||||
UpdateUserNull: "错误:输入面板用户为空!"
|
||||
UpdateUserBlank: "错误:输入面板用户中包含空格字符!"
|
||||
UpdateUserFormat: "错误:输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
|
||||
UpdateUserErr: "错误:面板用户修改失败,{{ .err }}"
|
||||
UpdateUserNull: "错误: 输入面板用户为空!"
|
||||
UpdateUserBlank: "错误: 输入面板用户中包含空格字符!"
|
||||
UpdateUserFormat: "错误: 输入面板用户错误!仅支持英文、中文、数字和_,长度3-30"
|
||||
UpdateUserErr: "错误: 面板用户修改失败,{{ .err }}"
|
||||
UpdateSuccessful: "修改成功!"
|
||||
UpdateUserResult: "面板用户:{{ .name }}"
|
||||
UpdatePasswordRead: "错误:面板密码信息读取错误,{{ .err }}"
|
||||
UpdatePasswordNull: "错误:输入面板密码为空!"
|
||||
UpdateUPasswordBlank: "错误:输入面板密码中包含空格字符!"
|
||||
UpdatePasswordFormat: "错误:面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
|
||||
UpdatePasswordLen: "错误:请输入 6 位以上密码!"
|
||||
UpdatePasswordRe: "确认密码:"
|
||||
UpdatePasswordErr: "错误:面板密码修改失败,{{ .err }}"
|
||||
UpdatePasswordSame: "错误:两次密码不匹配,请检查后重试!"
|
||||
UpdatePasswordResult: "面板密码:{{ .name }}"
|
||||
UpdatePortFormat: "错误:输入的端口号必须在 1 到 65535 之间!"
|
||||
UpdatePortUsed: "错误:该端口号正被占用,请检查后重试!"
|
||||
UpdatePortErr: "错误:面板端口修改失败,{{ .err }}"
|
||||
UpdatePortResult: "面板端口:{{ .name }}"
|
||||
UpdateUserResult: "面板用户: {{ .name }}"
|
||||
UpdatePasswordRead: "错误: 面板密码信息读取错误,{{ .err }}"
|
||||
UpdatePasswordNull: "错误: 输入面板密码为空!"
|
||||
UpdateUPasswordBlank: "错误: 输入面板密码中包含空格字符!"
|
||||
UpdatePasswordFormat: "错误: 面板密码仅支持字母、数字、特殊字符(!@#$%*_,.?),长度 8-30 位!"
|
||||
UpdatePasswordLen: "错误: 请输入 6 位以上密码!"
|
||||
UpdatePasswordRe: "确认密码: "
|
||||
UpdatePasswordErr: "错误: 面板密码修改失败,{{ .err }}"
|
||||
UpdatePasswordSame: "错误: 两次密码不匹配,请检查后重试!"
|
||||
UpdatePasswordResult: "面板密码: {{ .name }}"
|
||||
UpdatePortFormat: "错误: 输入的端口号必须在 1 到 65535 之间!"
|
||||
UpdatePortUsed: "错误: 该端口号正被占用,请检查后重试!"
|
||||
UpdatePortErr: "错误: 面板端口修改失败,{{ .err }}"
|
||||
UpdatePortResult: "面板端口: {{ .name }}"
|
||||
UpdatePortFirewallAdd: "添加防火墙端口规则失败,{{ .err }},请您手动将 {{ .name }} 端口添加至防火墙规则中。"
|
||||
UpdatePortFirewallDel: "错误:防火墙端口删除失败,{{ .err }}"
|
||||
UpdatePortFirewallDel: "错误: 防火墙端口删除失败,{{ .err }}"
|
||||
UpdatePortFirewallReload: "防火墙重载失败,{{ .err }},请您手动重载防火墙。"
|
||||
UserInfo: "获取面板信息"
|
||||
UserInfoAddr: "面板地址:"
|
||||
UserInfoPassHelp: "提示:修改密码可执行命令:"
|
||||
DBConnErr: "错误:初始化数据库连接失败,{{ .err }}"
|
||||
SystemVersion: "版本:"
|
||||
SystemMode: "模式:"
|
||||
UserInfoAddr: "面板地址: "
|
||||
UserInfoPassHelp: "提示: 修改密码可执行命令: "
|
||||
DBConnErr: "错误: 初始化数据库连接失败,{{ .err }}"
|
||||
SystemVersion: "版本: "
|
||||
SystemMode: "模式: "
|
||||
|
||||
#ai-tool
|
||||
ErrOpenrestyInstall: '请先安装 Openresty'
|
||||
ErrSSL: "证书内容为空,请检查证书!"
|
||||
|
||||
#mobile app
|
||||
ErrVerifyToken: '令牌验证错误,请重置后再次扫码'
|
||||
|
||||
@@ -109,6 +109,15 @@ func handleNoRoute(c *gin.Context) {
|
||||
c.Data(statusCode, "text/html; charset=utf-8", data)
|
||||
}
|
||||
|
||||
func checkSession(c *gin.Context) bool {
|
||||
sId, err := c.Cookie(constant.SessionName)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = global.SESSION.Get(sId)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
||||
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
|
||||
@@ -136,10 +145,15 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||
})
|
||||
}
|
||||
rootRouter.GET("/", func(c *gin.Context) {
|
||||
if !checkEntrance(c) {
|
||||
if !checkEntrance(c) && !checkSession(c) {
|
||||
handleNoRoute(c)
|
||||
return
|
||||
}
|
||||
entrance = authService.GetSecurityEntrance()
|
||||
if entrance != "" {
|
||||
entranceValue := base64.StdEncoding.EncodeToString([]byte(entrance))
|
||||
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
|
||||
}
|
||||
staticServer := http.FileServer(http.FS(web.IndexHtml))
|
||||
staticServer.ServeHTTP(c.Writer, c.Request)
|
||||
})
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -102,27 +102,38 @@ func isValid1PanelToken(panelToken string, panelTimestamp string) bool {
|
||||
|
||||
func isIPInWhiteList(clientIP string) bool {
|
||||
ipWhiteString := global.CONF.System.IpWhiteList
|
||||
ipWhiteList := strings.Split(ipWhiteString, "\n")
|
||||
if len(ipWhiteString) == 0 {
|
||||
global.LOG.Error("IP whitelist is empty")
|
||||
return false
|
||||
}
|
||||
ipWhiteList, ipErr := common.HandleIPList(ipWhiteString)
|
||||
if ipErr != nil {
|
||||
global.LOG.Errorf("Failed to handle IP list: %v", ipErr)
|
||||
return false
|
||||
}
|
||||
clientParsedIP := net.ParseIP(clientIP)
|
||||
if clientParsedIP == nil {
|
||||
return false
|
||||
}
|
||||
iPv4 := clientParsedIP.To4()
|
||||
iPv6 := clientParsedIP.To16()
|
||||
for _, cidr := range ipWhiteList {
|
||||
if cidr == "0.0.0.0" {
|
||||
if (iPv4 != nil && (cidr == "0.0.0.0" || cidr == "0.0.0.0/0" || iPv4.String() == cidr)) || (iPv6 != nil && (cidr == "::/0" || iPv6.String() == cidr)) {
|
||||
return true
|
||||
}
|
||||
_, ipNet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
if cidr == clientIP {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
}
|
||||
if ipNet.Contains(net.ParseIP(clientIP)) {
|
||||
if (iPv4 != nil && ipNet.Contains(iPv4)) || (iPv6 != nil && ipNet.Contains(iPv6)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GenerateMD5(input string) string {
|
||||
func GenerateMD5(param string) string {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(input))
|
||||
hash.Write([]byte(param))
|
||||
return hex.EncodeToString(hash.Sum(nil))
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/common"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/schema_v12"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/schema"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ func (n NvidiaSMI) LoadGpuInfo() (*common.GpuInfo, error) {
|
||||
return nil, fmt.Errorf("calling nvidia-smi failed, err: %v", std)
|
||||
}
|
||||
data := []byte(std)
|
||||
schema := "v11"
|
||||
version := "v11"
|
||||
|
||||
buf := bytes.NewBuffer(data)
|
||||
decoder := xml.NewDecoder(buf)
|
||||
@@ -51,15 +51,18 @@ func (n NvidiaSMI) LoadGpuInfo() (*common.GpuInfo, error) {
|
||||
parts := strings.Split(directive, " ")
|
||||
s := strings.Trim(parts[len(parts)-1], "\" ")
|
||||
if strings.HasPrefix(s, "nvsmi_device_") && strings.HasSuffix(s, ".dtd") {
|
||||
schema = strings.TrimSuffix(strings.TrimPrefix(s, "nvsmi_device_"), ".dtd")
|
||||
version = strings.TrimSuffix(strings.TrimPrefix(s, "nvsmi_device_"), ".dtd")
|
||||
} else {
|
||||
global.LOG.Debugf("Cannot find schema version in %q", directive)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if schema != "v12" {
|
||||
return &common.GpuInfo{}, nil
|
||||
if version == "v12" || version == "v11" {
|
||||
return schema.Parse(data, version)
|
||||
} else {
|
||||
global.LOG.Errorf("don't support such schema version %s", version)
|
||||
}
|
||||
return schema_v12.Parse(data)
|
||||
|
||||
return &common.GpuInfo{}, nil
|
||||
}
|
||||
|
||||
+9
-4
@@ -1,4 +1,4 @@
|
||||
package schema_v12
|
||||
package schema
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ai_tools/gpu/common"
|
||||
)
|
||||
|
||||
func Parse(buf []byte) (*common.GpuInfo, error) {
|
||||
func Parse(buf []byte, version string) (*common.GpuInfo, error) {
|
||||
var (
|
||||
s smi
|
||||
info common.GpuInfo
|
||||
@@ -36,8 +36,13 @@ func Parse(buf []byte) (*common.GpuInfo, error) {
|
||||
|
||||
gpuItem.Temperature = s.Gpu[i].Temperature.GpuTemp
|
||||
gpuItem.PerformanceState = s.Gpu[i].PerformanceState
|
||||
gpuItem.PowerDraw = s.Gpu[i].GpuPowerReadings.PowerDraw
|
||||
gpuItem.MaxPowerLimit = s.Gpu[i].GpuPowerReadings.MaxPowerLimit
|
||||
if version == "v12" {
|
||||
gpuItem.PowerDraw = s.Gpu[i].GpuPowerReadings.PowerDraw
|
||||
gpuItem.MaxPowerLimit = s.Gpu[i].GpuPowerReadings.MaxPowerLimit
|
||||
} else {
|
||||
gpuItem.PowerDraw = s.Gpu[i].PowerReadings.PowerDraw
|
||||
gpuItem.MaxPowerLimit = s.Gpu[i].PowerReadings.MaxPowerLimit
|
||||
}
|
||||
gpuItem.MemUsed = s.Gpu[i].FbMemoryUsage.Used
|
||||
gpuItem.MemTotal = s.Gpu[i].FbMemoryUsage.Total
|
||||
gpuItem.GPUUtil = s.Gpu[i].Utilization.GpuUtil
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package schema_v12
|
||||
package schema
|
||||
|
||||
type smi struct {
|
||||
AttachedGpus string `xml:"attached_gpus"`
|
||||
@@ -3,11 +3,13 @@ package ssl
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/json"
|
||||
"github.com/go-acme/lego/v4/providers/dns/rainyun"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/providers/dns/freemyip"
|
||||
"github.com/go-acme/lego/v4/providers/dns/rainyun"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/go-acme/lego/v4/acme"
|
||||
"github.com/go-acme/lego/v4/acme/api"
|
||||
@@ -73,6 +75,7 @@ const (
|
||||
Volcengine DnsType = "Volcengine"
|
||||
CloudFlare DnsType = "CloudFlare"
|
||||
CloudDns DnsType = "CloudDns"
|
||||
FreeMyIP DnsType = "FreeMyIP"
|
||||
NameSilo DnsType = "NameSilo"
|
||||
NameCheap DnsType = "NameCheap"
|
||||
NameCom DnsType = "NameCom"
|
||||
@@ -155,6 +158,12 @@ func (c *AcmeClient) UseDns(dnsType DnsType, params string, websiteSSL model.Web
|
||||
clouddnsConfig.PollingInterval = pollingInterval
|
||||
clouddnsConfig.TTL = ttl
|
||||
p, err = clouddns.NewDNSProviderConfig(clouddnsConfig)
|
||||
case FreeMyIP:
|
||||
freeMyIpConfig := freemyip.NewDefaultConfig()
|
||||
freeMyIpConfig.Token = param.Token
|
||||
freeMyIpConfig.PropagationTimeout = propagationTimeout
|
||||
freeMyIpConfig.PollingInterval = pollingInterval
|
||||
p, err = freemyip.NewDNSProviderConfig(freeMyIpConfig)
|
||||
case NameCheap:
|
||||
namecheapConfig := namecheap.NewDefaultConfig()
|
||||
namecheapConfig.APIKey = param.APIkey
|
||||
|
||||
@@ -5,8 +5,7 @@ system:
|
||||
repo_url: https://resource.1panel.pro
|
||||
app_repo: https://apps.1panel.pro
|
||||
is_demo: false
|
||||
is_intl: true
|
||||
port: 9999
|
||||
port: 8888
|
||||
username: admin
|
||||
password: admin123
|
||||
|
||||
|
||||
@@ -3483,7 +3483,7 @@ const docTemplate = `{
|
||||
"summary": "Container stats",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"type": "string",
|
||||
"description": "container id",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
@@ -19382,6 +19382,9 @@ const docTemplate = `{
|
||||
"dto.ForwardRuleOperate": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"forceDelete": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -20708,6 +20711,9 @@ const docTemplate = `{
|
||||
"dto.OllamaBindDomainRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"acmeAccountID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"allowIPs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -26721,7 +26727,7 @@ const docTemplate = `{
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"description": "- ` + "`" + `1Panel-Token` + "`" + ` is the key for the panel API Key.",
|
||||
"description": "Custom Token Format, Format: md5('1panel' + API-Key + UnixTimestamp).\n` + "`" + `` + "`" + `` + "`" + `\neg:\ncurl -X GET \"http://localhost:4004/api/v1/dashboard/current\" \\\n-H \"1Panel-Token: \u003c1panel_token\u003e\" \\\n-H \"1Panel-Timestamp: \u003ccurrent_unix_timestamp\u003e\"\n` + "`" + `` + "`" + `` + "`" + `\n- ` + "`" + `1Panel-Token` + "`" + ` is the key for the panel API Key.",
|
||||
"type": "apiKey",
|
||||
"name": "1Panel-Token",
|
||||
"in": "header"
|
||||
|
||||
@@ -3480,7 +3480,7 @@
|
||||
"summary": "Container stats",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"type": "string",
|
||||
"description": "container id",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
@@ -19379,6 +19379,9 @@
|
||||
"dto.ForwardRuleOperate": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"forceDelete": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -20705,6 +20708,9 @@
|
||||
"dto.OllamaBindDomainRes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"acmeAccountID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"allowIPs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -26718,7 +26724,7 @@
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"ApiKeyAuth": {
|
||||
"description": "- `1Panel-Token` is the key for the panel API Key.",
|
||||
"description": "Custom Token Format, Format: md5('1panel' + API-Key + UnixTimestamp).\n```\neg:\ncurl -X GET \"http://localhost:4004/api/v1/dashboard/current\" \\\n-H \"1Panel-Token: \u003c1panel_token\u003e\" \\\n-H \"1Panel-Timestamp: \u003ccurrent_unix_timestamp\u003e\"\n```\n- `1Panel-Token` is the key for the panel API Key.",
|
||||
"type": "apiKey",
|
||||
"name": "1Panel-Token",
|
||||
"in": "header"
|
||||
|
||||
@@ -1578,6 +1578,8 @@ definitions:
|
||||
type: object
|
||||
dto.ForwardRuleOperate:
|
||||
properties:
|
||||
forceDelete:
|
||||
type: boolean
|
||||
rules:
|
||||
items:
|
||||
properties:
|
||||
@@ -2480,6 +2482,8 @@ definitions:
|
||||
type: object
|
||||
dto.OllamaBindDomainRes:
|
||||
properties:
|
||||
acmeAccountID:
|
||||
type: integer
|
||||
allowIPs:
|
||||
items:
|
||||
type: string
|
||||
@@ -8585,7 +8589,7 @@ paths:
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@@ -16762,7 +16766,15 @@ schemes:
|
||||
- https
|
||||
securityDefinitions:
|
||||
ApiKeyAuth:
|
||||
description: '- `1Panel-Token` is the key for the panel API Key.'
|
||||
description: |-
|
||||
Custom Token Format, Format: md5('1panel' + API-Key + UnixTimestamp).
|
||||
```
|
||||
eg:
|
||||
curl -X GET "http://localhost:4004/api/v1/dashboard/current" \
|
||||
-H "1Panel-Token: <1panel_token>" \
|
||||
-H "1Panel-Timestamp: <current_unix_timestamp>"
|
||||
```
|
||||
- `1Panel-Token` is the key for the panel API Key.
|
||||
in: header
|
||||
name: 1Panel-Token
|
||||
type: apiKey
|
||||
|
||||
@@ -104,6 +104,7 @@ export namespace AI {
|
||||
export interface BindDomainRes {
|
||||
domain: string;
|
||||
sslID: number;
|
||||
acmeAccountID: number;
|
||||
allowIPs: string[];
|
||||
websiteID?: number;
|
||||
connUrl: string;
|
||||
|
||||
@@ -98,7 +98,7 @@ export const operateFire = (operation: string) => {
|
||||
export const operatePortRule = (params: Host.RulePort) => {
|
||||
return http.post<Host.RulePort>(`/hosts/firewall/port`, params, TimeoutEnum.T_40S);
|
||||
};
|
||||
export const operateForwardRule = (params: { rules: Host.RuleForward[] }) => {
|
||||
export const operateForwardRule = (params: { rules: Host.RuleForward[]; forceDelete: boolean }) => {
|
||||
return http.post<Host.RulePort>(`/hosts/firewall/forward`, params, TimeoutEnum.T_40S);
|
||||
};
|
||||
export const operateIPRule = (params: Host.RuleIP) => {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<script lang="ts" setup>
|
||||
import i18n from '@/lang';
|
||||
import { dateFormatForName } from '@/utils/util';
|
||||
import { computed, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue';
|
||||
import { computed, nextTick, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
@@ -145,10 +145,12 @@ const searchLogs = async () => {
|
||||
);
|
||||
terminalSocket.value.onmessage = (event) => {
|
||||
logInfo.value += event.data;
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
nextTick(() => {
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
import { cleanContainerLog } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
||||
import { onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
||||
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
@@ -113,10 +113,12 @@ const searchLogs = async () => {
|
||||
);
|
||||
terminalSocket.value.onmessage = (event) => {
|
||||
logInfo.value += event.data;
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
nextTick(() => {
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -200,6 +200,10 @@ export const DNSTypes = [
|
||||
label: 'GoDaddy',
|
||||
value: 'Godaddy',
|
||||
},
|
||||
{
|
||||
label: 'FreeMyIP',
|
||||
value: 'FreeMyIP',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('website.rainyun'),
|
||||
value: 'RainYun',
|
||||
|
||||
@@ -14,7 +14,7 @@ const message = {
|
||||
fit2cloud: '飛致雲',
|
||||
lingxia: '凌霞',
|
||||
button: {
|
||||
run: '運行',
|
||||
run: '執行',
|
||||
create: '建立',
|
||||
add: '新增',
|
||||
save: '儲存',
|
||||
@@ -123,7 +123,7 @@ const message = {
|
||||
},
|
||||
msg: {
|
||||
noneData: '暫無資料',
|
||||
disConn: '請直接點擊斷開按鈕斷開終端連接,避免使用 {0} 等退出命令。',
|
||||
disConn: '請直接點選斷開按鈕斷開終端連接,避免使用 {0} 等退出指令。',
|
||||
delete: '刪除 操作不可復原,是否繼續?',
|
||||
clean: '清空 操作不可復原,是否繼續?',
|
||||
deleteTitle: '刪除',
|
||||
@@ -579,18 +579,18 @@ const message = {
|
||||
ai_tools: {
|
||||
model: {
|
||||
model: '模型',
|
||||
create: '添加模型',
|
||||
create: '新增模型',
|
||||
create_helper: '拉取 "{0}"',
|
||||
ollama_doc: '您可以訪問 Ollama 官方網站,搜索並查找更多模型。',
|
||||
container_conn_helper: '容器間訪問或連接使用此地址',
|
||||
ollama_doc: '您可以瀏覽 Ollama 官方網站,搜尋並查找更多模型。',
|
||||
container_conn_helper: '容器間瀏覽或連接使用此地址',
|
||||
ollama_sync: '同步 Ollama 模型發現下列模型不存在,是否刪除?',
|
||||
from_remote: '該模型並非通過 1Panel 下載,無相關拉取日誌。',
|
||||
from_remote: '該模型並非透過 1Panel 下載,無相關拉取日誌。',
|
||||
no_logs: '該模型的拉取日誌已被刪除,無法查看相關日誌。',
|
||||
},
|
||||
gpu: {
|
||||
gpu: 'GPU 监控',
|
||||
gpu: 'GPU 監控',
|
||||
base: '基礎資訊',
|
||||
gpuHelper: '目前系統未檢測到 NVIDIA-SMI或者XPU-SMI 指令,請檢查後重試!',
|
||||
gpuHelper: '目前系統未檢測到 NVIDIA-SMI 或者 XPU-SMI 指令,請檢查後重試!',
|
||||
driverVersion: '驅動版本',
|
||||
cudaVersion: 'CUDA 版本',
|
||||
process: '行程資訊',
|
||||
@@ -599,10 +599,10 @@ const message = {
|
||||
typeC: '計算',
|
||||
typeCG: '計算+圖形',
|
||||
processName: '行程名稱',
|
||||
processMemoryUsage: '顯存使用',
|
||||
processMemoryUsage: '記憶體使用',
|
||||
temperatureHelper: 'GPU 溫度過高會導致 GPU 頻率下降',
|
||||
performanceStateHelper: '從 P0 (最大性能) 到 P12 (最小性能)',
|
||||
busID: '總線地址',
|
||||
busID: '匯流排地址',
|
||||
persistenceMode: '持續模式',
|
||||
enabled: '開啟',
|
||||
disabled: '關閉',
|
||||
@@ -610,15 +610,15 @@ const message = {
|
||||
displayActive: '顯卡初始化',
|
||||
displayActiveT: '是',
|
||||
displayActiveF: '否',
|
||||
ecc: '是否開啟錯誤檢查和紀正技術',
|
||||
ecc: '是否開啟錯誤檢查和糾正技術',
|
||||
computeMode: '計算模式',
|
||||
default: '預設',
|
||||
exclusiveProcess: '行程排他',
|
||||
exclusiveThread: '線程排他',
|
||||
exclusiveThread: '執行緒排他',
|
||||
prohibited: '禁止',
|
||||
defaultHelper: '預設: 行程可以並發執行',
|
||||
exclusiveProcessHelper: '行程排他: 只有一個 CUDA 上下文可以使用 GPU, 但可以由多個線程共享',
|
||||
exclusiveThreadHelper: '線程排他: 只有一個線程在 CUDA 上下文中可以使用 GPU',
|
||||
exclusiveProcessHelper: '行程排他: 只有一個 CUDA 上下文可以使用 GPU, 但可以由多個執行緒共享',
|
||||
exclusiveThreadHelper: '執行緒排他: 只有一個執行緒在 CUDA 上下文中可以使用 GPU',
|
||||
prohibitedHelper: '禁止: 不允許行程同時執行',
|
||||
migModeHelper: '用於建立 MIG 實例,在用戶層實現 GPU 的物理隔離。',
|
||||
migModeNA: '不支援',
|
||||
@@ -1414,7 +1414,7 @@ const message = {
|
||||
proxyDockerHelper: '將代理伺服器配寘同步至 Docker,支援離線伺服器拉取鏡像等操作',
|
||||
apiInterface: 'API 介面',
|
||||
apiInterfaceClose: '關閉後將不能使用 API 介面進行瀏覽,APP功能將被限制,是否繼續?',
|
||||
apiInterfaceHelper: '支持面板 API 接口訪問功能(面板 APP 需要開啟該功能)',
|
||||
apiInterfaceHelper: '支持面板 API 介面瀏覽功能(面板 APP 需要開啟該功能)',
|
||||
apiInterfaceAlert1: '請不要在生產環境開啟,這可能新增伺服器安全風險',
|
||||
apiInterfaceAlert2: '請不要使用協力廠商應用呼叫面板 API,以防止潛在的安全威脅',
|
||||
apiInterfaceAlert3: 'API 介面檔案',
|
||||
@@ -1692,7 +1692,7 @@ const message = {
|
||||
setting: '升級專業版可以自訂面板 Logo、歡迎簡介等資訊。',
|
||||
monitor: '升級專業版可以查看網站的即時狀態、訪客趨勢、訪客來源、請求日誌等資訊。 ',
|
||||
alert: '升級專業版可透過簡訊接收告警資訊,並查看告警日誌,全面掌控各類關鍵事件,確保系統執行無憂。',
|
||||
app: '升級專業版可以通過手機 APP 管理伺服器並查看監控等功能。',
|
||||
app: '升級專業版可以透過手機 APP 管理伺服器並查看監控等功能。',
|
||||
},
|
||||
clean: {
|
||||
scan: '開始掃描',
|
||||
@@ -2112,7 +2112,7 @@ const message = {
|
||||
sni: '回源 SNI',
|
||||
sniHelper: '反代後端為 https 的時候可能需要設定回源 SNI,具體需要看 CDN 服務商文件',
|
||||
huaweicloud: '華為雲',
|
||||
rainyun: '瑞雲',
|
||||
rainyun: '雨雲',
|
||||
},
|
||||
php: {
|
||||
short_open_tag: '短標籤支援',
|
||||
@@ -2427,12 +2427,12 @@ const message = {
|
||||
aitool: {
|
||||
proxy: 'AI 代理增強',
|
||||
proxyHelper1: '綁定域名並啟用 HTTPS,提高傳輸安全性',
|
||||
proxyHelper2: '限制 IP 訪問,防止在公共網絡上暴露',
|
||||
proxyHelper3: '啟用流式傳輸',
|
||||
proxyHelper2: '限制 IP 瀏覽,防止在網路上暴露',
|
||||
proxyHelper3: '啟用即時串流',
|
||||
proxyHelper4: '創建後,您可以在網站列表中查看並管理',
|
||||
proxyHelper5: '啟用後,您可以在應用商店 - 已安裝 - Ollama - 參數中取消端口外部訪問以提高安全性。',
|
||||
proxyHelper5: '啟用後,您可以在應用商店 - 已安裝 - Ollama - 參數中取消埠外部瀏覽以提高安全性',
|
||||
proxyHelper6: '如需關閉代理配置,可以在網站列表中刪除',
|
||||
whiteListHelper: '限制僅白名單中的 IP 可訪問',
|
||||
whiteListHelper: '限制僅白名單中的 IP 可瀏覽',
|
||||
},
|
||||
};
|
||||
export default {
|
||||
|
||||
@@ -358,7 +358,7 @@ export function checkCidrV6(value: string): boolean {
|
||||
if (checkIpV6(value.split('/')[0])) {
|
||||
return true;
|
||||
}
|
||||
const reg = /^(?:[1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/;
|
||||
const reg = /^(?:[0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$/;
|
||||
if (!reg.test(value.split('/')[1])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ const loadEcc = (val: string) => {
|
||||
if (val === 'Enabled') {
|
||||
return i18n.global.t('ai_tools.gpu.enabled');
|
||||
}
|
||||
return val;
|
||||
return val || 0;
|
||||
};
|
||||
|
||||
const loadProcessType = (val: string) => {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<template #title>
|
||||
<span class="flx-align-center">
|
||||
{{ $t('ai_tools.model.ollama_doc') }}
|
||||
<el-link class="ml-5" icon="Position" @click="goSearch()" type="primary">
|
||||
<el-button link class="ml-5" icon="Position" @click="goSearch()" type="primary">
|
||||
{{ $t('firewall.quickJump') }}
|
||||
</el-link>
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
@@ -202,9 +202,6 @@ const listSSL = () => {
|
||||
const listAcmeAccount = () => {
|
||||
SearchAcmeAccount({ page: 1, pageSize: 100 }).then((res) => {
|
||||
acmeAccounts.value = res.data.items || [];
|
||||
if (acmeAccounts.value.length > 0) {
|
||||
req.value.acmeAccountID = acmeAccounts.value[0].id;
|
||||
}
|
||||
listSSL();
|
||||
});
|
||||
};
|
||||
@@ -238,7 +235,8 @@ const search = async (appInstallID: number) => {
|
||||
if (res.data.sslID > 0) {
|
||||
req.value.enableSSL = true;
|
||||
req.value.sslID = res.data.sslID;
|
||||
listSSL();
|
||||
req.value.acmeAccountID = res.data.acmeAccountID;
|
||||
listAcmeAccount();
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
@@ -114,14 +114,14 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="100"
|
||||
:label="$t('commons.table.createdAt')"
|
||||
min-width="80"
|
||||
:label="$t('commons.table.date')"
|
||||
prop="createdAt"
|
||||
:formatter="dateFormat"
|
||||
/>
|
||||
<fu-table-operations
|
||||
:ellipsis="mobile ? 0 : 10"
|
||||
:min-width="mobile ? 'auto' : 100"
|
||||
:min-width="mobile ? 'auto' : 200"
|
||||
:buttons="buttons"
|
||||
:label="$t('commons.table.operate')"
|
||||
fixed="right"
|
||||
@@ -430,7 +430,7 @@ const buttons = [
|
||||
onDelete(row);
|
||||
},
|
||||
disabled: (row: any) => {
|
||||
return row.status !== 'Success' && row.status !== 'Deleted';
|
||||
return row.status === 'Waiting';
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
import { cleanContainerLog, DownloadFile } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { dateFormatForName } from '@/utils/util';
|
||||
import { computed, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue';
|
||||
import { computed, nextTick, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
@@ -152,10 +152,12 @@ const searchLogs = async () => {
|
||||
);
|
||||
terminalSocket.value.onmessage = (event) => {
|
||||
logInfo.value += event.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '');
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
nextTick(() => {
|
||||
const state = view.value.state;
|
||||
view.value.dispatch({
|
||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
||||
scrollIntoView: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -77,7 +77,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<OpDialog ref="opRef" @search="search" />
|
||||
<OpDialog ref="opRef" @search="search" @submit="onSubmitDelete()">
|
||||
<template #content>
|
||||
<el-form class="mt-4 mb-1" ref="deleteForm" label-position="left">
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="forceDelete" :label="$t('website.forceDelete')" />
|
||||
<span class="input-help">
|
||||
{{ $t('website.forceDeleteHelper') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</OpDialog>
|
||||
<OperateDialog @search="search" ref="dialogRef" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -91,6 +102,7 @@ import { operateForwardRule, searchFireRule } from '@/api/modules/host';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import i18n from '@/lang';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
@@ -107,6 +119,8 @@ const fireName = ref();
|
||||
const fireStatusRef = ref();
|
||||
|
||||
const opRef = ref();
|
||||
const forceDelete = ref(false);
|
||||
const operateRules = ref();
|
||||
|
||||
const data = ref();
|
||||
const paginationConfig = reactive({
|
||||
@@ -180,6 +194,7 @@ const onDelete = async (row: Host.RuleForward | null) => {
|
||||
});
|
||||
}
|
||||
}
|
||||
operateRules.value = rules;
|
||||
opRef.value.acceptParams({
|
||||
title: i18n.global.t('commons.button.delete'),
|
||||
names: names,
|
||||
@@ -187,11 +202,24 @@ const onDelete = async (row: Host.RuleForward | null) => {
|
||||
i18n.global.t('firewall.forwardRule'),
|
||||
i18n.global.t('commons.button.delete'),
|
||||
]),
|
||||
api: operateForwardRule,
|
||||
params: { rules: rules },
|
||||
api: null,
|
||||
params: null,
|
||||
});
|
||||
};
|
||||
|
||||
const onSubmitDelete = async () => {
|
||||
loading.value = true;
|
||||
await operateForwardRule({ rules: operateRules.value, forceDelete: forceDelete.value })
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
|
||||
search();
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.edit'),
|
||||
@@ -208,6 +236,7 @@ const buttons = [
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
forceDelete.value = false;
|
||||
if (fireName.value !== '-') {
|
||||
loading.value = true;
|
||||
fireStatusRef.value.acceptParams();
|
||||
|
||||
@@ -98,7 +98,7 @@ import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { checkCidr, checkIp } from '@/utils/util';
|
||||
import { checkCidr, checkCidrV6, checkIpV4V6 } from '@/utils/util';
|
||||
import { GlobalStore } from '@/store';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
@@ -138,10 +138,16 @@ function checkIPs(rule: any, value: any, callback: any) {
|
||||
continue;
|
||||
}
|
||||
if (item.indexOf('/') !== -1) {
|
||||
if (checkCidr(item)) {
|
||||
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
|
||||
if (item.indexOf(':') !== -1) {
|
||||
if (checkCidrV6(item)) {
|
||||
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
|
||||
}
|
||||
} else {
|
||||
if (checkCidr(item)) {
|
||||
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
|
||||
}
|
||||
}
|
||||
} else if (checkIp(item)) {
|
||||
} else if (checkIpV4V6(item)) {
|
||||
return callback(new Error(i18n.global.t('firewall.addressFormatError')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,11 @@
|
||||
<el-input v-model.trim="account.authorization['token']"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="account.type === 'FreeMyIP'">
|
||||
<el-form-item label="Token" prop="authorization.token">
|
||||
<el-input v-model.trim="account.authorization['token']"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="account.type === 'CloudFlare'">
|
||||
<el-form-item label="EMAIL" prop="authorization.email">
|
||||
<el-input v-model.trim="account.authorization['email']"></el-input>
|
||||
|
||||
@@ -15,7 +15,7 @@ require (
|
||||
github.com/gin-contrib/gzip v0.0.6
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/glebarez/sqlite v1.10.0
|
||||
github.com/go-acme/lego/v4 v4.21.0
|
||||
github.com/go-acme/lego/v4 v4.22.2
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.1
|
||||
github.com/go-playground/validator/v10 v10.18.0
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
@@ -52,13 +52,12 @@ require (
|
||||
github.com/swaggo/swag v1.16.3
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.46
|
||||
github.com/xlzd/gotp v0.1.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/crypto v0.32.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/oauth2 v0.24.0
|
||||
golang.org/x/sys v0.28.0
|
||||
golang.org/x/term v0.27.0
|
||||
golang.org/x/sys v0.29.0
|
||||
golang.org/x/term v0.28.0
|
||||
golang.org/x/text v0.21.0
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/gorm v1.25.7
|
||||
@@ -119,7 +118,7 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.22.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
@@ -194,6 +193,7 @@ require (
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/nrdcg/freemyip v0.3.0 // indirect
|
||||
github.com/nrdcg/namesilo v0.2.1 // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
@@ -258,6 +258,7 @@ require (
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/time v0.8.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
|
||||
@@ -318,15 +318,15 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
|
||||
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||
github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc=
|
||||
github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA=
|
||||
github.com/go-acme/lego/v4 v4.21.0 h1:arEW+8o5p7VI8Bk1kr/PDlgD1DrxtTH1gJ4b7mehL8o=
|
||||
github.com/go-acme/lego/v4 v4.21.0/go.mod h1:HrSWzm3Ckj45Ie3i+p1zKVobbQoMOaGu9m4up0dUeDI=
|
||||
github.com/go-acme/lego/v4 v4.22.2 h1:ck+HllWrV/rZGeYohsKQ5iKNnU/WAZxwOdiu6cxky+0=
|
||||
github.com/go-acme/lego/v4 v4.22.2/go.mod h1:E2FndyI3Ekv0usNJt46mFb9LVpV/XBYT+4E3tz02Tzo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.1 h1:eGS0WTFRV30r103lU8JNXY27KbviRnqqIDobW3EV3iY=
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kRCk+E3UbV2f5gv+1ndLc=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
|
||||
@@ -756,6 +756,8 @@ github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7g
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=
|
||||
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
|
||||
github.com/nrdcg/freemyip v0.3.0 h1:0D2rXgvLwe2RRaVIjyUcQ4S26+cIS2iFwnhzDsEuuwc=
|
||||
github.com/nrdcg/freemyip v0.3.0/go.mod h1:c1PscDvA0ukBF0dwelU/IwOakNKnVxetpAQ863RMJoM=
|
||||
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
|
||||
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
|
||||
@@ -1104,8 +1106,8 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1250,16 +1252,16 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
Reference in New Issue
Block a user