mirror of https://github.com/1Panel-dev/1Panel
feat: 配置修改后重启,适配 SELinux 策略
parent
efd545882f
commit
7452cc19e0
|
@ -50,6 +50,33 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) {
|
|||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Update host ssh setting by file
|
||||
// @Description 上传文件更新 SSH 配置
|
||||
// @Accept json
|
||||
// @Param request body dto.SSHConf true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/conffile/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
|
||||
func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
|
||||
var req dto.SSHConf
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := sshService.UpdateByFile(req.File); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Generate host ssh secret
|
||||
// @Description 生成 ssh 密钥
|
||||
|
|
|
@ -20,6 +20,9 @@ type GenerateLoad struct {
|
|||
EncryptionMode string `json:"encryptionMode" validate:"required,oneof=rsa ed25519 ecdsa dsa"`
|
||||
}
|
||||
|
||||
type SSHConf struct {
|
||||
File string `json:"file"`
|
||||
}
|
||||
type SearchSSHLog struct {
|
||||
PageInfo
|
||||
Info string `json:"info"`
|
||||
|
@ -33,7 +36,8 @@ type SSHLog struct {
|
|||
}
|
||||
type SSHHistory struct {
|
||||
Date time.Time `json:"date"`
|
||||
Belong string `json:"belong"`
|
||||
DateStr string `json:"dateStr"`
|
||||
IsLocal bool `json:"isLocal"`
|
||||
User string `json:"user"`
|
||||
AuthMode string `json:"authMode"`
|
||||
Address string `json:"address"`
|
||||
|
|
|
@ -2,6 +2,7 @@ package service
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
|
@ -13,6 +14,7 @@ import (
|
|||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"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,6 +24,7 @@ type SSHService struct{}
|
|||
|
||||
type ISSHService interface {
|
||||
GetSSHInfo() (*dto.SSHInfo, error)
|
||||
UpdateByFile(value string) error
|
||||
Update(key, value string) error
|
||||
GenerateSSH(req dto.GenerateSSH) error
|
||||
LoadSSHSecret(mode string) (string, error)
|
||||
|
@ -87,6 +90,36 @@ func (u *SSHService) Update(key, value string) error {
|
|||
if _, err = file.WriteString(strings.Join(newFiles, "\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
sudo := ""
|
||||
hasSudo := cmd.HasNoPasswordSudo()
|
||||
if hasSudo {
|
||||
sudo = "sudo"
|
||||
}
|
||||
if key == "Port" {
|
||||
stdout, _ := cmd.Exec("getenforce")
|
||||
if stdout == "Enforcing\n" {
|
||||
_, _ = cmd.Execf("%s semanage port -a -t ssh_port_t -p tcp %s", sudo, value)
|
||||
}
|
||||
}
|
||||
_, _ = cmd.Execf("%s systemctl restart sshd", sudo)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SSHService) UpdateByFile(value string) error {
|
||||
file, err := os.OpenFile(sshPath, os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err = file.WriteString(value); err != nil {
|
||||
return err
|
||||
}
|
||||
sudo := ""
|
||||
hasSudo := cmd.HasNoPasswordSudo()
|
||||
if hasSudo {
|
||||
sudo = "sudo"
|
||||
}
|
||||
_, _ = cmd.Execf("%s systemctl restart sshd", sudo)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -198,6 +231,15 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
|
|||
}
|
||||
data.SuccessfulCount = data.TotalCount - data.FailedCount
|
||||
|
||||
timeNow := time.Now()
|
||||
nyc, _ := time.LoadLocation(common.LoadTimeZone())
|
||||
for i := 0; i < len(data.Logs); i++ {
|
||||
data.Logs[i].IsLocal = isPrivateIP(net.ParseIP(data.Logs[i].Address))
|
||||
data.Logs[i].Date, _ = time.ParseInLocation("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s", timeNow.Year(), data.Logs[i].DateStr), nyc)
|
||||
if data.Logs[i].Date.After(timeNow) {
|
||||
data.Logs[i].Date = data.Logs[i].Date.AddDate(-1, 0, 0)
|
||||
}
|
||||
}
|
||||
sort.Slice(data.Logs, func(i, j int) bool {
|
||||
return data.Logs[i].Date.After(data.Logs[j].Date)
|
||||
})
|
||||
|
@ -249,27 +291,22 @@ func updateSSHConf(oldFiles []string, param string, value interface{}) []string
|
|||
|
||||
func loadSuccessDatas(command string) []dto.SSHHistory {
|
||||
var datas []dto.SSHHistory
|
||||
timeNow := time.Now()
|
||||
stdout2, err := cmd.Exec(command)
|
||||
if err == nil {
|
||||
lines := strings.Split(string(stdout2), "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) != 14 {
|
||||
if len(parts) < 14 {
|
||||
continue
|
||||
}
|
||||
historyItem := dto.SSHHistory{
|
||||
Belong: parts[3],
|
||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||
AuthMode: parts[6],
|
||||
User: parts[8],
|
||||
Address: parts[10],
|
||||
Port: parts[12],
|
||||
Status: constant.StatusSuccess,
|
||||
}
|
||||
historyItem.Date, _ = time.Parse("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s %s %s", timeNow.Year(), parts[0], parts[1], parts[2]))
|
||||
if historyItem.Date.After(timeNow) {
|
||||
historyItem.Date = historyItem.Date.AddDate(-1, 0, 0)
|
||||
}
|
||||
datas = append(datas, historyItem)
|
||||
}
|
||||
}
|
||||
|
@ -278,29 +315,24 @@ func loadSuccessDatas(command string) []dto.SSHHistory {
|
|||
|
||||
func loadFailedAuthDatas(command string) []dto.SSHHistory {
|
||||
var datas []dto.SSHHistory
|
||||
timeNow := time.Now()
|
||||
stdout2, err := cmd.Exec(command)
|
||||
if err == nil {
|
||||
lines := strings.Split(string(stdout2), "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) != 15 {
|
||||
if len(parts) < 14 {
|
||||
continue
|
||||
}
|
||||
historyItem := dto.SSHHistory{
|
||||
Belong: parts[3],
|
||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||
AuthMode: parts[8],
|
||||
User: parts[10],
|
||||
Address: parts[11],
|
||||
Port: parts[13],
|
||||
Status: constant.StatusFailed,
|
||||
}
|
||||
historyItem.Date, _ = time.Parse("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s %s %s", timeNow.Year(), parts[0], parts[1], parts[2]))
|
||||
if historyItem.Date.After(timeNow) {
|
||||
historyItem.Date = historyItem.Date.AddDate(-1, 0, 0)
|
||||
}
|
||||
if strings.Contains(line, ": ") {
|
||||
historyItem.Message = strings.Split(line, ": ")[0]
|
||||
historyItem.Message = strings.Split(line, ": ")[1]
|
||||
}
|
||||
datas = append(datas, historyItem)
|
||||
}
|
||||
|
@ -310,29 +342,24 @@ func loadFailedAuthDatas(command string) []dto.SSHHistory {
|
|||
|
||||
func loadFailedSecureDatas(command string) []dto.SSHHistory {
|
||||
var datas []dto.SSHHistory
|
||||
timeNow := time.Now()
|
||||
stdout2, err := cmd.Exec(command)
|
||||
if err == nil {
|
||||
lines := strings.Split(string(stdout2), "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) != 14 {
|
||||
if len(parts) < 14 {
|
||||
continue
|
||||
}
|
||||
historyItem := dto.SSHHistory{
|
||||
Belong: parts[3],
|
||||
DateStr: fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2]),
|
||||
AuthMode: parts[6],
|
||||
User: parts[8],
|
||||
Address: parts[10],
|
||||
Port: parts[12],
|
||||
Status: constant.StatusFailed,
|
||||
}
|
||||
historyItem.Date, _ = time.Parse("2006 Jan 2 15:04:05", fmt.Sprintf("%d %s %s %s", timeNow.Year(), parts[0], parts[1], parts[2]))
|
||||
if historyItem.Date.After(timeNow) {
|
||||
historyItem.Date = historyItem.Date.AddDate(-1, 0, 0)
|
||||
}
|
||||
if strings.Contains(line, ": ") {
|
||||
historyItem.Message = strings.Split(line, ": ")[0]
|
||||
historyItem.Message = strings.Split(line, ": ")[1]
|
||||
}
|
||||
datas = append(datas, historyItem)
|
||||
}
|
||||
|
@ -346,3 +373,16 @@ func handleGunzip(path string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func isPrivateIP(ip net.IP) bool {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
switch true {
|
||||
case ip4[0] == 10:
|
||||
return true
|
||||
case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
|
||||
return true
|
||||
case ip4[0] == 192 && ip4[1] == 168:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
)
|
||||
|
||||
func TestCa(t *testing.T) {
|
||||
var (
|
||||
fileList []string
|
||||
datas []history
|
||||
successfulCount int
|
||||
failedCount int
|
||||
)
|
||||
baseDir := "/Users/slooop/Downloads"
|
||||
if err := filepath.Walk(baseDir, func(pathItem string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && strings.HasPrefix(info.Name(), "secure") || strings.HasPrefix(info.Name(), "auth") {
|
||||
fileList = append(fileList, strings.ReplaceAll(pathItem, ".gz", ""))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
for i := 0; i < len(fileList); i++ {
|
||||
if strings.HasPrefix(path.Base(fileList[i]), "secure") {
|
||||
dataItem := loadDatas2(fmt.Sprintf("cat %s | grep -a 'Failed password for' | grep -v 'invalid'", fileList[i]), 14, constant.StatusFailed)
|
||||
failedCount += len(dataItem)
|
||||
datas = append(datas, dataItem...)
|
||||
}
|
||||
if strings.HasPrefix(path.Base(fileList[i]), "auth.log") {
|
||||
dataItem := loadDatas2(fmt.Sprintf("cat %s | grep -a 'Connection closed by authenticating user' | grep -a 'preauth'", fileList[i]), 15, constant.StatusFailed)
|
||||
failedCount += len(dataItem)
|
||||
datas = append(datas, dataItem...)
|
||||
}
|
||||
dataItem := loadDatas2(fmt.Sprintf("cat %s | grep Accepted", fileList[i]), 14, constant.StatusSuccess)
|
||||
datas = append(datas, dataItem...)
|
||||
}
|
||||
successfulCount = len(datas) - failedCount
|
||||
fmt.Println(len(datas), successfulCount, failedCount)
|
||||
}
|
||||
|
||||
func loadDatas2(command string, length int, status string) []history {
|
||||
var datas []history
|
||||
stdout2, err := cmd.Exec(command)
|
||||
if err == nil {
|
||||
lines := strings.Split(string(stdout2), "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) != length {
|
||||
continue
|
||||
}
|
||||
historyItem := history{
|
||||
Belong: parts[3],
|
||||
User: parts[8],
|
||||
AuthMode: parts[6],
|
||||
Address: parts[10],
|
||||
Port: parts[12],
|
||||
Status: status,
|
||||
}
|
||||
dateStr := fmt.Sprintf("%d %s %s %s", time.Now().Year(), parts[0], parts[1], parts[2])
|
||||
historyItem.Date, _ = time.Parse("2006 Jan 2 15:04:05", dateStr)
|
||||
// if err != nil {
|
||||
// historyItem.Date, _ = time.Parse("2006 Jan 2 15:04:05", dateStr)
|
||||
// }
|
||||
fmt.Println(dateStr + "===>" + historyItem.Date.Format("2006.01.02 15:04:05"))
|
||||
datas = append(datas, historyItem)
|
||||
}
|
||||
}
|
||||
return datas
|
||||
}
|
||||
|
||||
func TestCas(t *testing.T) {
|
||||
ss := "2023 May 9 14:48:28"
|
||||
kk, err := time.Parse("2006 Jan 2 15:04:05", ss)
|
||||
fmt.Println(kk, err)
|
||||
}
|
||||
|
||||
type history struct {
|
||||
Date time.Time
|
||||
Belong string
|
||||
User string
|
||||
AuthMode string
|
||||
Address string
|
||||
Port string
|
||||
Status string
|
||||
Message string
|
||||
}
|
|
@ -40,6 +40,7 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
|||
hostRouter.POST("/ssh/generate", baseApi.GenerateSSH)
|
||||
hostRouter.POST("/ssh/secret", baseApi.LoadSSHSecret)
|
||||
hostRouter.POST("/ssh/log", baseApi.LoadSSHLogs)
|
||||
hostRouter.POST("/ssh/conffile/update", baseApi.UpdateSSHByfile)
|
||||
|
||||
hostRouter.GET("/command", baseApi.ListCommand)
|
||||
hostRouter.POST("/command", baseApi.CreateCommand)
|
||||
|
|
|
@ -129,7 +129,7 @@ export namespace Host {
|
|||
}
|
||||
export interface sshHistory {
|
||||
date: Date;
|
||||
belong: string;
|
||||
isLocal: boolean;
|
||||
user: string;
|
||||
authMode: string;
|
||||
address: string;
|
||||
|
|
|
@ -104,6 +104,9 @@ export const getSSHInfo = () => {
|
|||
export const updateSSH = (key: string, value: string) => {
|
||||
return http.post(`/hosts/ssh/update`, { key: key, value: value });
|
||||
};
|
||||
export const updateSSHByfile = (file: string) => {
|
||||
return http.post(`/hosts/ssh/conffile/update`, { file: file });
|
||||
};
|
||||
export const generateSecret = (params: Host.SSHGenerate) => {
|
||||
return http.post(`/hosts/ssh/generate`, params);
|
||||
};
|
||||
|
|
|
@ -815,6 +815,45 @@ const message = {
|
|||
'The default user of the PHP operating environment: the user group is 1000:1000, it is normal that the users inside and outside the container show inconsistencies',
|
||||
searchHelper: 'Support wildcards such as *',
|
||||
},
|
||||
ssh: {
|
||||
sshChange: 'SSH Setting',
|
||||
sshChangeHelper: 'Are you sure to change the SSH {0} configuration to {1}?',
|
||||
sshFileChangeHelper:
|
||||
'Modifying the configuration file may cause service availability. Exercise caution when performing this operation. Do you want to continue?',
|
||||
port: 'Port',
|
||||
portHelper: 'Specifies the port number monitored by the SSH service. The default port number is 22.',
|
||||
listenAddress: 'Listening address',
|
||||
addressHelper:
|
||||
'Specify the IP address monitored by the SSH service. The default value is 0.0.0.0. That is, all network interfaces are monitored.',
|
||||
permitRootLogin: 'root user',
|
||||
rootSettingHelper: 'The default login mode is SSH for user root.',
|
||||
rootHelper1: 'Allow SSH login',
|
||||
rootHelper2: 'Disable SSH login',
|
||||
rootHelper3: 'Only key login is allowed',
|
||||
rootHelper4: 'Only predefined commands can be executed. No other operations can be performed.',
|
||||
passwordAuthentication: 'Password auth',
|
||||
pwdAuthHelper: 'Whether to enable password authentication. This parameter is enabled by default.',
|
||||
pubkeyAuthentication: 'Key auth',
|
||||
key: 'Key',
|
||||
pubkey: 'Key info',
|
||||
encryptionMode: 'Encryption mode',
|
||||
passwordHelper: 'Please enter a 6-10 digit encryption password',
|
||||
generate: 'Generate key',
|
||||
reGenerate: 'Regenerate key',
|
||||
keyAuthHelper: 'Whether to enable key authentication. This parameter is enabled by default.',
|
||||
useDNS: 'useDNS',
|
||||
dnsHelper:
|
||||
'Controls whether the DNS resolution function is enabled on the SSH server to verify the identity of the connection.',
|
||||
loginLogs: 'SSH login log',
|
||||
loginUser: 'User',
|
||||
loginMode: 'Login mode',
|
||||
authenticating: 'Key',
|
||||
publickey: 'Key',
|
||||
password: 'Password',
|
||||
belong: 'Belong',
|
||||
local: 'Local',
|
||||
remote: 'Remote',
|
||||
},
|
||||
setting: {
|
||||
all: 'All',
|
||||
panel: 'Panel',
|
||||
|
|
|
@ -823,6 +823,7 @@ const message = {
|
|||
ssh: {
|
||||
sshChange: 'SSH 配置修改',
|
||||
sshChangeHelper: '确认将 SSH {0} 配置修改为 {1} 吗?',
|
||||
sshFileChangeHelper: '直接修改配置文件可能会导致服务不可用,请谨慎操作,是否继续?',
|
||||
port: '连接端口',
|
||||
portHelper: '指定 SSH 服务监听的端口号,默认为 22。',
|
||||
listenAddress: '监听地址',
|
||||
|
@ -832,7 +833,7 @@ const message = {
|
|||
rootHelper1: '允许 SSH 登录',
|
||||
rootHelper2: '禁止 SSH 登录',
|
||||
rootHelper3: '仅允许密钥登录',
|
||||
rootHelper4: '仅允许带密码的密钥登录',
|
||||
rootHelper4: '仅允许执行预先定义的命令,不能进行其他操作。',
|
||||
passwordAuthentication: '密码认证',
|
||||
pwdAuthHelper: '是否启用密码认证,默认启用。',
|
||||
pubkeyAuthentication: '密钥认证',
|
||||
|
@ -849,7 +850,11 @@ const message = {
|
|||
loginUser: '用户',
|
||||
loginMode: '登录方式',
|
||||
authenticating: '密钥',
|
||||
publickey: '密钥',
|
||||
password: '密码',
|
||||
belong: '归属地',
|
||||
local: '内网',
|
||||
remote: '外网',
|
||||
},
|
||||
setting: {
|
||||
all: '全部',
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
<template #toolbar>
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
<el-tag type="success">{{ $t('commons.status.success') }}: {{ successfulCount }}</el-tag>
|
||||
<el-tag type="danger" style="margin-left: 5px">
|
||||
<el-tag type="success" class="tagClass" @click="onSearch('Success')">
|
||||
{{ $t('commons.status.success') }}: {{ successfulCount }}
|
||||
</el-tag>
|
||||
<el-tag type="danger" class="tagClass" @click="onSearch('Failed')" style="margin-left: 5px">
|
||||
{{ $t('commons.status.failed') }}: {{ faliedCount }}
|
||||
</el-tag>
|
||||
</el-col>
|
||||
|
@ -16,8 +18,8 @@
|
|||
<div class="search-button">
|
||||
<el-input
|
||||
v-model="searchInfo"
|
||||
clearable
|
||||
@clear="search()"
|
||||
clearable
|
||||
suffix-icon="Search"
|
||||
@keyup.enter="search()"
|
||||
@change="search()"
|
||||
|
@ -29,7 +31,7 @@
|
|||
</template>
|
||||
|
||||
<template #search>
|
||||
<el-select v-model="searchStatus" @change="search()" clearable>
|
||||
<el-select v-model="searchStatus" @change="search()">
|
||||
<template #prefix>{{ $t('commons.table.status') }}</template>
|
||||
<el-option :label="$t('commons.table.all')" value="All"></el-option>
|
||||
<el-option :label="$t('commons.status.success')" value="Success"></el-option>
|
||||
|
@ -38,9 +40,11 @@
|
|||
</template>
|
||||
<template #main>
|
||||
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
|
||||
<el-table-column min-width="40" :label="$t('logs.loginIP')" prop="ip">
|
||||
<template #default="{ row }">{{ row.address }}:{{ row.port }}</template>
|
||||
<el-table-column min-width="60" :label="$t('logs.loginIP')" prop="address" />
|
||||
<el-table-column min-width="30" :label="$t('ssh.belong')" prop="isLocal">
|
||||
<template #default="{ row }">{{ row.isLocal ? $t('ssh.local') : $t('ssh.remote') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column min-width="40" :label="$t('firewall.port')" prop="port" />
|
||||
<el-table-column min-width="40" :label="$t('ssh.loginMode')" prop="authMode">
|
||||
<template #default="{ row }">{{ $t('ssh.' + row.authMode) }}</template>
|
||||
</el-table-column>
|
||||
|
@ -104,14 +108,33 @@ const search = async () => {
|
|||
data.value = res.data.logs || [];
|
||||
faliedCount.value = res.data.failedCount;
|
||||
successfulCount.value = res.data.successfulCount;
|
||||
paginationConfig.total = res.data.failedCount + res.data.successfulCount;
|
||||
if (searchStatus.value === 'Success') {
|
||||
paginationConfig.total = res.data.successfulCount;
|
||||
}
|
||||
if (searchStatus.value === 'Failed') {
|
||||
paginationConfig.total = res.data.failedCount;
|
||||
}
|
||||
if (searchStatus.value === 'All') {
|
||||
paginationConfig.total = res.data.failedCount + res.data.successfulCount;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const onSearch = (status: string) => {
|
||||
searchStatus.value = status;
|
||||
search();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
search();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tagClass {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -117,8 +117,8 @@ import { oneDark } from '@codemirror/theme-one-dark';
|
|||
import PubKey from '@/views/host/ssh/ssh/pubkey/index.vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { getSSHInfo, updateSSH } from '@/api/modules/host';
|
||||
import { LoadFile, SaveFileContent } from '@/api/modules/files';
|
||||
import { getSSHInfo, updateSSH, updateSSHByfile } from '@/api/modules/host';
|
||||
import { LoadFile } from '@/api/modules/files';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||
|
||||
|
@ -141,15 +141,21 @@ const form = reactive({
|
|||
});
|
||||
|
||||
const onSaveFile = async () => {
|
||||
loading.value = true;
|
||||
await SaveFileContent({ path: '/etc/ssh/sshd_config', content: sshConf.value })
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
ElMessageBox.confirm(i18n.global.t('ssh.sshFileChangeHelper'), i18n.global.t('ssh.sshChange'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
type: 'info',
|
||||
}).then(async () => {
|
||||
loading.value = true;
|
||||
await updateSSHByfile(sshConf.value)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onOpenDrawer = () => {
|
||||
|
@ -165,7 +171,7 @@ const onSave = async (formEl: FormInstance | undefined, key: string, value: stri
|
|||
}
|
||||
|
||||
ElMessageBox.confirm(
|
||||
i18n.global.t('ssh.sshChangeHelper', [i18n.global.t('ssh.' + itemKey), value]),
|
||||
i18n.global.t('ssh.sshChangeHelper', [i18n.global.t('ssh.' + itemKey), changei18n(value)]),
|
||||
i18n.global.t('ssh.sshChange'),
|
||||
{
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
|
@ -196,6 +202,23 @@ function callback(error: any) {
|
|||
}
|
||||
}
|
||||
|
||||
const changei18n = (value: string) => {
|
||||
switch (value) {
|
||||
case 'yes':
|
||||
return i18n.global.t('commons.button.enable');
|
||||
case 'no':
|
||||
return i18n.global.t('commons.button.disable');
|
||||
case 'without-password':
|
||||
return i18n.global.t('ssh.rootHelper3');
|
||||
case 'forced-commands-only':
|
||||
return i18n.global.t('ssh.rootHelper4');
|
||||
case 'yes':
|
||||
return i18n.global.t('commons.button.enable');
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
const loadSSHConf = async () => {
|
||||
const res = await LoadFile({ path: '/etc/ssh/sshd_config' });
|
||||
sshConf.value = res.data || '';
|
||||
|
|
Loading…
Reference in New Issue