feat: 完成端口修改功能

This commit is contained in:
ssongliu 2023-02-02 15:01:37 +08:00 committed by ssongliu
parent aa4cec47d9
commit 1946eb2313
20 changed files with 129 additions and 77 deletions

View File

View File

@ -11,6 +11,7 @@ type SettingRepo struct{}
type ISettingRepo interface {
GetList(opts ...DBOption) ([]model.Setting, error)
Get(opts ...DBOption) (model.Setting, error)
Create(key, value string) error
Update(key, value string) error
WithByKey(key string) DBOption
}
@ -29,6 +30,14 @@ func (u *SettingRepo) GetList(opts ...DBOption) ([]model.Setting, error) {
return settings, err
}
func (u *SettingRepo) Create(key, value string) error {
setting := &model.Setting{
Key: key,
Value: value,
}
return global.DB.Create(setting).Error
}
func (u *SettingRepo) Get(opts ...DBOption) (model.Setting, error) {
var settings model.Setting
db := global.DB.Model(&model.Setting{})

View File

@ -2,7 +2,6 @@ package service
import (
"encoding/json"
"errors"
"strconv"
"time"
@ -63,15 +62,16 @@ func (u *SettingService) Update(c *gin.Context, key, value string) error {
}
func (u *SettingService) UpdatePort(port uint) error {
global.Viper.Set("system.port", port)
if err := global.Viper.WriteConfig(); err != nil {
if err := settingRepo.Update("ServerPort", strconv.Itoa(int(port))); err != nil {
return err
}
_ = settingRepo.Update("ServerPort", strconv.Itoa(int(port)))
stdout, err := cmd.Exec("systemctl restart 1panel.service")
if err != nil {
return errors.New(stdout)
}
_ = settingRepo.Update("SystemStatus", "Restarting")
go func() {
_, err := cmd.Exec("systemctl restart 1panel.service")
if err != nil {
global.LOG.Errorf("restart system port failed, err: %v")
}
}()
return nil
}

View File

@ -75,18 +75,14 @@ func (u *UpgradeService) Upgrade(version string) error {
originalDir := fmt.Sprintf("%s/%s/original", constant.TmpDir, timeStr)
downloadPath := fmt.Sprintf("%s/releases/%s/%s.tar.gz", global.CONF.System.AppOss, version, version)
setting, err := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
if err != nil {
return err
}
u.changeStatus(constant.StatusWaiting, nil)
_ = settingRepo.Update("SystemStatus", "Upgrading")
go func() {
if err := os.MkdirAll(originalDir, os.ModePerm); err != nil {
u.changeStatus(setting.Value, err)
global.LOG.Error(err.Error())
return
}
if err := fileOp.DownloadFile(downloadPath, filePath); err != nil {
u.changeStatus(setting.Value, fmt.Errorf("download file failed, err: %v", err))
global.LOG.Errorf("download file failed, err: %v", err)
return
}
global.LOG.Info("download file from oss successful!")
@ -94,34 +90,35 @@ func (u *UpgradeService) Upgrade(version string) error {
_ = os.Remove(filePath)
}()
if err := fileOp.Decompress(filePath, rootDir, files.TarGz); err != nil {
u.changeStatus(setting.Value, fmt.Errorf("decompress file failed, err: %v", err))
global.LOG.Errorf("decompress file failed, err: %v", err)
return
}
if err := u.handleBackup(fileOp, originalDir); err != nil {
u.changeStatus(setting.Value, fmt.Errorf("handle backup original file failed, err: %v", err))
global.LOG.Errorf("handle backup original file failed, err: %v", err)
return
}
global.LOG.Info("backup original data successful, now start to upgrade!")
if err := cpBinary(rootDir+"/1panel", "/usr/local/bin/1panel"); err != nil {
u.handleRollback(fileOp, originalDir, 1)
u.changeStatus(setting.Value, fmt.Errorf("upgrade 1panel failed, err: %v", err))
global.LOG.Errorf("upgrade 1panel failed, err: %v", err)
return
}
if err := cpBinary(rootDir+"/1pctl", "/usr/local/bin/1pctl"); err != nil {
u.handleRollback(fileOp, originalDir, 2)
u.changeStatus(setting.Value, fmt.Errorf("upgrade 1pctl failed, err: %v", err))
global.LOG.Errorf("upgrade 1pctl failed, err: %v", err)
return
}
if err := cpBinary(rootDir+"/1panel.service", "/etc/systemd/system/1panel.service"); err != nil {
u.handleRollback(fileOp, originalDir, 3)
u.changeStatus(setting.Value, fmt.Errorf("upgrade 1panel.service failed, err: %v", err))
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
return
}
global.LOG.Info("upgrade successful!")
u.changeStatus(version, nil)
_ = settingRepo.Update("SystemStatus", "Upgrade")
_ = settingRepo.Update("SystemVersion", version)
_, _ = cmd.Exec("systemctl restart 1panel.service")
}()
return nil
@ -165,12 +162,3 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string,
global.LOG.Errorf("rollback 1panel failed, err: %v", err)
}
}
func (u *UpgradeService) changeStatus(status string, err error) {
if err != nil {
global.LOG.Error(err.Error())
}
if err := settingRepo.Update("SystemVersion", status); err != nil {
global.LOG.Errorf("update system version failed, err: %v", err)
}
}

View File

@ -1,7 +1,7 @@
package configs
type System struct {
Port int `mapstructure:"port"`
Port string `mapstructure:"port"`
DbFile string `mapstructure:"db_file"`
DbPath string `mapstructure:"db_path"`
LogPath string `mapstructure:"log_path"`

22
backend/init/hook/hook.go Normal file
View File

@ -0,0 +1,22 @@
package hook
import (
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/global"
)
func Init() {
settingRepo := repo.NewISettingRepo()
portSetting, err := settingRepo.Get(settingRepo.WithByKey("ServerPort"))
if err != nil {
global.LOG.Errorf("load service port from setting failed, err: %v", err)
}
global.CONF.System.Port = portSetting.Value
if _, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus")); err != nil {
_ = settingRepo.Create("SystemStatus", "Free")
}
if err := settingRepo.Update("SystemStatus", "Free"); err != nil {
global.LOG.Fatalf("init service before start failed, err: %v", "Free")
}
}

View File

@ -99,7 +99,7 @@ var AddTableSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "ExpirationDays", Value: "0"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "ComplexityVerification", Value: "enable"}).Error; err != nil {
if err := tx.Create(&model.Setting{Key: "ComplexityVerification", Value: "disable"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "MFAStatus", Value: "disable"}).Error; err != nil {
@ -131,6 +131,9 @@ var AddTableSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "SystemVersion", Value: "v1.0.0"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "SystemStatus", Value: "Free"}).Error; err != nil {
return err
}
return nil
},
}

