feat: SSL 配置增加重启选项 (#6792)

pull/6793/head
ssongliu 2024-10-21 22:47:14 +08:00 committed by GitHub
parent e531b509d6
commit 9a79dc4cdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 95 additions and 38 deletions

View File

@ -30,6 +30,7 @@ type SettingInfo struct {
ServerPort string `json:"serverPort"`
SSL string `json:"ssl"`
SSLType string `json:"sslType"`
AutoRestart string `json:"autoRestart"`
BindDomain string `json:"bindDomain"`
AllowIPs string `json:"allowIPs"`
SecurityEntrance string `json:"securityEntrance"`
@ -73,12 +74,13 @@ type SettingUpdate struct {
}
type SSLUpdate struct {
SSLType string `json:"sslType" validate:"required,oneof=self select import import-paste import-local"`
Domain string `json:"domain"`
SSL string `json:"ssl" validate:"required,oneof=enable disable"`
Cert string `json:"cert"`
Key string `json:"key"`
SSLID uint `json:"sslID"`
SSLType string `json:"sslType" validate:"required,oneof=self select import import-paste import-local"`
Domain string `json:"domain"`
SSL string `json:"ssl" validate:"required,oneof=enable disable"`
Cert string `json:"cert"`
Key string `json:"key"`
SSLID uint `json:"sslID"`
AutoRestart string `json:"autoRestart"`
}
type SSLInfo struct {
Domain string `json:"domain"`

View File

@ -322,6 +322,9 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
if err := settingRepo.Update("SSL", req.SSL); err != nil {
return err
}
if err := settingRepo.Update("AutoRestart", req.AutoRestart); err != nil {
return err
}
sID, _ := c.Cookie(constant.SessionName)
c.SetCookie(constant.SessionName, sID, 0, "", "", true, true)

View File

@ -3,7 +3,6 @@ package service
import (
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
"log"
"os"
"path"
@ -13,6 +12,8 @@ import (
"strings"
"time"
"github.com/1Panel-dev/1Panel/backend/utils/xpack"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/i18n"
@ -1001,20 +1002,23 @@ func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
}
}
func GetSystemSSL() (bool, uint) {
func GetSystemSSL() (bool, bool, uint) {
sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL"))
if err != nil {
global.LOG.Errorf("load service ssl from setting failed, err: %v", err)
return false, 0
return false, false, 0
}
if sslSetting.Value == "enable" {
sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID"))
idValue, _ := strconv.Atoi(sslID.Value)
if idValue > 0 {
return true, uint(idValue)
if idValue <= 0 {
return false, false, 0
}
auto, _ := settingRepo.Get(settingRepo.WithByKey("AutoRestart"))
return true, auto.Value == "enable", uint(idValue)
}
return false, 0
return false, false, 0
}
func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error {
@ -1033,7 +1037,7 @@ func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error {
return buserr.WithErr(constant.ErrSSLApply, err)
}
}
enable, sslID := GetSystemSSL()
enable, auto, sslID := GetSystemSSL()
if enable && sslID == websiteSSL.ID {
fileOp := files.NewFileOp()
secretDir := path.Join(global.CONF.System.BaseDir, "1panel/secret")
@ -1045,6 +1049,9 @@ func UpdateSSLConfig(websiteSSL model.WebsiteSSL) error {
global.LOG.Errorf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", websiteSSL.PrimaryDomain, err.Error())
return err
}
if auto {
_, _ = cmd.Exec("systemctl restart 1panel.service")
}
}
return nil
}

View File

@ -10,6 +10,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/service"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/files"
)
@ -22,7 +23,7 @@ func NewSSLJob() *ssl {
}
func (ssl *ssl) Run() {
systemSSLEnable, sslID := service.GetSystemSSL()
systemSSLEnable, auto, sslID := service.GetSystemSSL()
sslRepo := repo.NewISSLRepo()
sslService := service.NewIWebsiteSSLService()
sslList, _ := sslRepo.List()
@ -70,6 +71,9 @@ func (ssl *ssl) Run() {
global.LOG.Errorf("Failed to update the SSL certificate for 1Panel System domain [%s] , err:%s", s.PrimaryDomain, err.Error())
continue
}
if auto {
_, _ = cmd.Exec("systemctl restart 1panel.service")
}
}
global.LOG.Infof("The SSL certificate for the [%s] domain has been successfully updated", s.PrimaryDomain)
}

View File

@ -95,6 +95,8 @@ func Init() {
migrations.AddClamStatus,
migrations.AddAlertMenu,
migrations.AddComposeColumn,
migrations.AddAutoRestart,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

View File

@ -324,3 +324,13 @@ var AddComposeColumn = &gormigrate.Migration{
return nil
},
}
var AddAutoRestart = &gormigrate.Migration{
ID: "20241021-add-auto-restart",
Migrate: func(tx *gorm.DB) error {
if err := tx.Create(&model.Setting{Key: "AutoRestart", Value: "enable"}).Error; err != nil {
return err
}
return nil
},
}

View File

@ -29,6 +29,7 @@ export namespace Setting {
bindAddress: string;
ssl: string;
sslType: string;
autoRestart: string;
allowIPs: string;
bindDomain: string;
securityEntrance: string;

View File

@ -4,6 +4,7 @@
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
:before-close="handleClose"
:size="globalStore.isFullScreen ? '100%' : '50%'"
>
<template #header>
@ -21,10 +22,10 @@
</el-drawer>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { computed, ref, watch } from 'vue';
import LogFile from '@/components/log-file/index.vue';
import { GlobalStore } from '@/store';
import screenfull from 'screenfull';
import { GlobalStore } from '@/store';
import i18n from '@/lang';
const globalStore = GlobalStore();
@ -45,19 +46,22 @@ const open = ref(false);
const config = ref();
const em = defineEmits(['close']);
const handleClose = (search: boolean) => {
const handleClose = () => {
open.value = false;
em('close', search);
em('close', false);
globalStore.isFullScreen = false;
};
watch(open, (val) => {
if (screenfull.isEnabled && !val && !mobile.value) screenfull.exit();
});
function toggleFullscreen() {
if (screenfull.isEnabled) {
screenfull.toggle();
}
globalStore.isFullScreen = !globalStore.isFullScreen;
}
const loadTooltip = () => {
return i18n.global.t('commons.button.' + (screenfull.isFullscreen ? 'quitFullscreen' : 'fullscreen'));
return i18n.global.t('commons.button.' + (globalStore.isFullScreen ? 'quitFullscreen' : 'fullscreen'));
};
const acceptParams = (props: LogProps) => {

View File

@ -1518,8 +1518,11 @@ const message = {
bindDomain: 'Bind Domain',
unBindDomain: 'Unbind domain',
panelSSL: 'Panel SSL',
panelSSLHelper:
'After the automatic renewal of the panel SSL, you need to manually restart the 1Panel service for the changes to take effect.',
sslAutoRestart: 'Restart 1Panel service after certificate auto-renewal',
sslChangeHelper1:
'Currently, automatic restart of 1Panel service is not selected. The certificate auto-renewal will not take effect immediately and will still require a manual restart of 1Panel.',
sslChangeHelper2:
'The 1Panel service will automatically restart after setting the panel SSL. Do you want to continue?',
unBindDomainHelper:
'The action of unbinding a domain name may cause system insecurity. Do you want to continue?',
bindDomainHelper:

View File

@ -1468,7 +1468,9 @@ const message = {
bindDomain: '',
unBindDomain: '',
panelSSL: ' SSL',
panelSSLHelper: ' SSL 1Panel ',
sslAutoRestart: ' 1Panel ',
sslChangeHelper1: ' 1Panel 1Panel',
sslChangeHelper2: ' SSL 1Panel ',
unBindDomainHelper: '',
bindDomainHelper: ' 1Panel ',
bindDomainHelper1: '',

View File

@ -1470,7 +1470,9 @@ const message = {
bindDomain: '',
unBindDomain: '',
panelSSL: ' SSL',
panelSSLHelper: ' SSL 1Panel ',
sslAutoRestart: ' 1Panel ',
sslChangeHelper1: ' 1Panel 1Panel',
sslChangeHelper2: ' SSL 1Panel ',
unBindDomainHelper: '',
bindDomainHelper: '访 1Panel ',
bindDomainHelper1: '',
@ -1494,7 +1496,6 @@ const message = {
mfaInterval: '',
mfaTitleHelper: ' 1Panel ',
mfaIntervalHelper: '',
sslChangeHelper: 'https ',
sslDisable: '',
sslDisableHelper: ' https ',
noAuthSetting: '',

View File

@ -114,7 +114,7 @@
<div v-if="form.ssl === 'enable' && sslInfo">
<el-tag>{{ $t('setting.domainOrIP') }} {{ sslInfo.domain }}</el-tag>
<el-tag style="margin-left: 5px">
{{ $t('setting.timeOut') }} {{ sslInfo.timeout }}
{{ $t('setting.timeOut') }} {{ dateFormat('', '', sslInfo.timeout) }}
</el-tag>
<div>
<el-button link type="primary" @click="handleSSL">
@ -194,6 +194,7 @@ import TimeoutSetting from '@/views/setting/safe/timeout/index.vue';
import EntranceSetting from '@/views/setting/safe/entrance/index.vue';
import DomainSetting from '@/views/setting/safe/domain/index.vue';
import AllowIPsSetting from '@/views/setting/safe/allowips/index.vue';
import { dateFormat } from '@/utils/util';
import { updateSetting, getSettingInfo, getSystemAvailable, updateSSL, loadSSLInfo } from '@/api/modules/setting';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
@ -224,6 +225,7 @@ const form = reactive({
bindAddress: '',
ssl: 'disable',
sslType: 'self',
autoRestart: 'disable',
securityEntrance: '',
expirationDays: 0,
expirationTime: '',
@ -248,6 +250,7 @@ const search = async () => {
if (form.ssl === 'enable') {
loadInfo();
}
form.autoRestart = res.data.autoRestart;
form.securityEntrance = res.data.securityEntrance;
form.expirationDays = Number(res.data.expirationDays);
form.expirationTime = res.data.expirationTime;
@ -327,6 +330,7 @@ const handleSSL = async () => {
ssl: form.ssl,
sslType: form.sslType,
sslInfo: sslInfo.value,
autoRestart: form.autoRestart,
};
sslRef.value!.acceptParams(params);
return;

View File

@ -11,13 +11,6 @@
<template #header>
<DrawerHeader :header="$t('setting.panelSSL')" :back="handleClose" />
</template>
<el-alert class="common-prompt" :closable="false" type="error">
<template #default>
<span>
<span>{{ $t('setting.panelSSLHelper') }}</span>
</span>
</template>
</el-alert>
<el-form ref="formRef" label-position="top" :model="form" :rules="rules" v-loading="loading">
<el-row type="flex" justify="center">
<el-col :span="22">
@ -40,7 +33,9 @@
<el-form-item v-if="form.timeout">
<el-tag>{{ $t('setting.domainOrIP') }} {{ form.domain }}</el-tag>
<el-tag style="margin-left: 5px">{{ $t('setting.timeOut') }} {{ form.timeout }}</el-tag>
<el-tag style="margin-left: 5px">
{{ $t('setting.timeOut') }} {{ dateFormat('', '', form.timeout) }}
</el-tag>
<el-button
@click="onDownload"
style="margin-left: 5px"
@ -117,6 +112,14 @@
</el-descriptions-item>
</el-descriptions>
</div>
<el-form-item v-if="form.sslType !== 'import'">
<el-checkbox true-value="enable" false-value="disable" v-model="form.autoRestart">
{{ $t('setting.sslAutoRestart') }}
</el-checkbox>
<span v-if="form.autoRestart === 'disable'" class="input-help">
{{ $t('setting.sslChangeHelper1') }}
</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
@ -133,7 +136,7 @@
</template>
<script lang="ts" setup>
import { Website } from '@/api/interface/website';
import { dateFormatSimple, getProvider } from '@/utils/util';
import { dateFormatSimple, dateFormat, getProvider } from '@/utils/util';
import { ListSSL } from '@/api/modules/website';
import { reactive, ref } from 'vue';
import i18n from '@/lang';
@ -159,6 +162,7 @@ const form = reactive({
key: '',
rootPath: '',
timeout: '',
autoRestart: 'disable',
});
const rules = reactive({
@ -175,6 +179,7 @@ const itemSSL = ref();
interface DialogProps {
sslType: string;
sslInfo?: Setting.SSLInfo;
autoRestart: string;
}
const acceptParams = async (params: DialogProps): Promise<void> => {
if (params.sslType.indexOf('-') !== -1) {
@ -197,6 +202,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
} else {
loadSSLs();
}
form.autoRestart = params.autoRestart;
drawerVisible.value = true;
};
const emit = defineEmits<{ (e: 'search'): void }>();
@ -237,7 +243,10 @@ const onSaveSSL = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
ElMessageBox.confirm(i18n.global.t('setting.sslChangeHelper'), 'https', {
let msg = !form.autoRestart
? i18n.global.t('setting.sslChangeHelper1') + '\n\n\n' + 'qwdqwdqwd'
: i18n.global.t('setting.sslChangeHelper2');
ElMessageBox.confirm(msg, i18n.global.t('setting.panelSSL'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
@ -253,6 +262,7 @@ const onSaveSSL = async (formEl: FormInstance | undefined) => {
sslID: form.sslID,
cert: form.cert,
key: form.key,
autoRestart: form.autoRestart,
};
let href = window.location.href;
param.domain = href.split('//')[1].split(':')[0];

View File

@ -92,6 +92,10 @@ let timer: NodeJS.Timer | null = null;
const em = defineEmits(['search']);
watch(open, (val) => {
if (screenfull.isEnabled && !val && !mobile.value) screenfull.exit();
});
const mobile = computed(() => {
return globalStore.isMobile();
});