mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 20:49:03 +08:00
feat: 病毒扫描增加病毒库刷新状态 (#5710)
This commit is contained in:
parent
0c2653d270
commit
577dfadb9a
@ -190,12 +190,12 @@ func (b *BaseApi) LoadClamRecordLog(c *gin.Context) {
|
|||||||
// @Summary Load clam file
|
// @Summary Load clam file
|
||||||
// @Description 获取扫描文件
|
// @Description 获取扫描文件
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Param request body dto.OperationWithName true "request"
|
// @Param request body dto.ClamFileReq true "request"
|
||||||
// @Success 200 {object} dto.PageResult
|
// @Success 200 {object} dto.PageResult
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Router /toolbox/clam/file/search [post]
|
// @Router /toolbox/clam/file/search [post]
|
||||||
func (b *BaseApi) SearchClamFile(c *gin.Context) {
|
func (b *BaseApi) SearchClamFile(c *gin.Context) {
|
||||||
var req dto.OperationWithName
|
var req dto.ClamFileReq
|
||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@ type ClamBaseInfo struct {
|
|||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
IsActive bool `json:"isActive"`
|
IsActive bool `json:"isActive"`
|
||||||
IsExist bool `json:"isExist"`
|
IsExist bool `json:"isExist"`
|
||||||
|
|
||||||
|
FreshVersion string `json:"freshVersion"`
|
||||||
|
FreshIsActive bool `json:"freshIsActive"`
|
||||||
|
FreshIsExist bool `json:"freshIsExist"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClamInfo struct {
|
type ClamInfo struct {
|
||||||
@ -36,6 +40,11 @@ type ClamLogReq struct {
|
|||||||
RecordName string `json:"recordName"`
|
RecordName string `json:"recordName"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClamFileReq struct {
|
||||||
|
Tail string `json:"tail"`
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
type ClamLog struct {
|
type ClamLog struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ScanDate string `json:"scanDate"`
|
ScanDate string `json:"scanDate"`
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
clamServiceNameCentOs = "clamd@scan.service"
|
clamServiceNameCentOs = "clamd@scan.service"
|
||||||
clamServiceNameUbuntu = "clamav-daemon.service"
|
clamServiceNameUbuntu = "clamav-daemon.service"
|
||||||
|
freshClamService = "clamav-freshclam.service"
|
||||||
resultDir = "clamav"
|
resultDir = "clamav"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ type IClamService interface {
|
|||||||
Update(req dto.ClamUpdate) error
|
Update(req dto.ClamUpdate) error
|
||||||
Delete(req dto.ClamDelete) error
|
Delete(req dto.ClamDelete) error
|
||||||
HandleOnce(req dto.OperateByID) error
|
HandleOnce(req dto.OperateByID) error
|
||||||
LoadFile(req dto.OperationWithName) (string, error)
|
LoadFile(req dto.ClamFileReq) (string, error)
|
||||||
UpdateFile(req dto.UpdateByNameAndFile) error
|
UpdateFile(req dto.UpdateByNameAndFile) error
|
||||||
LoadRecords(req dto.ClamLogSearch) (int64, interface{}, error)
|
LoadRecords(req dto.ClamLogSearch) (int64, interface{}, error)
|
||||||
CleanRecord(req dto.OperateByID) error
|
CleanRecord(req dto.OperateByID) error
|
||||||
@ -56,6 +57,7 @@ func NewIClamService() IClamService {
|
|||||||
func (f *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
func (f *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
||||||
var baseInfo dto.ClamBaseInfo
|
var baseInfo dto.ClamBaseInfo
|
||||||
baseInfo.Version = "-"
|
baseInfo.Version = "-"
|
||||||
|
baseInfo.FreshVersion = "-"
|
||||||
exist1, _ := systemctl.IsExist(clamServiceNameCentOs)
|
exist1, _ := systemctl.IsExist(clamServiceNameCentOs)
|
||||||
if exist1 {
|
if exist1 {
|
||||||
f.serviceName = clamServiceNameCentOs
|
f.serviceName = clamServiceNameCentOs
|
||||||
@ -68,6 +70,11 @@ func (f *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
|||||||
baseInfo.IsExist = true
|
baseInfo.IsExist = true
|
||||||
baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameUbuntu)
|
baseInfo.IsActive, _ = systemctl.IsActive(clamServiceNameUbuntu)
|
||||||
}
|
}
|
||||||
|
freshExist, _ := systemctl.IsExist(freshClamService)
|
||||||
|
if freshExist {
|
||||||
|
baseInfo.FreshIsExist = true
|
||||||
|
baseInfo.FreshIsActive, _ = systemctl.IsActive(freshClamService)
|
||||||
|
}
|
||||||
|
|
||||||
if baseInfo.IsActive {
|
if baseInfo.IsActive {
|
||||||
version, err := cmd.Exec("clamdscan --version")
|
version, err := cmd.Exec("clamdscan --version")
|
||||||
@ -80,6 +87,17 @@ func (f *ClamService) LoadBaseInfo() (dto.ClamBaseInfo, error) {
|
|||||||
baseInfo.Version = strings.TrimPrefix(version, "ClamAV ")
|
baseInfo.Version = strings.TrimPrefix(version, "ClamAV ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if baseInfo.FreshIsActive {
|
||||||
|
version, err := cmd.Exec("freshclam --version")
|
||||||
|
if err != nil {
|
||||||
|
return baseInfo, nil
|
||||||
|
}
|
||||||
|
if strings.Contains(version, "/") {
|
||||||
|
baseInfo.FreshVersion = strings.TrimPrefix(strings.Split(version, "/")[0], "ClamAV ")
|
||||||
|
} else {
|
||||||
|
baseInfo.FreshVersion = strings.TrimPrefix(version, "ClamAV ")
|
||||||
|
}
|
||||||
|
}
|
||||||
return baseInfo, nil
|
return baseInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +109,12 @@ func (f *ClamService) Operate(operate string) error {
|
|||||||
return fmt.Errorf("%s the %s failed, err: %s", operate, f.serviceName, stdout)
|
return fmt.Errorf("%s the %s failed, err: %s", operate, f.serviceName, stdout)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
case "fresh-start", "fresh-restart", "fresh-stop":
|
||||||
|
stdout, err := cmd.Execf("systemctl %s %s", strings.TrimPrefix(operate, "fresh-"), freshClamService)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s the %s failed, err: %s", operate, f.serviceName, stdout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("not support such operation: %v", operate)
|
return fmt.Errorf("not support such operation: %v", operate)
|
||||||
}
|
}
|
||||||
@ -296,7 +320,7 @@ func (u *ClamService) CleanRecord(req dto.OperateByID) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ClamService) LoadFile(req dto.OperationWithName) (string, error) {
|
func (u *ClamService) LoadFile(req dto.ClamFileReq) (string, error) {
|
||||||
filePath := ""
|
filePath := ""
|
||||||
switch req.Name {
|
switch req.Name {
|
||||||
case "clamd":
|
case "clamd":
|
||||||
@ -306,6 +330,10 @@ func (u *ClamService) LoadFile(req dto.OperationWithName) (string, error) {
|
|||||||
filePath = "/etc/clamd.d/scan.conf"
|
filePath = "/etc/clamd.d/scan.conf"
|
||||||
}
|
}
|
||||||
case "clamd-log":
|
case "clamd-log":
|
||||||
|
filePath = u.loadLogPath("clamd-log")
|
||||||
|
if len(filePath) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
if u.serviceName == clamServiceNameUbuntu {
|
if u.serviceName == clamServiceNameUbuntu {
|
||||||
filePath = "/var/log/clamav/clamav.log"
|
filePath = "/var/log/clamav/clamav.log"
|
||||||
} else {
|
} else {
|
||||||
@ -318,6 +346,10 @@ func (u *ClamService) LoadFile(req dto.OperationWithName) (string, error) {
|
|||||||
filePath = "/etc/freshclam.conf"
|
filePath = "/etc/freshclam.conf"
|
||||||
}
|
}
|
||||||
case "freshclam-log":
|
case "freshclam-log":
|
||||||
|
filePath = u.loadLogPath("freshclam-log")
|
||||||
|
if len(filePath) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
if u.serviceName == clamServiceNameUbuntu {
|
if u.serviceName == clamServiceNameUbuntu {
|
||||||
filePath = "/var/log/clamav/freshclam.log"
|
filePath = "/var/log/clamav/freshclam.log"
|
||||||
} else {
|
} else {
|
||||||
@ -329,11 +361,18 @@ func (u *ClamService) LoadFile(req dto.OperationWithName) (string, error) {
|
|||||||
if _, err := os.Stat(filePath); err != nil {
|
if _, err := os.Stat(filePath); err != nil {
|
||||||
return "", buserr.New("ErrHttpReqNotFound")
|
return "", buserr.New("ErrHttpReqNotFound")
|
||||||
}
|
}
|
||||||
content, err := os.ReadFile(filePath)
|
var tail string
|
||||||
if err != nil {
|
if req.Tail != "0" {
|
||||||
return "", err
|
tail = req.Tail
|
||||||
|
} else {
|
||||||
|
tail = "+1"
|
||||||
}
|
}
|
||||||
return string(content), nil
|
cmd := exec.Command("tail", "-n", tail, filePath)
|
||||||
|
stdout, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("tail -n %v failed, err: %v", req.Tail, err)
|
||||||
|
}
|
||||||
|
return string(stdout), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error {
|
func (u *ClamService) UpdateFile(req dto.UpdateByNameAndFile) error {
|
||||||
@ -419,3 +458,42 @@ func loadResultFromLog(pathItem string) dto.ClamLog {
|
|||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
func (u *ClamService) loadLogPath(name string) string {
|
||||||
|
confPath := ""
|
||||||
|
if name == "clamd-log" {
|
||||||
|
if u.serviceName == clamServiceNameUbuntu {
|
||||||
|
confPath = "/etc/clamav/clamd.conf"
|
||||||
|
} else {
|
||||||
|
confPath = "/etc/clamd.d/scan.conf"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if u.serviceName == clamServiceNameUbuntu {
|
||||||
|
confPath = "/etc/clamav/freshclam.conf"
|
||||||
|
} else {
|
||||||
|
confPath = "/etc/freshclam.conf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(confPath); err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
content, err := os.ReadFile(confPath)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(content), "\n")
|
||||||
|
if name == "clamd-log" {
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "LogFile ") {
|
||||||
|
return strings.Trim(strings.ReplaceAll(line, "LogFile ", ""), " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "UpdateLogFile ") {
|
||||||
|
return strings.Trim(strings.ReplaceAll(line, "UpdateLogFile ", ""), " ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
@ -11212,7 +11212,7 @@ const docTemplate = `{
|
|||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/dto.OperationWithName"
|
"$ref": "#/definitions/dto.ClamFileReq"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -12928,6 +12928,57 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/websites/ca/download": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "下载 CA 证书文件",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Website CA"
|
||||||
|
],
|
||||||
|
"summary": "Download CA file",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.WebsiteResourceReq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [
|
||||||
|
{
|
||||||
|
"db": "website_cas",
|
||||||
|
"input_column": "id",
|
||||||
|
"input_value": "id",
|
||||||
|
"isList": false,
|
||||||
|
"output_column": "name",
|
||||||
|
"output_value": "name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bodyKeys": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"formatEN": "download ca file [name]",
|
||||||
|
"formatZH": "下载 CA 证书文件 [name]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/websites/ca/obtain": {
|
"/websites/ca/obtain": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -15482,6 +15533,15 @@ const docTemplate = `{
|
|||||||
"dto.ClamBaseInfo": {
|
"dto.ClamBaseInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"freshIsActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"freshIsExist": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"freshVersion": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"isActive": {
|
"isActive": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@ -15533,6 +15593,20 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.ClamFileReq": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tail": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.ClamLogReq": {
|
"dto.ClamLogReq": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -19778,6 +19852,9 @@ const docTemplate = `{
|
|||||||
"group": {
|
"group": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"isDir": {
|
"isDir": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@ -20610,6 +20687,9 @@ const docTemplate = `{
|
|||||||
"path"
|
"path"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -20765,6 +20845,9 @@ const docTemplate = `{
|
|||||||
"expand": {
|
"expand": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -22265,6 +22348,9 @@ const docTemplate = `{
|
|||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"sni": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -22833,6 +22919,9 @@ const docTemplate = `{
|
|||||||
"group": {
|
"group": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"isDir": {
|
"isDir": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -11205,7 +11205,7 @@
|
|||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/dto.OperationWithName"
|
"$ref": "#/definitions/dto.ClamFileReq"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -12921,6 +12921,57 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/websites/ca/download": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "下载 CA 证书文件",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Website CA"
|
||||||
|
],
|
||||||
|
"summary": "Download CA file",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "request",
|
||||||
|
"name": "request",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.WebsiteResourceReq"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-panel-log": {
|
||||||
|
"BeforeFunctions": [
|
||||||
|
{
|
||||||
|
"db": "website_cas",
|
||||||
|
"input_column": "id",
|
||||||
|
"input_value": "id",
|
||||||
|
"isList": false,
|
||||||
|
"output_column": "name",
|
||||||
|
"output_value": "name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bodyKeys": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"formatEN": "download ca file [name]",
|
||||||
|
"formatZH": "下载 CA 证书文件 [name]",
|
||||||
|
"paramKeys": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/websites/ca/obtain": {
|
"/websites/ca/obtain": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -15475,6 +15526,15 @@
|
|||||||
"dto.ClamBaseInfo": {
|
"dto.ClamBaseInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"freshIsActive": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"freshIsExist": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"freshVersion": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"isActive": {
|
"isActive": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@ -15526,6 +15586,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dto.ClamFileReq": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tail": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dto.ClamLogReq": {
|
"dto.ClamLogReq": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -19771,6 +19845,9 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"isDir": {
|
"isDir": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@ -20603,6 +20680,9 @@
|
|||||||
"path"
|
"path"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -20758,6 +20838,9 @@
|
|||||||
"expand": {
|
"expand": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"page": {
|
"page": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
@ -22258,6 +22341,9 @@
|
|||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"sni": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -22826,6 +22912,9 @@
|
|||||||
"group": {
|
"group": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"isDetail": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"isDir": {
|
"isDir": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -218,6 +218,12 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
dto.ClamBaseInfo:
|
dto.ClamBaseInfo:
|
||||||
properties:
|
properties:
|
||||||
|
freshIsActive:
|
||||||
|
type: boolean
|
||||||
|
freshIsExist:
|
||||||
|
type: boolean
|
||||||
|
freshVersion:
|
||||||
|
type: string
|
||||||
isActive:
|
isActive:
|
||||||
type: boolean
|
type: boolean
|
||||||
isExist:
|
isExist:
|
||||||
@ -251,6 +257,15 @@ definitions:
|
|||||||
required:
|
required:
|
||||||
- ids
|
- ids
|
||||||
type: object
|
type: object
|
||||||
|
dto.ClamFileReq:
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
tail:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
type: object
|
||||||
dto.ClamLogReq:
|
dto.ClamLogReq:
|
||||||
properties:
|
properties:
|
||||||
clamName:
|
clamName:
|
||||||
@ -3119,6 +3134,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
group:
|
group:
|
||||||
type: string
|
type: string
|
||||||
|
isDetail:
|
||||||
|
type: boolean
|
||||||
isDir:
|
isDir:
|
||||||
type: boolean
|
type: boolean
|
||||||
isHidden:
|
isHidden:
|
||||||
@ -3668,6 +3685,8 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
request.FileContentReq:
|
request.FileContentReq:
|
||||||
properties:
|
properties:
|
||||||
|
isDetail:
|
||||||
|
type: boolean
|
||||||
path:
|
path:
|
||||||
type: string
|
type: string
|
||||||
required:
|
required:
|
||||||
@ -3773,6 +3792,8 @@ definitions:
|
|||||||
type: boolean
|
type: boolean
|
||||||
expand:
|
expand:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
isDetail:
|
||||||
|
type: boolean
|
||||||
page:
|
page:
|
||||||
type: integer
|
type: integer
|
||||||
pageSize:
|
pageSize:
|
||||||
@ -4780,6 +4801,8 @@ definitions:
|
|||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
sni:
|
||||||
|
type: boolean
|
||||||
required:
|
required:
|
||||||
- id
|
- id
|
||||||
- match
|
- match
|
||||||
@ -5167,6 +5190,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
group:
|
group:
|
||||||
type: string
|
type: string
|
||||||
|
isDetail:
|
||||||
|
type: boolean
|
||||||
isDir:
|
isDir:
|
||||||
type: boolean
|
type: boolean
|
||||||
isHidden:
|
isHidden:
|
||||||
@ -12558,7 +12583,7 @@ paths:
|
|||||||
name: request
|
name: request
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/dto.OperationWithName'
|
$ref: '#/definitions/dto.ClamFileReq'
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
@ -13665,6 +13690,39 @@ paths:
|
|||||||
formatEN: Delete website ca [name]
|
formatEN: Delete website ca [name]
|
||||||
formatZH: 删除网站 ca [name]
|
formatZH: 删除网站 ca [name]
|
||||||
paramKeys: []
|
paramKeys: []
|
||||||
|
/websites/ca/download:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 下载 CA 证书文件
|
||||||
|
parameters:
|
||||||
|
- description: request
|
||||||
|
in: body
|
||||||
|
name: request
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/request.WebsiteResourceReq'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
summary: Download CA file
|
||||||
|
tags:
|
||||||
|
- Website CA
|
||||||
|
x-panel-log:
|
||||||
|
BeforeFunctions:
|
||||||
|
- db: website_cas
|
||||||
|
input_column: id
|
||||||
|
input_value: id
|
||||||
|
isList: false
|
||||||
|
output_column: name
|
||||||
|
output_value: name
|
||||||
|
bodyKeys:
|
||||||
|
- id
|
||||||
|
formatEN: download ca file [name]
|
||||||
|
formatZH: 下载 CA 证书文件 [name]
|
||||||
|
paramKeys: []
|
||||||
/websites/ca/obtain:
|
/websites/ca/obtain:
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -121,6 +121,10 @@ export namespace Toolbox {
|
|||||||
version: string;
|
version: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
isExist: boolean;
|
isExist: boolean;
|
||||||
|
|
||||||
|
freshVersion: string;
|
||||||
|
freshIsExist: boolean;
|
||||||
|
freshIsActive: boolean;
|
||||||
}
|
}
|
||||||
export interface ClamInfo {
|
export interface ClamInfo {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -117,8 +117,8 @@ export const searchClamRecord = (param: Toolbox.ClamSearchLog) => {
|
|||||||
export const getClamRecordLog = (param: Toolbox.ClamRecordReq) => {
|
export const getClamRecordLog = (param: Toolbox.ClamRecordReq) => {
|
||||||
return http.post<string>(`/toolbox/clam/record/log`, param);
|
return http.post<string>(`/toolbox/clam/record/log`, param);
|
||||||
};
|
};
|
||||||
export const searchClamFile = (name: string) => {
|
export const searchClamFile = (name: string, tail: string) => {
|
||||||
return http.post<string>(`/toolbox/clam/file/search`, { name: name });
|
return http.post<string>(`/toolbox/clam/file/search`, { name: name, tail: tail });
|
||||||
};
|
};
|
||||||
export const updateClamFile = (name: string, file: string) => {
|
export const updateClamFile = (name: string, file: string) => {
|
||||||
return http.post(`/toolbox/clam/file/update`, { name: name, file: file });
|
return http.post(`/toolbox/clam/file/update`, { name: name, file: file });
|
||||||
|
@ -1074,6 +1074,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
clam: {
|
clam: {
|
||||||
clam: 'Virus Scan',
|
clam: 'Virus Scan',
|
||||||
|
showFresh: 'Show Virus Database Service',
|
||||||
|
hideFresh: 'Hide Virus Database Service',
|
||||||
clamHelper:
|
clamHelper:
|
||||||
'The minimum recommended configuration for ClamAV is: 3 GiB of RAM or more, single-core CPU with 2.0 GHz or higher, and at least 5 GiB of available hard disk space.',
|
'The minimum recommended configuration for ClamAV is: 3 GiB of RAM or more, single-core CPU with 2.0 GHz or higher, and at least 5 GiB of available hard disk space.',
|
||||||
noClam: 'ClamAV service not detected, please refer to the official documentation for installation!',
|
noClam: 'ClamAV service not detected, please refer to the official documentation for installation!',
|
||||||
|
@ -1016,6 +1016,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
clam: {
|
clam: {
|
||||||
clam: '病毒掃描',
|
clam: '病毒掃描',
|
||||||
|
showFresh: '顯示病毒庫服務',
|
||||||
|
hideFresh: '隱藏病毒庫服務',
|
||||||
clamHelper:
|
clamHelper:
|
||||||
'ClamAV 的最低建議配置為:3 GiB 以上的 RAM,2.0 GHz 以上的單核 CPU,以及至少 5 GiB 的可用硬盤空間。',
|
'ClamAV 的最低建議配置為:3 GiB 以上的 RAM,2.0 GHz 以上的單核 CPU,以及至少 5 GiB 的可用硬盤空間。',
|
||||||
noClam: '未檢測到 ClamAV 服務,請參考官方文檔進行安裝!',
|
noClam: '未檢測到 ClamAV 服務,請參考官方文檔進行安裝!',
|
||||||
|
@ -1017,6 +1017,8 @@ const message = {
|
|||||||
},
|
},
|
||||||
clam: {
|
clam: {
|
||||||
clam: '病毒扫描',
|
clam: '病毒扫描',
|
||||||
|
showFresh: '显示病毒库服务',
|
||||||
|
hideFresh: '隐藏病毒库服务',
|
||||||
clamHelper:
|
clamHelper:
|
||||||
'ClamAV 的最低建议配置为:3 GiB 以上的 RAM,2.0 GHz 以上的单核 CPU,以及至少 5 GiB 的可用硬盘空间',
|
'ClamAV 的最低建议配置为:3 GiB 以上的 RAM,2.0 GHz 以上的单核 CPU,以及至少 5 GiB 的可用硬盘空间',
|
||||||
doc: '帮助文档',
|
doc: '帮助文档',
|
||||||
|
@ -29,6 +29,15 @@
|
|||||||
|
|
||||||
<template #main>
|
<template #main>
|
||||||
<div>
|
<div>
|
||||||
|
<el-select style="width: 20%" @change="search" v-model.number="tail">
|
||||||
|
<template #prefix>{{ $t('toolbox.clam.scanResult') }}</template>
|
||||||
|
<el-option :value="0" :label="$t('commons.table.all')" />
|
||||||
|
<el-option :value="10" :label="10" />
|
||||||
|
<el-option :value="100" :label="100" />
|
||||||
|
<el-option :value="200" :label="200" />
|
||||||
|
<el-option :value="500" :label="500" />
|
||||||
|
<el-option :value="1000" :label="1000" />
|
||||||
|
</el-select>
|
||||||
<codemirror
|
<codemirror
|
||||||
:autofocus="true"
|
:autofocus="true"
|
||||||
:placeholder="$t('commons.msg.noneData')"
|
:placeholder="$t('commons.msg.noneData')"
|
||||||
@ -75,13 +84,14 @@ const handleReady = (payload) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const activeName = ref('clamd');
|
const activeName = ref('clamd');
|
||||||
|
const tail = ref(0);
|
||||||
const content = ref();
|
const content = ref();
|
||||||
const confirmRef = ref();
|
const confirmRef = ref();
|
||||||
|
|
||||||
const loadHeight = () => {
|
const loadHeight = () => {
|
||||||
let height = globalStore.openMenuTabs ? '405px' : '375px';
|
let height = globalStore.openMenuTabs ? '425px' : '395px';
|
||||||
if (canUpdate()) {
|
if (canUpdate()) {
|
||||||
height = globalStore.openMenuTabs ? '363px' : '333px';
|
height = globalStore.openMenuTabs ? '383px' : '353px';
|
||||||
}
|
}
|
||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
@ -93,7 +103,7 @@ const canUpdate = () => {
|
|||||||
const search = async (itemName: string) => {
|
const search = async (itemName: string) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
activeName.value = itemName;
|
activeName.value = itemName;
|
||||||
await searchClamFile(activeName.value)
|
await searchClamFile(activeName.value, tail.value + '')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
content.value = res.data;
|
content.value = res.data;
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
<div class="app-status tool-status" v-if="data.isExist">
|
<div class="app-status tool-status" v-if="data.isExist">
|
||||||
<el-card>
|
<el-card>
|
||||||
<div>
|
<div>
|
||||||
<el-tag effect="dark" type="success">ClamAV</el-tag>
|
<el-tag class="w-17" effect="dark" type="success">ClamAV</el-tag>
|
||||||
<el-tag round class="status-content" v-if="data.isActive" type="success">
|
<el-tag round class="status-content" v-if="data.isActive" type="success">
|
||||||
{{ $t('commons.status.running') }}
|
{{ $t('commons.status.running') }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tag round class="status-content" v-if="!data.isActive" type="info">
|
<el-tag round class="status-content" v-if="!data.isActive" type="info">
|
||||||
{{ $t('commons.status.stopped') }}
|
{{ $t('commons.status.stopped') }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tag class="status-content">{{ $t('app.version') }}:{{ data.version }}</el-tag>
|
<el-tag class="status-content w-24">{{ $t('app.version') }}:{{ data.version }}</el-tag>
|
||||||
<span class="buttons">
|
<span class="buttons">
|
||||||
<el-button type="primary" v-if="!data.isActive" link @click="onOperate('start')">
|
<el-button type="primary" v-if="!data.isActive" link @click="onOperate('start')">
|
||||||
{{ $t('app.start') }}
|
{{ $t('app.start') }}
|
||||||
@ -26,6 +26,35 @@
|
|||||||
<el-button type="primary" link @click="setting">
|
<el-button type="primary" link @click="setting">
|
||||||
{{ $t('commons.button.set') }}
|
{{ $t('commons.button.set') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-button type="primary" v-if="showFresh" link @click="changeShow(false)">
|
||||||
|
{{ $t('toolbox.clam.hideFresh') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" v-if="!showFresh" link @click="changeShow(true)">
|
||||||
|
{{ $t('toolbox.clam.showFresh') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4" v-if="showFresh">
|
||||||
|
<el-tag class="w-16" effect="dark" type="success">FreshClam</el-tag>
|
||||||
|
<el-tag round class="status-content" v-if="data.freshIsActive" type="success">
|
||||||
|
{{ $t('commons.status.running') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag round class="status-content" v-if="!data.freshIsActive" type="info">
|
||||||
|
{{ $t('commons.status.stopped') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag class="status-content w-24">{{ $t('app.version') }}:{{ data.freshVersion }}</el-tag>
|
||||||
|
<span class="buttons">
|
||||||
|
<el-button type="primary" v-if="!data.freshIsActive" link @click="onOperate('fresh-start')">
|
||||||
|
{{ $t('app.start') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" v-if="data.freshIsActive" link @click="onOperate('fresh-stop')">
|
||||||
|
{{ $t('app.stop') }}
|
||||||
|
</el-button>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-button type="primary" link @click="onOperate('fresh-restart')">
|
||||||
|
{{ $t('app.restart') }}
|
||||||
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -59,8 +88,13 @@ const data = ref({
|
|||||||
isExist: false,
|
isExist: false,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
version: '',
|
version: '',
|
||||||
|
|
||||||
|
freshIsExist: false,
|
||||||
|
freshIsActive: false,
|
||||||
|
freshVersion: '',
|
||||||
});
|
});
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const showFresh = ref(localStorage.getItem('clam-fresh-show') !== 'hide');
|
||||||
|
|
||||||
const em = defineEmits(['setting', 'getStatus', 'update:loading', 'update:maskShow']);
|
const em = defineEmits(['setting', 'getStatus', 'update:loading', 'update:maskShow']);
|
||||||
|
|
||||||
@ -72,6 +106,11 @@ const toDoc = async () => {
|
|||||||
window.open('https://1panel.cn/docs/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer');
|
window.open('https://1panel.cn/docs/user_manual/toolbox/clam/', '_blank', 'noopener,noreferrer');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeShow = (val: boolean) => {
|
||||||
|
showFresh.value = val;
|
||||||
|
localStorage.setItem('clam-fresh-show', showFresh.value ? 'show' : 'hide');
|
||||||
|
};
|
||||||
|
|
||||||
const onOperate = async (operation: string) => {
|
const onOperate = async (operation: string) => {
|
||||||
em('update:maskShow', false);
|
em('update:maskShow', false);
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
|
Loading…
Reference in New Issue
Block a user