View File

@ -10,13 +10,13 @@ import (
func GlobalLoading() gin.HandlerFunc {
return func(c *gin.Context) {
settingRepo := repo.NewISettingRepo()
upgradeSetting, err := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
status, err := settingRepo.Get(settingRepo.WithByKey("SystemStatus"))
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if upgradeSetting.Value == constant.StatusWaiting {
helper.ErrorWithDetail(c, constant.CodeGlobalLoading, "Upgrading", err)
if status.Value != "Free" {
helper.ErrorWithDetail(c, constant.CodeGlobalLoading, status.Value, err)
return
}
c.Next()

View File

@ -15,6 +15,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/init/db"
"github.com/1Panel-dev/1Panel/backend/init/hook"
"github.com/1Panel-dev/1Panel/backend/init/log"
"github.com/1Panel-dev/1Panel/backend/init/migration"
"github.com/1Panel-dev/1Panel/backend/init/router"
@ -38,11 +39,12 @@ func Start() {
gin.SetMode("debug")
cron.Run()
business.Init()
hook.Init()
rootRouter := router.Routers()
address := fmt.Sprintf(":%d", global.CONF.System.Port)
address := fmt.Sprintf(":%s", global.CONF.System.Port)
s := initServer(address, rootRouter)
global.LOG.Infof("server run success on %d", global.CONF.System.Port)
global.LOG.Infof("server run success on %s", global.CONF.System.Port)
if err := s.ListenAndServe(); err != nil {
global.LOG.Error(err)
panic(err)

View File

@ -1,5 +1,4 @@
system:
port: 9999
db_file: 1Panel.db
app_oss: "https://1panel.oss-cn-hangzhou.aliyuncs.com"

View File

@ -29,8 +29,6 @@ declare module 'vue' {
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']

View File

@ -63,6 +63,7 @@ export default {
},
loadingText: {
Upgrading: 'System upgrade, please wait...',
Restarting: 'System restart, please wait...',
},
msg: {
delete: 'This operation cannot be rolled back. Do you want to continue',

View File

@ -66,6 +66,7 @@ export default {
},
loadingText: {
Upgrading: '系统升级中请稍候...',
Restarting: '系统重启中请稍候...',
},
msg: {
delete: '删除 操作不可回滚是否继续',

View File

@ -350,6 +350,7 @@ onMounted(() => {
onUnmounted(() => {
clearInterval(Number(timer));
timer = null;
});
</script>

View File

@ -123,7 +123,7 @@ const initTerm = (formEl: FormInstance | undefined) => {
formEl.validate(async (valid) => {
if (!valid) return;
let href = window.location.href;
let ipLocal = href.split('//')[1].split(':')[0];
let ipLocal = href.split('//')[1].split('/')[0];
terminalOpen.value = true;
let ifm = document.getElementById('terminal-exec') as HTMLInputElement | null;
term = new Terminal({
@ -141,7 +141,7 @@ const initTerm = (formEl: FormInstance | undefined) => {
if (ifm) {
term.open(ifm);
terminalSocket = new WebSocket(
`ws://${ipLocal}:9999/api/v1/containers/exec?containerid=${form.containerID}&cols=${term.cols}&rows=${term.rows}&user=${form.user}&command=${form.command}`,
`ws://${ipLocal}/api/v1/containers/exec?containerid=${form.containerID}&cols=${term.cols}&rows=${term.rows}&user=${form.user}&command=${form.command}`,
);
terminalSocket.onopen = runRealTerminal;
terminalSocket.onmessage = onWSReceive;

View File

@ -70,7 +70,7 @@ const closeRealTerminal = (ev: CloseEvent) => {
const initTerm = () => {
let ifm = document.getElementById('terminal-exec') as HTMLInputElement | null;
let href = window.location.href;
let ipLocal = href.split('//')[1].split(':')[0];
let ipLocal = href.split('//')[1].split('/')[0];
term = new Terminal({
lineHeight: 1.2,
fontSize: 12,
@ -86,7 +86,7 @@ const initTerm = () => {
if (ifm) {
term.open(ifm);
terminalSocket = new WebSocket(
`ws://${ipLocal}:9999/api/v1/databases/redis/exec?cols=${term.cols}&rows=${term.rows}`,
`ws://${ipLocal}/api/v1/databases/redis/exec?cols=${term.cols}&rows=${term.rows}`,
);
terminalSocket.onopen = runRealTerminal;
terminalSocket.onmessage = onWSReceive;

View File

@ -56,8 +56,8 @@ const onClose = () => {};
const initProcess = () => {
let href = window.location.href;
let ipLocal = href.split('//')[1].split(':')[0];
processSocket = new WebSocket(`ws://${ipLocal}:9999/api/v1/files/ws`);
let ipLocal = href.split('//')[1].split('/')[0];
processSocket = new WebSocket(`ws://${ipLocal}/api/v1/files/ws`);
processSocket.onopen = onOpenProcess;
processSocket.onmessage = onMessage;
processSocket.onerror = onerror;

View File

@ -93,7 +93,7 @@ const initErrorTerm = (errorInfo: string) => {
const initTerm = () => {
let ifm = document.getElementById('terminal-' + terminalID.value) as HTMLInputElement | null;
let href = window.location.href;
let ipLocal = href.split('//')[1].split(':')[0];
let ipLocal = href.split('//')[1].split('/')[0];
term = new Terminal({
lineHeight: 1.2,
fontSize: 12,
@ -109,7 +109,7 @@ const initTerm = () => {
if (ifm) {
term.open(ifm);
terminalSocket = new WebSocket(
`ws://${ipLocal}:9999/api/v1/terminals?id=${wsID.value}&cols=${term.cols}&rows=${term.rows}`,
`ws://${ipLocal}/api/v1/terminals?id=${wsID.value}&cols=${term.cols}&rows=${term.rows}`,
);
terminalSocket.onopen = runRealTerminal;
terminalSocket.onmessage = onWSReceive;

View File

@ -166,7 +166,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import type { ElForm } from 'element-plus';
import { ElMessage } from 'element-plus';
@ -176,6 +176,8 @@ import { MenuStore } from '@/store/modules/menu';
import i18n from '@/lang';
import { Rules } from '@/global/form-rules';
let timer: NodeJS.Timer | null = null;
const globalStore = GlobalStore();
const menuStore = MenuStore();
@ -318,6 +320,11 @@ function checkPassword(rule: any, value: any, callback: any) {
onMounted(() => {
document.title = globalStore.themeConfig.panelName;
timer = setInterval(() => {
if (loginForm.captcha === '') {
loginVerify();
}
}, 1000 * 8);
checkStatus();
document.onkeydown = (e: any) => {
e = window.event || e;
@ -327,6 +334,11 @@ onMounted(() => {
}
};
});
onUnmounted(() => {
clearInterval(Number(timer));
timer = null;
});
</script>
<style scoped lang="scss">

View File

@ -31,6 +31,20 @@
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('setting.panelPort')" :rules="Rules.port" prop="serverPort">
<el-input clearable v-model.number="form.serverPort">
<template #append>
<el-button
@click="onSavePort(panelFormRef, 'ServerPort', form.serverPort)"
icon="Collection"
>
{{ $t('commons.button.save') }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item :label="$t('setting.language')" :rules="Rules.requiredSelect" prop="language">
<el-radio-group
style="width: 100%"
@ -84,9 +98,9 @@
<script lang="ts" setup>
import { ref, reactive, onMounted, computed } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import { ElMessage, ElForm, ElMessageBox } from 'element-plus';
import LayoutContent from '@/layout/layout-content.vue';
import { syncTime, getSettingInfo, updateSetting } from '@/api/modules/setting';
import { syncTime, getSettingInfo, updateSetting, updatePort } from '@/api/modules/setting';
import { Rules } from '@/global/form-rules';
import { GlobalStore } from '@/store';
import { useI18n } from 'vue-i18n';
@ -179,32 +193,34 @@ const onSave = async (formEl: FormInstance | undefined, key: string, val: any) =
});
};
// const onSavePort = async (formEl: FormInstance | undefined, key: string, val: any) => {
// if (!formEl) return;
// const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback);
// if (!result) {
// return;
// }
// ElMessageBox.confirm(i18n.t('setting.portChangeHelper'), i18n.t('setting.portChange'), {
// confirmButtonText: i18n.t('commons.button.confirm'),
// cancelButtonText: i18n.t('commons.button.cancel'),
// type: 'info',
// }).then(async () => {
// loading.value = true;
// let param = {
// serverPort: val,
// };
// await updatePort(param)
// .then(() => {
// loading.value = false;
// ElMessage.success(i18n.t('commons.msg.operationSuccess'));
// search();
// })
// .catch(() => {
// loading.value = false;
// });
// });
// };
const onSavePort = async (formEl: FormInstance | undefined, key: string, val: any) => {
if (!formEl) return;
const result = await formEl.validateField(key.replace(key[0], key[0].toLowerCase()), callback);
if (!result) {
return;
}
ElMessageBox.confirm(i18n.t('setting.portChangeHelper'), i18n.t('setting.portChange'), {
confirmButtonText: i18n.t('commons.button.confirm'),
cancelButtonText: i18n.t('commons.button.cancel'),
type: 'info',
}).then(async () => {
loading.value = true;
let param = {
serverPort: val,
};
await updatePort(param)
.then(() => {
loading.value = false;
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
let href = window.location.href;
let ip = href.split('//')[1].split(':')[0];
window.open(`${href.split('//')[0]}//${ip}:${val}/1panel/login`, '_self');
})
.catch(() => {
loading.value = false;
});
});
};
function countdown() {
count.value = TIME_COUNT.value;