mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
refactor: adjust login settings logic (#12916)
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
@@ -94,6 +95,10 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !checkSettingValueRange(req.Key, req.Value) {
|
||||
helper.ErrorWithDetail(c, http.StatusBadRequest, "ErrInvalidParams", buserr.WithName("ErrInvalidParams", req.Value))
|
||||
return
|
||||
}
|
||||
if req.Key == "PasskeyTrustedProxies" {
|
||||
value, err := normalizePasskeyTrustedProxies(req.Value)
|
||||
if err != nil {
|
||||
@@ -113,6 +118,25 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
func checkSettingValueRange(key, value string) bool {
|
||||
switch key {
|
||||
case "SessionTimeout":
|
||||
valueNum, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return valueNum >= 300 && valueNum <= 864000
|
||||
case "ExpirationDays":
|
||||
valueNum, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return valueNum >= 0 && valueNum <= 60
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Update system terminal setting
|
||||
// @Accept json
|
||||
|
||||
+12
-45
@@ -245,8 +245,6 @@ func GetCurrentUserInfo() (*dto.CurrentUserInfo, error) {
|
||||
if err := json.Unmarshal(arr, &info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info.SessionTimeout, _ = strconv.Atoi(settingMap["SessionTimeout"])
|
||||
info.ExpirationDays, _ = strconv.Atoi(settingMap["ExpirationDays"])
|
||||
info.MFAInterval, _ = strconv.Atoi(settingMap["MFAInterval"])
|
||||
info.ApiKeyValidityTime, _ = strconv.Atoi(settingMap["ApiKeyValidityTime"])
|
||||
info.Name = settingMap["UserName"]
|
||||
@@ -255,6 +253,13 @@ func GetCurrentUserInfo() (*dto.CurrentUserInfo, error) {
|
||||
info.NodeRoles = []dto.CurrentUserNodeRole{}
|
||||
return &info, nil
|
||||
}
|
||||
func LoadPasswordExpirationTime(_ *gin.Context) (string, error) {
|
||||
return repo.NewISettingRepo().GetValueByKey("ExpirationTime")
|
||||
}
|
||||
func SyncPasswordExpirationTime(expirationDays string) error {
|
||||
expiredDays, _ := strconv.Atoi(expirationDays)
|
||||
return repo.NewISettingRepo().Update("ExpirationTime", buildPasswordExpirationTime(expiredDays))
|
||||
}
|
||||
func UpdateCurrentUserInfo(c *gin.Context, req dto.CurrentUserUpdate) error {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
currentName, err := settingRepo.GetValueByKey("UserName")
|
||||
@@ -281,20 +286,6 @@ func UpdateCurrentUserInfo(c *gin.Context, req dto.CurrentUserUpdate) error {
|
||||
if err := settingRepo.Update("UserName", req.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("SessionTimeout", strconv.Itoa(req.SessionTimeout)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("ExpirationDays", strconv.Itoa(req.ExpirationDays)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
expirationTime := ""
|
||||
if req.ExpirationDays != 0 {
|
||||
expirationTime = time.Now().AddDate(0, 0, req.ExpirationDays).Format(constant.DateTimeLayout)
|
||||
}
|
||||
if err := settingRepo.Update("ExpirationTime", expirationTime); err != nil {
|
||||
return err
|
||||
}
|
||||
if shouldDeleteSession {
|
||||
deleteCurrentSession(c)
|
||||
}
|
||||
@@ -349,7 +340,7 @@ func HandlePasswordExpired(c *gin.Context, old, new string) error {
|
||||
return err
|
||||
}
|
||||
timeout, _ := strconv.Atoi(expiredSetting.Value)
|
||||
if err := settingRepo.Update("ExpirationTime", time.Now().AddDate(0, 0, timeout).Format(constant.DateTimeLayout)); err != nil {
|
||||
if err := settingRepo.Update("ExpirationTime", buildPasswordExpirationTime(timeout)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -357,35 +348,11 @@ func HandlePasswordExpired(c *gin.Context, old, new string) error {
|
||||
return buserr.New("ErrInitialPassword")
|
||||
}
|
||||
|
||||
func LoadSessionTimeout(sessionUser psession.SessionUser) (int, error) {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
sessionTimeout, err := settingRepo.GetValueByKey("SessionTimeout")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
func buildPasswordExpirationTime(expirationDays int) string {
|
||||
if expirationDays == 0 {
|
||||
return ""
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(sessionTimeout)
|
||||
return lifeTime, nil
|
||||
}
|
||||
func LoadExpired(sessionUser psession.SessionUser) (bool, time.Time, error) {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
expirationDays, err := settingRepo.GetValueByKey("ExpirationDays")
|
||||
if err != nil {
|
||||
return true, time.Time{}, err
|
||||
}
|
||||
expiredDays, _ := strconv.Atoi(expirationDays)
|
||||
if expiredDays == 0 {
|
||||
return false, time.Time{}, nil
|
||||
}
|
||||
|
||||
expirationTime, err := settingRepo.GetValueByKey("ExpirationTime")
|
||||
if err != nil {
|
||||
return true, time.Time{}, err
|
||||
}
|
||||
expiredTime, err := time.ParseInLocation(constant.DateTimeLayout, expirationTime, common.LoadExpiredLocation())
|
||||
if err != nil {
|
||||
return true, time.Time{}, err
|
||||
}
|
||||
return true, expiredTime, nil
|
||||
return time.Now().AddDate(0, 0, expirationDays).Format(constant.DateTimeLayout)
|
||||
}
|
||||
|
||||
func deleteCurrentSession(c *gin.Context) {
|
||||
|
||||
@@ -62,11 +62,8 @@ type ApiInterfaceConfig struct {
|
||||
|
||||
type CurrentUserInfo struct {
|
||||
Name string `json:"name"`
|
||||
SessionTimeout int `json:"sessionTimeout"`
|
||||
MFAStatus string `json:"mfaStatus"`
|
||||
MFAInterval int `json:"mfaInterval"`
|
||||
ExpirationDays int `json:"expirationDays"`
|
||||
ExpirationTime string `json:"expirationTime"`
|
||||
ComplexitySetting string `json:"complexitySetting"`
|
||||
|
||||
ApiInterfaceStatus string `json:"apiInterfaceStatus"`
|
||||
@@ -87,10 +84,7 @@ type CurrentUserNodeRole struct {
|
||||
}
|
||||
|
||||
type CurrentUserUpdate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
OldPassword string `json:"oldPassword"`
|
||||
SessionTimeout int `json:"sessionTimeout" validate:"required,min=300,max=864000"`
|
||||
ExpirationDays int `json:"expirationDays" validate:"min=0,max=60"`
|
||||
ExpirationTime string `json:"expirationTime"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
OldPassword string `json:"oldPassword"`
|
||||
}
|
||||
|
||||
+11
-11
@@ -9,16 +9,17 @@ type SettingInfo struct {
|
||||
DeveloperMode string `json:"developerMode"`
|
||||
UpgradeBackupCopies string `json:"upgradeBackupCopies"`
|
||||
|
||||
Port string `json:"port"`
|
||||
Ipv6 string `json:"ipv6"`
|
||||
BindAddress string `json:"bindAddress"`
|
||||
PanelName string `json:"panelName"`
|
||||
Edition string `json:"edition"`
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
Language string `json:"language"`
|
||||
DocSource string `json:"docSource"`
|
||||
IsOffline string `json:"isOffline"`
|
||||
SessionTimeout string `json:"sessionTimeout"`
|
||||
Port string `json:"port"`
|
||||
Ipv6 string `json:"ipv6"`
|
||||
BindAddress string `json:"bindAddress"`
|
||||
PanelName string `json:"panelName"`
|
||||
Edition string `json:"edition"`
|
||||
Theme string `json:"theme"`
|
||||
MenuTabs string `json:"menuTabs"`
|
||||
Language string `json:"language"`
|
||||
DocSource string `json:"docSource"`
|
||||
IsOffline string `json:"isOffline"`
|
||||
|
||||
ServerPort string `json:"serverPort"`
|
||||
SSL string `json:"ssl"`
|
||||
@@ -30,7 +31,6 @@ type SettingInfo struct {
|
||||
DashboardMemoVisible string `json:"dashboardMemoVisible"`
|
||||
DashboardSimpleNodeVisible string `json:"dashboardSimpleNodeVisible"`
|
||||
ExpirationDays string `json:"expirationDays"`
|
||||
ExpirationTime string `json:"expirationTime"`
|
||||
ComplexityVerification string `json:"complexityVerification"`
|
||||
|
||||
AppStoreVersion string `json:"appStoreVersion"`
|
||||
|
||||
+14
-31
@@ -169,11 +169,17 @@ func (u *SettingService) Update(c *gin.Context, key, value string) error {
|
||||
if oldVal.Value == value {
|
||||
return nil
|
||||
}
|
||||
sessionLifeTime := 0
|
||||
switch key {
|
||||
case "IsOffline":
|
||||
if !global.CONF.Base.IsEnterprise {
|
||||
return buserr.New("ErrNotSupportInEnterpriseEdition")
|
||||
}
|
||||
case "SessionTimeout":
|
||||
sessionLifeTime, err = strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "AppStoreLastModified":
|
||||
exist, _ := settingRepo.Get(repo.WithByKey("AppStoreLastModified"))
|
||||
if exist.ID == 0 {
|
||||
@@ -200,6 +206,14 @@ func (u *SettingService) Update(c *gin.Context, key, value string) error {
|
||||
if err := settingRepo.Update(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
if key == "ExpirationDays" {
|
||||
if err := xpack.AuthProvider.SyncPasswordExpirationTime(value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if key == "SessionTimeout" {
|
||||
global.SESSION.ApplyTimeout(sessionLifeTime)
|
||||
}
|
||||
|
||||
switch key {
|
||||
case "BindDomain":
|
||||
@@ -504,37 +518,6 @@ func (u *SettingService) LoadFromCert() (*dto.SSLInfo, error) {
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (u *SettingService) HandlePasswordExpired(c *gin.Context, old, new string) error {
|
||||
setting, err := settingRepo.Get(repo.WithByKey("Password"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
passwordFromDB, err := encrypt.StringDecrypt(setting.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if passwordFromDB == old {
|
||||
newPassword, err := encrypt.StringEncrypt(new)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := settingRepo.Update("Password", newPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
expiredSetting, err := settingRepo.Get(repo.WithByKey("ExpirationDays"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
timeout, _ := strconv.Atoi(expiredSetting.Value)
|
||||
if err := settingRepo.Update("ExpirationTime", time.Now().AddDate(0, 0, timeout).Format(constant.DateTimeLayout)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return buserr.New("ErrInitialPassword")
|
||||
}
|
||||
|
||||
func (u *SettingService) GetTerminalInfo() (*dto.TerminalInfo, error) {
|
||||
setting, err := settingRepo.List()
|
||||
if err != nil {
|
||||
|
||||
@@ -27460,7 +27460,8 @@ const docTemplate = `{
|
||||
"enum": [
|
||||
"SystemIP",
|
||||
"DockerSockPath",
|
||||
"FileRecycleBin"
|
||||
"FileRecycleBin",
|
||||
"FirewallPortWhiteList"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -29939,12 +29940,6 @@ const docTemplate = `{
|
||||
"complexitySetting": {
|
||||
"type": "string"
|
||||
},
|
||||
"expirationDays": {
|
||||
"type": "integer"
|
||||
},
|
||||
"expirationTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"ipWhiteList": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -29971,9 +29966,6 @@ const docTemplate = `{
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionTimeout": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -29997,14 +29989,6 @@ const docTemplate = `{
|
||||
},
|
||||
"dto.CurrentUserUpdate": {
|
||||
"properties": {
|
||||
"expirationDays": {
|
||||
"maximum": 60,
|
||||
"minimum": 0,
|
||||
"type": "integer"
|
||||
},
|
||||
"expirationTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -30013,16 +29997,10 @@ const docTemplate = `{
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionTimeout": {
|
||||
"maximum": 864000,
|
||||
"minimum": 300,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"sessionTimeout"
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -34284,6 +34262,9 @@ const docTemplate = `{
|
||||
},
|
||||
"dto.SearchLgLogWithPage": {
|
||||
"properties": {
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -34293,6 +34274,9 @@ const docTemplate = `{
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
@@ -34409,6 +34393,9 @@ const docTemplate = `{
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -34417,6 +34404,9 @@ const docTemplate = `{
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -34559,6 +34549,9 @@ const docTemplate = `{
|
||||
"fileRecycleBin": {
|
||||
"type": "string"
|
||||
},
|
||||
"firewallPortWhiteList": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanData": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -27456,7 +27456,8 @@
|
||||
"enum": [
|
||||
"SystemIP",
|
||||
"DockerSockPath",
|
||||
"FileRecycleBin"
|
||||
"FileRecycleBin",
|
||||
"FirewallPortWhiteList"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -29935,12 +29936,6 @@
|
||||
"complexitySetting": {
|
||||
"type": "string"
|
||||
},
|
||||
"expirationDays": {
|
||||
"type": "integer"
|
||||
},
|
||||
"expirationTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"ipWhiteList": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -29967,9 +29962,6 @@
|
||||
},
|
||||
"role": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionTimeout": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -29993,14 +29985,6 @@
|
||||
},
|
||||
"dto.CurrentUserUpdate": {
|
||||
"properties": {
|
||||
"expirationDays": {
|
||||
"maximum": 60,
|
||||
"minimum": 0,
|
||||
"type": "integer"
|
||||
},
|
||||
"expirationTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -30009,16 +29993,10 @@
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"sessionTimeout": {
|
||||
"maximum": 864000,
|
||||
"minimum": 300,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"sessionTimeout"
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
@@ -34280,6 +34258,9 @@
|
||||
},
|
||||
"dto.SearchLgLogWithPage": {
|
||||
"properties": {
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -34289,6 +34270,9 @@
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
@@ -34405,6 +34389,9 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"endTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"info": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -34413,6 +34400,9 @@
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"startTime": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -34555,6 +34545,9 @@
|
||||
"fileRecycleBin": {
|
||||
"type": "string"
|
||||
},
|
||||
"firewallPortWhiteList": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanData": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -3,9 +3,11 @@ package router
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
baseRepo "github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/cmd/server/res"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
@@ -75,11 +77,12 @@ func checkSession(c *gin.Context) bool {
|
||||
return false
|
||||
}
|
||||
c.Set(psessionUtils.GinContextSessionUserKey, psession)
|
||||
lifeTime, err := xpack.AuthProvider.LoadSessionTimeout(c, psession)
|
||||
sessionTimeout, err := baseRepo.NewISettingRepo().GetValueByKey("SessionTimeout")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get session timeout failed, err: %v", err)
|
||||
return false
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(sessionTimeout)
|
||||
if _, err := global.SESSION.RefreshIfNeeded(c, psession, global.CONF.Conn.SSL == constant.StatusEnable, lifeTime); err != nil {
|
||||
global.LOG.Warnf("proxy refresh session failed, path=%s, err=%v", c.Request.URL.Path, err)
|
||||
return false
|
||||
|
||||
@@ -23,10 +23,11 @@ const SuperAdminSessionUserID = "__super_admin__"
|
||||
const GinContextSessionUserKey = "session_user"
|
||||
|
||||
type sessionItem struct {
|
||||
CreatedAt time.Time
|
||||
CSRFToken string
|
||||
User SessionUser
|
||||
ExpiredAt time.Time
|
||||
CreatedAt time.Time
|
||||
LastActiveAt time.Time
|
||||
CSRFToken string
|
||||
User SessionUser
|
||||
ExpiredAt time.Time
|
||||
}
|
||||
|
||||
type PSession struct {
|
||||
@@ -92,8 +93,9 @@ func (p *PSession) set(c *gin.Context, user SessionUser, secure bool, ttlSeconds
|
||||
}
|
||||
}
|
||||
|
||||
expiredAt := time.Now().Add(time.Duration(ttlSeconds) * time.Second)
|
||||
createdAt := time.Now()
|
||||
now := time.Now()
|
||||
expiredAt := now.Add(time.Duration(ttlSeconds) * time.Second)
|
||||
createdAt := now
|
||||
csrfToken := ""
|
||||
|
||||
p.mu.Lock()
|
||||
@@ -111,10 +113,11 @@ func (p *PSession) set(c *gin.Context, user SessionUser, secure bool, ttlSeconds
|
||||
}
|
||||
}
|
||||
p.sessions[sessionID] = sessionItem{
|
||||
CreatedAt: createdAt,
|
||||
CSRFToken: csrfToken,
|
||||
User: user,
|
||||
ExpiredAt: expiredAt,
|
||||
CreatedAt: createdAt,
|
||||
LastActiveAt: now,
|
||||
CSRFToken: csrfToken,
|
||||
User: user,
|
||||
ExpiredAt: expiredAt,
|
||||
}
|
||||
p.evictOverflowLocked(sessionID)
|
||||
p.mu.Unlock()
|
||||
@@ -217,6 +220,27 @@ func (p *PSession) DeleteByID(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PSession) ApplyTimeout(ttlSeconds int) {
|
||||
now := time.Now()
|
||||
ttl := time.Duration(ttlSeconds) * time.Second
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
for sessionID, item := range p.sessions {
|
||||
lastActiveAt := item.LastActiveAt
|
||||
if lastActiveAt.IsZero() {
|
||||
lastActiveAt = item.CreatedAt
|
||||
}
|
||||
expiredAt := lastActiveAt.Add(ttl)
|
||||
if now.After(expiredAt) {
|
||||
delete(p.sessions, sessionID)
|
||||
continue
|
||||
}
|
||||
item.ExpiredAt = expiredAt
|
||||
p.sessions[sessionID] = item
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PSession) Clean() error {
|
||||
p.mu.Lock()
|
||||
p.sessions = make(map[string]sessionItem)
|
||||
|
||||
@@ -31,6 +31,8 @@ var baseSettingKeys = map[string]struct{}{
|
||||
"Theme": {},
|
||||
"MenuTabs": {},
|
||||
"Language": {},
|
||||
"SessionTimeout": {},
|
||||
"ExpirationDays": {},
|
||||
"DeveloperMode": {},
|
||||
"UpgradeBackupCopies": {},
|
||||
"SecurityEntrance": {},
|
||||
|
||||
@@ -2,13 +2,17 @@ package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
baseRepo "github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
psessionUtils "github.com/1Panel-dev/1Panel/core/init/session/psession"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/xpack"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -52,15 +56,27 @@ func PasswordExpired() gin.HandlerFunc {
|
||||
helper.BadAuth(c, "ErrNotLogin", err)
|
||||
return
|
||||
}
|
||||
needCheck, expiredTime, err := xpack.AuthProvider.LoadExpired(c, psession)
|
||||
settingRepo := baseRepo.NewISettingRepo()
|
||||
expirationDays, err := settingRepo.GetValueByKey("ExpirationDays")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPasswordExpired", err)
|
||||
return
|
||||
}
|
||||
if !needCheck {
|
||||
expiredDays, _ := strconv.Atoi(expirationDays)
|
||||
if expiredDays == 0 {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
expirationTime, err := xpack.AuthProvider.LoadPasswordExpirationTime(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPasswordExpired", err)
|
||||
return
|
||||
}
|
||||
expiredTime, err := time.ParseInLocation(constant.DateTimeLayout, expirationTime, common.LoadExpiredLocation())
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPasswordExpired", err)
|
||||
return
|
||||
}
|
||||
|
||||
if time.Now().After(expiredTime) {
|
||||
helper.ErrorWithDetail(c, 313, "ErrPasswordExpired", err)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
baseRepo "github.com/1Panel-dev/1Panel/core/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/core/buserr"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
psessionUtils "github.com/1Panel-dev/1Panel/core/init/session/psession"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/xpack"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -33,13 +35,14 @@ func SessionAuth() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
c.Set(psessionUtils.GinContextSessionUserKey, psession)
|
||||
lifeTime, err := xpack.AuthProvider.LoadSessionTimeout(c, psession)
|
||||
sessionTimeout, err := baseRepo.NewISettingRepo().GetValueByKey("SessionTimeout")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("get session timeout failed, err: %v", err)
|
||||
helper.InternalServer(c, err)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(sessionTimeout)
|
||||
|
||||
if _, err := global.SESSION.RefreshIfNeeded(c, psession, global.CONF.Conn.SSL == constant.StatusEnable, lifeTime); err != nil {
|
||||
errItem := err.Error()
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/auth"
|
||||
baseDto "github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/core/init/session/psession"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/mfa"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/xpack/providers"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -54,13 +51,6 @@ func (a *authHelper) ResetSuperAdminUser(name, password string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *authHelper) LoadSessionTimeout(_ *gin.Context, sessionUser psession.SessionUser) (int, error) {
|
||||
return auth.LoadSessionTimeout(sessionUser)
|
||||
}
|
||||
func (a *authHelper) LoadExpired(_ *gin.Context, sessionUser psession.SessionUser) (bool, time.Time, error) {
|
||||
return auth.LoadExpired(sessionUser)
|
||||
}
|
||||
|
||||
func (a *authHelper) CoreAPIAuthMiddleware() gin.HandlerFunc {
|
||||
return auth.APIAuthMiddleware(auth.LoadAPIAuthConfig, nil)
|
||||
}
|
||||
@@ -86,6 +76,12 @@ func (a *authHelper) UpdateApiConfig(c *gin.Context, req baseDto.ApiInterfaceCon
|
||||
func (a *authHelper) GetCurrentUserInfo(_ *gin.Context) (*baseDto.CurrentUserInfo, error) {
|
||||
return auth.GetCurrentUserInfo()
|
||||
}
|
||||
func (a *authHelper) LoadPasswordExpirationTime(c *gin.Context) (string, error) {
|
||||
return auth.LoadPasswordExpirationTime(c)
|
||||
}
|
||||
func (a *authHelper) SyncPasswordExpirationTime(expirationDays string) error {
|
||||
return auth.SyncPasswordExpirationTime(expirationDays)
|
||||
}
|
||||
func (a *authHelper) UpdateCurrentUserInfo(c *gin.Context, req baseDto.CurrentUserUpdate) error {
|
||||
return auth.UpdateCurrentUserInfo(c, req)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package providers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/core/init/session/psession"
|
||||
"github.com/1Panel-dev/1Panel/core/utils/mfa"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -15,9 +12,6 @@ type AuthProvider interface {
|
||||
|
||||
ResetSuperAdminUser(name, password string) error
|
||||
|
||||
LoadSessionTimeout(c *gin.Context, sessionUser psession.SessionUser) (int, error)
|
||||
LoadExpired(c *gin.Context, sessionUser psession.SessionUser) (bool, time.Time, error)
|
||||
|
||||
LoadMFA(c *gin.Context, req dto.MfaRequest) (mfa.Otp, error)
|
||||
MFABind(c *gin.Context, req dto.MfaCredential) error
|
||||
MFAClose(c *gin.Context) error
|
||||
@@ -35,6 +29,8 @@ type AuthProvider interface {
|
||||
ClearPasskeys() error
|
||||
|
||||
GetCurrentUserInfo(c *gin.Context) (*dto.CurrentUserInfo, error)
|
||||
LoadPasswordExpirationTime(c *gin.Context) (string, error)
|
||||
SyncPasswordExpirationTime(expirationDays string) error
|
||||
UpdateCurrentUserInfo(c *gin.Context, req dto.CurrentUserUpdate) error
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
|
||||
|
||||
@@ -48,9 +48,6 @@ export namespace Login {
|
||||
export interface AuthInfo {
|
||||
id: number;
|
||||
name: string;
|
||||
sessionTimeout: number;
|
||||
expirationDays: number;
|
||||
expirationTime: string;
|
||||
mfaStatus: string;
|
||||
mfaInterval: number;
|
||||
role: string;
|
||||
@@ -68,9 +65,6 @@ export namespace Login {
|
||||
name: string;
|
||||
password: string;
|
||||
oldPassword: string;
|
||||
sessionTimeout: number;
|
||||
expirationDays: number;
|
||||
expirationTime: string;
|
||||
}
|
||||
export interface MFARequest {
|
||||
title: string;
|
||||
|
||||
@@ -34,6 +34,7 @@ export namespace Setting {
|
||||
developerMode: string;
|
||||
|
||||
sessionTimeout: number;
|
||||
expirationDays: number;
|
||||
|
||||
panelName: string;
|
||||
edition: string;
|
||||
|
||||
@@ -40,29 +40,6 @@
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.days')" prop="expirationDays">
|
||||
<el-input
|
||||
clearable
|
||||
v-model.number="form.expirationDays"
|
||||
name="profile-expiration-days"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<div>
|
||||
<span class="input-help" v-if="form.expirationDays !== 0">
|
||||
{{ $t('setting.timeoutHelper', [loadTimeOut()]) }}
|
||||
</span>
|
||||
<span class="input-help" v-else>
|
||||
{{ $t('setting.noneSetting') }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="input-help">{{ $t('setting.expirationHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.sessionTimeout')" prop="sessionTimeout">
|
||||
<el-input v-model.number="form.sessionTimeout" name="profile-session-timeout" autocomplete="off" />
|
||||
<span class="input-help">
|
||||
{{ $t('setting.sessionTimeoutHelper', [form.sessionTimeout]) }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-form label-position="top" :model="form" class="setting-section">
|
||||
@@ -449,11 +426,8 @@ const form = reactive({
|
||||
name: '',
|
||||
password: '',
|
||||
oldPassword: '',
|
||||
sessionTimeout: 0,
|
||||
mfaStatus: 'Disable',
|
||||
mfaInterval: 30,
|
||||
expirationDays: 0,
|
||||
expirationTime: '',
|
||||
apiInterfaceStatus: 'Disable',
|
||||
apiKey: '',
|
||||
ipWhiteList: '',
|
||||
@@ -514,8 +488,6 @@ const userRules = reactive({
|
||||
name: [Rules.requiredInput, Rules.noSpace],
|
||||
oldPassword: [Rules.requiredInput],
|
||||
password: [{ validator: validatePassword, trigger: 'blur' }],
|
||||
sessionTimeout: [Rules.integerNumber, checkNumberRange(300, 864000)],
|
||||
expirationDays: [Rules.integerNumberWith0, checkNumberRange(0, 60)],
|
||||
});
|
||||
const mfaRules = reactive({
|
||||
code: [Rules.requiredInput],
|
||||
@@ -529,7 +501,7 @@ const apiRules = reactive({
|
||||
});
|
||||
|
||||
const getUserFormFields = () => {
|
||||
const fields = ['name', 'password', 'sessionTimeout', 'expirationDays'];
|
||||
const fields = ['name', 'password'];
|
||||
if (form.password) {
|
||||
fields.push('oldPassword');
|
||||
}
|
||||
@@ -559,15 +531,11 @@ const syncCurrentUser = (currentUser: Login.AuthInfo) => {
|
||||
form.name = currentUser.name;
|
||||
form.password = '';
|
||||
form.oldPassword = '';
|
||||
form.sessionTimeout = currentUser.sessionTimeout;
|
||||
form.expirationTime = currentUser.expirationTime;
|
||||
form.expirationDays = currentUser.expirationDays;
|
||||
form.mfaStatus = currentUser.mfaStatus || 'Disable';
|
||||
form.mfaInterval = currentUser.mfaInterval;
|
||||
savedMfaStatus.value = form.mfaStatus;
|
||||
mfaDialogOpen.value = false;
|
||||
apiDialogOpen.value = false;
|
||||
form.expirationDays = form.expirationDays ? form.expirationDays : 0;
|
||||
syncApiConfig(currentUser);
|
||||
};
|
||||
|
||||
@@ -862,9 +830,6 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
name: form.name,
|
||||
password: form.password,
|
||||
oldPassword: form.oldPassword,
|
||||
sessionTimeout: form.sessionTimeout,
|
||||
expirationDays: form.expirationDays,
|
||||
expirationTime: form.expirationTime,
|
||||
};
|
||||
loading.value = true;
|
||||
await updateUserInfo(param)
|
||||
@@ -933,26 +898,6 @@ const onSaveApi = async (formEl: FormInstance | undefined) => {
|
||||
});
|
||||
};
|
||||
|
||||
function loadTimeOut() {
|
||||
if (!form.expirationTime) {
|
||||
if (form.expirationDays) {
|
||||
return form.expirationDays;
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
if (form.expirationDays === 0) {
|
||||
form.expirationTime = '-';
|
||||
return '-';
|
||||
}
|
||||
let stayGap = new Date(form.expirationTime).getTime() - new Date().getTime();
|
||||
if (stayGap < 0) {
|
||||
form.expirationTime = '-';
|
||||
return '-';
|
||||
}
|
||||
return Math.floor(stayGap / (3600 * 1000 * 24));
|
||||
}
|
||||
|
||||
const handleMFA = async () => {
|
||||
if (!form.mfaStatus) {
|
||||
return;
|
||||
|
||||
@@ -103,6 +103,19 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.sessionTimeout')" prop="sessionTimeout">
|
||||
<el-input disabled v-model.number="form.sessionTimeout">
|
||||
<template #append>
|
||||
<el-button @click="onChangeTimeout" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="input-help">
|
||||
{{ $t('setting.sessionTimeoutHelper', [form.sessionTimeout]) }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('setting.systemIP')" prop="systemIP">
|
||||
<el-input disabled v-if="form.systemIP" v-model="form.systemIP">
|
||||
<template #append>
|
||||
@@ -176,6 +189,7 @@
|
||||
<PanelName ref="panelNameRef" @search="search()" />
|
||||
<SystemIP ref="systemIPRef" @search="search()" />
|
||||
<Proxy ref="proxyRef" @search="search()" />
|
||||
<Timeout ref="timeoutRef" @search="search()" />
|
||||
<HideMenu ref="hideMenuRef" @search="search()" />
|
||||
<ThemeColor ref="themeColorRef" />
|
||||
<Watermark ref="watermarkRef" @search="search()" />
|
||||
@@ -193,6 +207,7 @@ import { MsgSuccess } from '@/utils/message';
|
||||
import ThemeColor from '@/views/setting/panel/theme-color/index.vue';
|
||||
import Watermark from '@/views/setting/panel/watermark/index.vue';
|
||||
import Edition from '@/views/setting/panel/edition/index.vue';
|
||||
import Timeout from '@/views/setting/panel/timeout/index.vue';
|
||||
import PanelName from '@/views/setting/panel/name/index.vue';
|
||||
import SystemIP from '@/views/setting/panel/systemip/index.vue';
|
||||
import Proxy from '@/views/setting/panel/proxy/index.vue';
|
||||
@@ -236,6 +251,7 @@ const form = reactive({
|
||||
themeColor: {} as ThemeColor,
|
||||
menuTabs: '',
|
||||
language: '',
|
||||
sessionTimeout: 0,
|
||||
docSource: 'withByRegion',
|
||||
edition: '',
|
||||
isOffline: 'Disable',
|
||||
@@ -259,6 +275,7 @@ const show = ref();
|
||||
const panelNameRef = ref();
|
||||
const systemIPRef = ref();
|
||||
const proxyRef = ref();
|
||||
const timeoutRef = ref();
|
||||
const hideMenuRef = ref();
|
||||
const watermarkRef = ref();
|
||||
const themeColorRef = ref();
|
||||
@@ -291,6 +308,7 @@ const search = async () => {
|
||||
form.menuTabs = res.data.menuTabs;
|
||||
form.panelName = res.data.panelName;
|
||||
form.language = res.data.language;
|
||||
form.sessionTimeout = Number(res.data.sessionTimeout || 0);
|
||||
form.docSource = res.data.docSource || 'withByRegion';
|
||||
form.edition = res.data.edition;
|
||||
form.isOffline = res.data.isOffline || 'Disable';
|
||||
@@ -335,6 +353,9 @@ const search = async () => {
|
||||
const onChangeTitle = () => {
|
||||
panelNameRef.value.acceptParams({ panelName: form.panelName });
|
||||
};
|
||||
const onChangeTimeout = () => {
|
||||
timeoutRef.value.acceptParams({ sessionTimeout: form.sessionTimeout });
|
||||
};
|
||||
const onChangeSystemIP = () => {
|
||||
systemIPRef.value.acceptParams({ systemIP: form.systemIP });
|
||||
};
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<DrawerPro v-model="drawerVisible" :header="$t('setting.sessionTimeout')" @close="handleClose" size="small">
|
||||
<el-form ref="formRef" label-position="top" :rules="rules" :model="form" @submit.prevent v-loading="loading">
|
||||
<el-form-item :label="$t('setting.sessionTimeout')" prop="sessionTimeout">
|
||||
<el-input clearable v-model.number="form.sessionTimeout" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button :disabled="loading" type="primary" @click="onSaveTimeout(formRef)">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
interface DialogProps {
|
||||
sessionTimeout: number;
|
||||
}
|
||||
const drawerVisible = ref();
|
||||
const loading = ref();
|
||||
|
||||
const form = reactive({
|
||||
sessionTimeout: 86400,
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
sessionTimeout: [Rules.integerNumber, checkNumberRange(300, 864000)],
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
form.sessionTimeout = params.sessionTimeout;
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
|
||||
const onSaveTimeout = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
loading.value = true;
|
||||
await updateSetting({ key: 'SessionTimeout', value: form.sessionTimeout + '' })
|
||||
.then(async () => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
loading.value = false;
|
||||
drawerVisible.value = false;
|
||||
emit('search');
|
||||
return;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
drawerVisible.value = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<DrawerPro v-model="drawerVisible" :header="$t('setting.expirationTime')" @close="handleClose" size="small">
|
||||
<el-form ref="timeoutFormRef" @submit.prevent label-position="top" v-loading="loading" :model="form">
|
||||
<el-form-item
|
||||
:label="$t('setting.days')"
|
||||
prop="days"
|
||||
:rules="[Rules.integerNumberWith0, checkNumberRange(0, 60)]"
|
||||
>
|
||||
<el-input clearable v-model.number="form.days" />
|
||||
<span class="input-help">{{ $t('setting.expirationHelper') }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button :disabled="loading" type="primary" @click="submitTimeout(timeoutFormRef)">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</DrawerPro>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { updateSetting } from '@/api/modules/setting';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
interface DialogProps {
|
||||
expirationDays: number;
|
||||
}
|
||||
const drawerVisible = ref();
|
||||
const loading = ref();
|
||||
|
||||
const timeoutFormRef = ref();
|
||||
const form = reactive({
|
||||
days: 0,
|
||||
});
|
||||
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
form.days = params.expirationDays;
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
|
||||
const submitTimeout = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
loading.value = true;
|
||||
await updateSetting({ key: 'ExpirationDays', value: form.days + '' })
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
emit('search');
|
||||
drawerVisible.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
drawerVisible.value = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
@@ -123,6 +123,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.expirationTime')" prop="expirationDays">
|
||||
<el-input disabled v-model="form.expirationDays">
|
||||
<template #append>
|
||||
<el-button @click="onChangeExpirationDays" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="input-help">
|
||||
{{
|
||||
form.expirationDays === 0
|
||||
? $t('setting.noneSetting')
|
||||
: $t('setting.expirationHelper')
|
||||
}}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.complexity')" prop="complexityVerification">
|
||||
<el-switch
|
||||
@change="onSaveComplexity"
|
||||
@@ -146,6 +162,7 @@
|
||||
<EntranceSetting ref="entranceRef" @search="search" />
|
||||
<DomainSetting ref="domainRef" @search="search" />
|
||||
<AllowIPsSetting ref="allowIPsRef" @search="search" />
|
||||
<ExpirationSetting ref="expirationRef" @search="search" />
|
||||
<ResponseSetting ref="responseRef" @search="search()" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -157,6 +174,7 @@ import PortSetting from '@/views/setting/safe/port/index.vue';
|
||||
import BindSetting from '@/views/setting/safe/bind/index.vue';
|
||||
import ResponseSetting from '@/views/setting/safe/response/index.vue';
|
||||
import SSLSetting from '@/views/setting/safe/ssl/index.vue';
|
||||
import ExpirationSetting from '@/views/setting/safe/expiration/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';
|
||||
@@ -172,6 +190,7 @@ const loading = ref(false);
|
||||
const entranceRef = ref();
|
||||
const portRef = ref();
|
||||
const bindRef = ref();
|
||||
const expirationRef = ref();
|
||||
const responseRef = ref();
|
||||
|
||||
const sslRef = ref();
|
||||
@@ -188,6 +207,7 @@ const form = reactive({
|
||||
sslItem: 'Disable',
|
||||
sslType: 'self',
|
||||
securityEntrance: '',
|
||||
expirationDays: 0,
|
||||
complexityVerification: 'Disable',
|
||||
allowIPs: '',
|
||||
bindDomain: '',
|
||||
@@ -210,6 +230,7 @@ const search = async () => {
|
||||
loadInfo();
|
||||
}
|
||||
form.securityEntrance = res.data.securityEntrance;
|
||||
form.expirationDays = Number(res.data.expirationDays);
|
||||
form.complexityVerification = res.data.complexityVerification;
|
||||
form.allowIPs = res.data.allowIPs.replaceAll(',', '\n');
|
||||
form.bindDomain = res.data.bindDomain;
|
||||
@@ -256,6 +277,9 @@ const onChangeBindDomain = () => {
|
||||
const onChangeAllowIPs = () => {
|
||||
allowIPsRef.value.acceptParams({ allowIPs: form.allowIPs });
|
||||
};
|
||||
const onChangeExpirationDays = async () => {
|
||||
expirationRef.value.acceptParams({ expirationDays: form.expirationDays });
|
||||
};
|
||||
const handleSSL = async () => {
|
||||
if (form.sslItem !== 'Disable') {
|
||||
let params = {
|
||||
|
||||
Reference in New Issue
Block a user