1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00
1Panel/cmd/server/cmd/update.go

279 lines
8.4 KiB
Go

package cmd
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"unicode"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/i18n"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
"github.com/1Panel-dev/1Panel/backend/utils/firewall"
fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client"
"github.com/spf13/cobra"
"golang.org/x/term"
)
func init() {
updateCmd.SetHelpFunc(func(c *cobra.Command, s []string) {
i18n.UseI18nForCmd(language)
loadUpdateHelper()
})
RootCmd.AddCommand(updateCmd)
updateCmd.AddCommand(updateUserName)
updateCmd.AddCommand(updatePassword)
updateCmd.AddCommand(updatePort)
}
var updateCmd = &cobra.Command{
Use: "update",
RunE: func(cmd *cobra.Command, args []string) error {
i18n.UseI18nForCmd(language)
loadUpdateHelper()
return nil
},
}
var updateUserName = &cobra.Command{
Use: "username",
Short: i18n.GetMsgByKeyForCmd("UpdateUser"),
RunE: func(cmd *cobra.Command, args []string) error {
i18n.UseI18nForCmd(language)
if !isRoot() {
fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update username"}))
return nil
}
username()
return nil
},
}
var updatePassword = &cobra.Command{
Use: "password",
Short: i18n.GetMsgByKeyForCmd("UpdatePassword"),
RunE: func(cmd *cobra.Command, args []string) error {
i18n.UseI18nForCmd(language)
if !isRoot() {
fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update password"}))
return nil
}
password()
return nil
},
}
var updatePort = &cobra.Command{
Use: "port",
Short: i18n.GetMsgByKeyForCmd("UpdatePort"),
RunE: func(cmd *cobra.Command, args []string) error {
i18n.UseI18nForCmd(language)
if !isRoot() {
fmt.Println(i18n.GetMsgWithMapForCmd("SudoHelper", map[string]interface{}{"cmd": "sudo 1pctl update port"}))
return nil
}
port()
return nil
},
}
func username() {
reader := bufio.NewReader(os.Stdin)
fmt.Print(i18n.GetMsgByKeyForCmd("UpdateUser") + ": ")
newUsername, _ := reader.ReadString('\n')
newUsername = strings.Trim(newUsername, "\n")
if len(newUsername) == 0 {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserNull"))
return
}
if strings.Contains(newUsername, " ") {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserBlank"))
return
}
result, err := regexp.MatchString("^[a-zA-Z0-9_\u4e00-\u9fa5]{3,30}$", newUsername)
if !result || err != nil {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdateUserFormat"))
return
}
db, err := loadDBConn()
if err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()}))
return
}
if err := setSettingByKey(db, "UserName", newUsername); err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserErr", map[string]interface{}{"err": err.Error()}))
return
}
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful"))
fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserResult", map[string]interface{}{"name": newUsername}))
}
func password() {
fmt.Print(i18n.GetMsgByKeyForCmd("UpdatePassword") + ": ")
bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
fmt.Println("\n" + i18n.GetMsgWithMapForCmd("UpdatePasswordRead", map[string]interface{}{"err": err.Error()}))
return
}
newPassword := string(bytePassword)
newPassword = strings.Trim(newPassword, "\n")
if len(newPassword) == 0 {
fmt.Println("\n", i18n.GetMsgByKeyForCmd("UpdatePasswordNull"))
return
}
if strings.Contains(newPassword, " ") {
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateUPasswordBlank"))
return
}
db, err := loadDBConn()
if err != nil {
fmt.Println("\n" + i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()}))
return
}
complexSetting := getSettingByKey(db, "ComplexityVerification")
if complexSetting == "enable" {
if isValidPassword("newPassword") {
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdatePasswordFormat"))
return
}
}
if len(newPassword) < 6 {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePasswordLen"))
return
}
fmt.Print("\n" + i18n.GetMsgByKeyForCmd("UpdatePasswordRe"))
byteConfirmPassword, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
fmt.Println("\n" + i18n.GetMsgWithMapForCmd("UpdatePasswordRead", map[string]interface{}{"err": err.Error()}))
return
}
confirmPassword := string(byteConfirmPassword)
confirmPassword = strings.Trim(confirmPassword, "\n")
if newPassword != confirmPassword {
fmt.Println("\n", i18n.GetMsgByKeyForCmd("UpdatePasswordSame"))
return
}
p := ""
encryptSetting := getSettingByKey(db, "EncryptKey")
if len(encryptSetting) == 16 {
global.CONF.System.EncryptKey = encryptSetting
p, _ = encrypt.StringEncrypt(newPassword)
} else {
p = newPassword
}
if err := setSettingByKey(db, "Password", p); err != nil {
fmt.Println("\n", i18n.GetMsgWithMapForCmd("UpdatePortErr", map[string]interface{}{"err": err.Error()}))
return
}
username := getSettingByKey(db, "UserName")
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful"))
fmt.Println(i18n.GetMsgWithMapForCmd("UpdateUserResult", map[string]interface{}{"name": username}))
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePasswordResult", map[string]interface{}{"name": string(newPassword)}))
}
func port() {
reader := bufio.NewReader(os.Stdin)
fmt.Print(i18n.GetMsgByKeyForCmd("UpdatePort") + ": ")
newPortStr, _ := reader.ReadString('\n')
newPortStr = strings.Trim(newPortStr, "\n")
newPort, err := strconv.Atoi(strings.TrimSpace(newPortStr))
if err != nil || newPort < 1 || newPort > 65535 {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePortFormat"))
return
}
if common.ScanPort(newPort) {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdatePortUsed"))
return
}
db, err := loadDBConn()
if err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("DBConnErr", map[string]interface{}{"err": err.Error()}))
return
}
oldPortStr := getSettingByKey(db, "ServerPort")
if err := setSettingByKey(db, "ServerPort", newPortStr); err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortErr", map[string]interface{}{"err": err.Error()}))
return
}
fmt.Println("\n" + i18n.GetMsgByKeyForCmd("UpdateSuccessful"))
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortResult", map[string]interface{}{"name": newPortStr}))
if client, err := firewall.NewFirewallClient(); err == nil {
if err := client.Port(fireClient.FireInfo{Port: newPortStr, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortFirewallAdd", map[string]interface{}{"name": newPortStr, "err": err.Error()}))
}
if err := client.Port(fireClient.FireInfo{Port: oldPortStr, Protocol: "tcp", Strategy: "accept"}, "remove"); err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortFirewallDel", map[string]interface{}{"err": err.Error()}))
}
if err := client.Reload(); err != nil {
fmt.Println(i18n.GetMsgWithMapForCmd("UpdatePortFirewallReload", map[string]interface{}{"err": err.Error()}))
}
}
std, err := cmd.Exec("1pctl restart")
if err != nil {
fmt.Println(std)
}
}
func isValidPassword(password string) bool {
numCount := 0
alphaCount := 0
specialCount := 0
for _, char := range password {
switch {
case unicode.IsDigit(char):
numCount++
case unicode.IsLetter(char):
alphaCount++
case isSpecialChar(char):
specialCount++
}
}
if len(password) < 8 && len(password) > 30 {
return false
}
if (numCount == 0 && alphaCount == 0) || (alphaCount == 0 && specialCount == 0) || (numCount == 0 && specialCount == 0) {
return false
}
return true
}
func isSpecialChar(char rune) bool {
specialChars := "!@#$%*_,.?"
return unicode.IsPunct(char) && contains(specialChars, char)
}
func contains(specialChars string, char rune) bool {
for _, c := range specialChars {
if c == char {
return true
}
}
return false
}
func loadUpdateHelper() {
fmt.Println(i18n.GetMsgByKeyForCmd("UpdateCommands"))
fmt.Println("\nUsage:\n 1panel update [command]\n\nAvailable Commands:")
fmt.Println("\n password " + i18n.GetMsgByKeyForCmd("UpdatePassword"))
fmt.Println(" port " + i18n.GetMsgByKeyForCmd("UpdatePort"))
fmt.Println(" username " + i18n.GetMsgByKeyForCmd("UpdateUser"))
fmt.Println("\nFlags:\n -h, --help help for update")
fmt.Println("\nUse \"1panel update [command] --help\" for more information about a command.")
}