9 Commits

19 changed files with 108 additions and 60 deletions

View File

@@ -4,7 +4,7 @@ import "github.com/1Panel-dev/1Panel/backend/app/dto"
type WebsiteSSLSearch struct {
dto.PageInfo
AcmeAccountID uint `json:"acmeAccountId"`
AcmeAccountID string `json:"acmeAccountID"`
}
type WebsiteSSLCreate struct {

View File

@@ -593,6 +593,9 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
config := getAppCommonConfig(envs)
config.DockerCompose = install.DockerCompose
res.Params = params
if config.ContainerName == "" {
config.ContainerName = install.ContainerName
}
res.AppContainerConfig = config
return &res, nil
}

View File

@@ -381,6 +381,9 @@ func getContainerNames(install model.AppInstall) ([]string, error) {
for k := range containerMap {
containerNames = append(containerNames, k)
}
if len(containerNames) == 0 {
containerNames = append(containerNames, install.ContainerName)
}
return containerNames, nil
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/ssl"
"path"
"strconv"
"strings"
)
@@ -66,7 +67,14 @@ func (w WebsiteSSLService) Search(search request.WebsiteSSLSearch) ([]response.W
opts []repo.DBOption
result []response.WebsiteSSLDTO
)
opts = append(opts, commonRepo.WithOrderBy("created_at desc"), websiteSSLRepo.WithByAcmeAccountId(search.AcmeAccountID))
opts = append(opts, commonRepo.WithOrderBy("created_at desc"))
if search.AcmeAccountID != "" {
acmeAccountID, err := strconv.ParseUint(search.AcmeAccountID, 10, 64)
if err != nil {
return nil, err
}
opts = append(opts, websiteSSLRepo.WithByAcmeAccountId(uint(acmeAccountID)))
}
sslList, err := websiteSSLRepo.List(opts...)
if err != nil {
return nil, err

View File

@@ -82,6 +82,7 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m
ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
ErrObjectInUsed: "This object is in use and cannot be deleted"
ErrRepoConn: "The repository information contains illegal characters"
ErrPortRules: "The number of ports does not match, please re-enter!"
#runtime
ErrDirNotFound: "The build folder does not exist! Please check file integrity"

View File

@@ -82,6 +82,7 @@ ErrTypeOfRedis: "恢復文件類型與當前持久化方式不符,請修改後
ErrInUsed: "{{ .detail }} 正被使用,無法刪除"
ErrObjectInUsed: "該對象正被使用,無法刪除"
ErrRepoConn: "倉庫資訊中存在不合法的字符"
ErrPortRules: "端口數目不匹配,請重新輸入!"
#runtime
ErrDirNotFound: "build 文件夾不存在!請檢查文件完整性!"

View File

@@ -82,6 +82,7 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
ErrObjectInUsed: "该对象正被使用,无法删除"
ErrRepoConn: "仓库信息中存在不合法的字符"
ErrPortRules: "端口数目不匹配,请重新输入!"
#runtime
ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!"

View File

@@ -437,7 +437,7 @@ var EncryptHostPassword = &gormigrate.Migration{
ID: "20230703-encrypt-host-password",
Migrate: func(tx *gorm.DB) error {
var hosts []model.Host
if err := tx.Find(&hosts).Error; err != nil {
if err := tx.Where("1 = 1").Find(&hosts).Error; err != nil {
return err
}
@@ -462,7 +462,7 @@ var EncryptHostPassword = &gormigrate.Migration{
if err != nil {
return err
}
if err := tx.Model(&model.Host{}).Update("private_key", key).Error; err != nil {
if err := tx.Model(&model.Host{}).Where("id = ?", host.ID).Update("private_key", key).Error; err != nil {
return err
}
}
@@ -471,7 +471,7 @@ var EncryptHostPassword = &gormigrate.Migration{
if err != nil {
return err
}
if err := tx.Model(&model.Host{}).Update("pass_phrase", pass).Error; err != nil {
if err := tx.Model(&model.Host{}).Where("id = ?", host.ID).Update("pass_phrase", pass).Error; err != nil {
return err
}
}

View File

@@ -1,5 +1,5 @@
// Code generated by swaggo/swag. DO NOT EDIT.
// Package docs GENERATED BY SWAG; DO NOT EDIT
// This file was generated by swaggo/swag
package docs
import "github.com/swaggo/swag"
@@ -11068,6 +11068,9 @@ const docTemplate = `{
"$ref": "#/definitions/dto.PortHelper"
}
},
"forcePull": {
"type": "boolean"
},
"image": {
"type": "string"
},
@@ -11078,13 +11081,13 @@ const docTemplate = `{
}
},
"memory": {
"type": "integer"
"type": "number"
},
"name": {
"type": "string"
},
"nanoCPUs": {
"type": "integer"
"type": "number"
},
"network": {
"type": "string"
@@ -11198,6 +11201,9 @@ const docTemplate = `{
"name"
],
"properties": {
"forcePull": {
"type": "boolean"
},
"image": {
"type": "string"
},
@@ -15159,8 +15165,8 @@ const docTemplate = `{
"pageSize"
],
"properties": {
"acmeAccountId": {
"type": "integer"
"acmeAccountID": {
"type": "string"
},
"page": {
"type": "integer"

View File

@@ -11061,6 +11061,9 @@
"$ref": "#/definitions/dto.PortHelper"
}
},
"forcePull": {
"type": "boolean"
},
"image": {
"type": "string"
},
@@ -11071,13 +11074,13 @@
}
},
"memory": {
"type": "integer"
"type": "number"
},
"name": {
"type": "string"
},
"nanoCPUs": {
"type": "integer"
"type": "number"
},
"network": {
"type": "string"
@@ -11191,6 +11194,9 @@
"name"
],
"properties": {
"forcePull": {
"type": "boolean"
},
"image": {
"type": "string"
},
@@ -15152,8 +15158,8 @@
"pageSize"
],
"properties": {
"acmeAccountId": {
"type": "integer"
"acmeAccountID": {
"type": "string"
},
"page": {
"type": "integer"

View File

@@ -327,6 +327,8 @@ definitions:
items:
$ref: '#/definitions/dto.PortHelper'
type: array
forcePull:
type: boolean
image:
type: string
labels:
@@ -334,11 +336,11 @@ definitions:
type: string
type: array
memory:
type: integer
type: number
name:
type: string
nanoCPUs:
type: integer
type: number
network:
type: string
publishAllPorts:
@@ -413,6 +415,8 @@ definitions:
type: object
dto.ContainerUpgrade:
properties:
forcePull:
type: boolean
image:
type: string
name:
@@ -3063,8 +3067,8 @@ definitions:
type: object
request.WebsiteSSLSearch:
properties:
acmeAccountId:
type: integer
acmeAccountID:
type: string
page:
type: integer
pageSize:

View File

@@ -208,7 +208,7 @@ export namespace Website {
export interface SSLReq {
name?: string;
acmeAccountID?: number;
acmeAccountID?: string;
}
export interface HTTPSReq {

View File

@@ -1,21 +1,9 @@
html.dark {
--el-box-shadow-light: 0px 0px 4px rgba(0, 0, 0, 0.1) !important;
--el-border-color-lighter: #1d2023;
--el-fill-color-blank: #111417;
--el-bg-color: rgba(0, 11, 21, 1);
// --el-text-color-primary: #999999;
--el-text-color-regular: #bbbfc4 !important;
--el-fill-color-light: #111417;
--el-border-color: #303438;
--el-bg-color-overlay: rgba(0, 11, 21, 1);
--el-border-color-light: #1d2023;
// * menu
--el-menu-bg-color: #111417 !important;
--el-menu-item-bg-color: #111417;
--el-menu-text-color: #ffffff;
--el-menu-item-bg-color-active: rgb(44, 45, 46);
// * panel-admin
--panel-bg-color: #1f1f1f;
--panel-border-color: #363b3f;
--panel-main-txt-color: #ebebeb;
--panel-text-color: rgb(174, 166, 153);
--panel-border: 1px solid #1d2023;
--panel-border-color: #394c5e;
@@ -29,12 +17,28 @@ html.dark {
--panel-path-bg: #2f3030;
--panel-button-disabled: #5a5a5a;
--el-box-shadow-light: 0px 0px 4px rgba(0, 0, 0, 0.1) !important;
--el-border-color-lighter: #1d2023;
--el-fill-color-blank: var(--panel-bg-color);
--el-bg-color: rgba(0, 11, 21, 1);
// --el-text-color-primary: #999999;
--el-text-color-regular: #bbbfc4 !important;
--el-fill-color-light: var(--panel-bg-color);
--el-border-color: #303438;
--el-bg-color-overlay: rgba(0, 11, 21, 1);
--el-border-color-light: #1d2023;
// * menu
--el-menu-bg-color: var(--panel-bg-color) !important;
--el-menu-item-bg-color: var(--panel-bg-color);
--el-menu-text-color: var(--panel-main-txt-color);
--el-menu-item-bg-color-active: rgb(44, 45, 46);
.el-tag.el-tag--info {
--el-tag-bg-color: rgb(49, 51, 51);
--el-tag-border-color: rgb(64, 67, 67);
}
.el-tag.el-tag--light {
--el-tag-bg-color: #111417;
--el-tag-bg-color: var(--panel-bg-color);
--el-tag-border-color: var(--el-color-primary);
}
.el-tag.el-tag--success {
@@ -44,9 +48,9 @@ html.dark {
--el-tag-border-color: var(--el-color-danger);
}
.el-card {
--el-card-bg-color: #111417;
color: #ffffff;
border: 1px solid var(--el-card-border-color) !important;
--el-card-bg-color: var(--panel-bg-color);
color: var(--panel-main-txt-color);
border: 1px solid var(--panel-border-color) !important;
}
.el-table {
@@ -84,7 +88,7 @@ html.dark {
--w-e-textarea-color: #eeeeee;
.md-editor-dark {
--md-bk-color: #111417;
--md-bk-color: var(--panel-bg-color);
}
// * 以下为自定义暗黑模式内容
@@ -98,7 +102,7 @@ html.dark {
transition: background-color 1000s ease-out 0.5s;
}
.el-input__wrapper {
background-color: #ffffff;
background-color: var(--panel-main-txt-color);
box-shadow: 0 0 0 1px #dcdfe6 inset;
}
.el-input__inner {
@@ -131,18 +135,18 @@ html.dark {
}
&.is-active {
background: var(--el-color-primary);
color: #ffffff;
color: var(--panel-main-txt-color);
&:hover {
.el-icon {
color: #ffffff !important;
color: var(--panel-main-txt-color) !important;
}
span {
color: #ffffff !important;
color: var(--panel-main-txt-color) !important;
}
}
&::before {
background: #ffffff;
background: var(--panel-main-txt-color);
}
}
}
@@ -171,7 +175,7 @@ html.dark {
.mobile-header {
background-color: var(--panel-main-bg-color) !important;
border-bottom: var(--panel-border);
color: #ffffff;
color: var(--panel-main-txt-color);
}
}
.system-label {
@@ -183,7 +187,7 @@ html.dark {
background: none;
}
.el-radio-button__original-radio:checked + .el-radio-button__inner {
color: #ffffff;
color: var(--panel-main-txt-color);
box-shadow: none !important;
}
}
@@ -240,7 +244,7 @@ html.dark {
transition: background-color 1000s ease-out 0.5s;
}
.el-avatar {
--el-avatar-bg-color: #111417 !important;
--el-avatar-bg-color: var(--panel-bg-color) !important;
box-shadow: 0px 0px 4px rgba(0, 94, 235, 0.1);
border: 0.5px solid #1f2022;
}

View File

@@ -224,7 +224,7 @@ const submit = async (formEl: FormInstance | undefined) => {
if (req.memoryLimit < 0) {
req.memoryLimit = 0;
}
if (req.advanced && !req.allowPort) {
if (installData.value.app.key != 'openresty' && req.advanced && !req.allowPort) {
ElMessageBox.confirm(i18n.global.t('app.installWarn'), i18n.global.t('app.checkTitle'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),

View File

@@ -119,7 +119,7 @@
</div>
<div v-if="row.expand && row.ports.length > 3">
<el-button type="primary" link @click="row.expand = false">
{{ $t('commons.button.shrink') }}
{{ $t('commons.button.collapse') }}
</el-button>
</div>
</div>

View File

@@ -264,6 +264,7 @@ const acceptParams = (params: DialogProps): void => {
title.value = i18n.global.t('container.' + dialogData.value.title);
if (params.title === 'edit') {
dialogData.value.rowData.memory = Number(dialogData.value.rowData.memory.toFixed(2));
dialogData.value.rowData.cmd = dialogData.value.rowData.cmd || [];
let itemCmd = '';
for (const item of dialogData.value.rowData.cmd) {
itemCmd += `'${item}' `;

View File

@@ -239,6 +239,7 @@ const isSafety = ref();
const chartOption = ref('network');
let timer: NodeJS.Timer | null = null;
let isInit = ref<boolean>(true);
let isStatusInit = ref<boolean>(true);
let isActive = ref(true);
const ioReadBytes = ref<Array<number>>([]);
@@ -355,7 +356,8 @@ const onLoadBaseInfo = async (isInit: boolean, range: string) => {
baseInfo.value = res.data;
currentInfo.value = baseInfo.value.currentInfo;
await onLoadCurrentInfo();
statuRef.value.acceptParams(currentInfo.value, baseInfo.value);
isStatusInit.value = false;
statuRef.value.acceptParams(currentInfo.value, baseInfo.value, isStatusInit.value);
appRef.value.acceptParams();
if (isInit) {
timer = setInterval(async () => {
@@ -421,7 +423,7 @@ const onLoadCurrentInfo = async () => {
}
loadData();
currentInfo.value = res.data;
statuRef.value.acceptParams(currentInfo.value, baseInfo.value);
statuRef.value.acceptParams(currentInfo.value, baseInfo.value, isStatusInit.value);
};
function loadUpTime(uptime: number) {
@@ -460,7 +462,7 @@ function loadUpTime(uptime: number) {
);
}
if (minutes !== 0) {
return minutes + i18n.global.t('home.Minute') + ' ' + seconds + i18n.global.t('commons.units.second');
return minutes + i18n.global.t('commons.units.minute') + ' ' + seconds + i18n.global.t('commons.units.second');
}
return seconds + i18n.global.t('commons.units.second');
}

View File

@@ -201,7 +201,7 @@ const currentInfo = ref<Dashboard.CurrentInfo>({
shotTime: new Date(),
});
const acceptParams = (current: Dashboard.CurrentInfo, base: Dashboard.BaseInfo): void => {
const acceptParams = (current: Dashboard.CurrentInfo, base: Dashboard.BaseInfo, isInit: boolean): void => {
currentInfo.value = current;
baseInfo.value = base;
freshChart('cpu', 'CPU', formatNumber(currentInfo.value.cpuUsedPercent));
@@ -215,7 +215,7 @@ const acceptParams = (current: Dashboard.CurrentInfo, base: Dashboard.BaseInfo):
freshChart('disk' + i, itemPath, formatNumber(currentInfo.value.diskData[i].usedPercent));
}
if (currentInfo.value.diskData.length > 5) {
showMore.value = false;
showMore.value = isInit ? false : showMore.value || false;
}
});
};

View File

@@ -207,7 +207,7 @@ const rules = ref({
});
const resData = ref();
const sslReq = reactive({
acmeAccountID: 0,
acmeAccountID: '',
});
const getPrivateKeyPath = (path: string) => {
@@ -218,11 +218,20 @@ const getCertificatePath = (path: string) => {
form.certificatePath = path;
};
const listSSL = () => {
sslReq.acmeAccountID = form.acmeAccountID;
sslReq.acmeAccountID = String(form.acmeAccountID);
ListSSL(sslReq).then((res) => {
ssls.value = res.data || [];
if (ssls.value.length > 0) {
form.websiteSSLId = ssls.value[0].id;
let exist = false;
for (const ssl of ssls.value) {
if (ssl.id === form.websiteSSLId) {
exist = true;
break;
}
}
if (!exist) {
form.websiteSSLId = ssls.value[0].id;
}
changeSSl(form.websiteSSLId);
} else {
websiteSSL.value = {};
@@ -269,7 +278,6 @@ const get = () => {
if (res.data.SSL && res.data.SSL.id > 0) {
form.websiteSSLId = res.data.SSL.id;
websiteSSL.value = res.data.SSL;
sslReq.acmeAccountID = res.data.SSL.acmeAccountId;
form.acmeAccountID = res.data.SSL.acmeAccountId;
}
}