A support delete file via sftp

This commit is contained in:
zhenorzz 2022-10-31 18:24:06 +08:00
parent a810b166f3
commit 6c28feb060
11 changed files with 135 additions and 7 deletions

View File

@ -43,6 +43,7 @@ func (s Server) Routes() []core.Route {
core.NewRoute("/server/previewFile", http.MethodGet, s.PreviewFile).Permissions(permission.SFTPPreviewFile).LogFunc(middleware.AddPreviewLog), core.NewRoute("/server/previewFile", http.MethodGet, s.PreviewFile).Permissions(permission.SFTPPreviewFile).LogFunc(middleware.AddPreviewLog),
core.NewRoute("/server/downloadFile", http.MethodGet, s.DownloadFile).Permissions(permission.SFTPDownloadFile).LogFunc(middleware.AddDownloadLog), core.NewRoute("/server/downloadFile", http.MethodGet, s.DownloadFile).Permissions(permission.SFTPDownloadFile).LogFunc(middleware.AddDownloadLog),
core.NewRoute("/server/uploadFile", http.MethodPost, s.UploadFile).Permissions(permission.SFTPTransferFile).LogFunc(middleware.AddUploadLog), core.NewRoute("/server/uploadFile", http.MethodPost, s.UploadFile).Permissions(permission.SFTPTransferFile).LogFunc(middleware.AddUploadLog),
core.NewRoute("/server/deleteFile", http.MethodDelete, s.DeleteFile).Permissions(permission.SFTPDeleteFile).LogFunc(middleware.AddDeleteLog),
core.NewRoute("/server/transferFile", http.MethodPost, s.TransferFile).Permissions(permission.SFTPUploadFile), core.NewRoute("/server/transferFile", http.MethodPost, s.TransferFile).Permissions(permission.SFTPUploadFile),
core.NewRoute("/server/report", http.MethodGet, s.Report).Permissions(permission.ShowServerMonitorPage), core.NewRoute("/server/report", http.MethodGet, s.Report).Permissions(permission.ShowServerMonitorPage),
core.NewRoute("/server/getAllMonitor", http.MethodGet, s.GetAllMonitor).Permissions(permission.ShowServerMonitorPage), core.NewRoute("/server/getAllMonitor", http.MethodGet, s.GetAllMonitor).Permissions(permission.ShowServerMonitorPage),
@ -544,6 +545,50 @@ func (Server) UploadFile(gp *core.Goploy) core.Response {
return response.JSON{} return response.JSON{}
} }
func (Server) DeleteFile(gp *core.Goploy) core.Response {
type ReqData struct {
File string `json:"file" validate:"required"`
ServerID int64 `json:"serverId" validate:"gt=0"`
}
var reqData ReqData
if err := decodeJson(gp.Body, &reqData); err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
server, err := (model.Server{ID: reqData.ServerID}).GetData()
if err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
client, err := server.ToSSHConfig().Dial()
if err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
defer client.Close()
sftpClient, err := sftp.NewClient(client)
if err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
defer sftpClient.Close()
fi, err := sftpClient.Stat(reqData.File)
if err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
if fi.IsDir() == true {
err = sftpClient.RemoveDirectory(reqData.File)
} else {
err = sftpClient.Remove(reqData.File)
}
if err != nil {
return response.JSON{Code: response.Error, Message: err.Error()}
}
return response.JSON{}
}
func (Server) TransferFile(gp *core.Goploy) core.Response { func (Server) TransferFile(gp *core.Goploy) core.Response {
type ReqData struct { type ReqData struct {
SourceServerID int64 `json:"sourceServerId" validate:"required"` SourceServerID int64 `json:"sourceServerId" validate:"required"`

View File

@ -96,6 +96,36 @@ func AddUploadLog(gp *core.Goploy, resp core.Response) {
} }
} }
func AddDeleteLog(gp *core.Goploy, resp core.Response) {
var serverID int64 = 0
var path = ""
respJson := resp.(response.JSON)
if respJson.Code != response.IllegalParam {
type ReqData struct {
ServerID int64 `json:"account"`
File string `json:"file"`
}
var reqData ReqData
_ = json.Unmarshal(gp.Body, &reqData)
serverID = reqData.ServerID
path = reqData.File
}
err := model.SftpLog{
NamespaceID: gp.Namespace.ID,
UserID: gp.UserInfo.ID,
ServerID: serverID,
RemoteAddr: gp.Request.RemoteAddr,
UserAgent: gp.Request.UserAgent(),
Type: model.SftpLogTypeDelete,
Path: path,
Reason: respJson.Message,
}.AddRow()
if err != nil {
core.Log(core.ERROR, err.Error())
}
}
func AddDownloadLog(gp *core.Goploy, resp core.Response) { func AddDownloadLog(gp *core.Goploy, resp core.Response) {
msg := "" msg := ""
path := "" path := ""

View File

@ -32,6 +32,7 @@ const (
SftpLogTypeUpload = "UPLOAD" SftpLogTypeUpload = "UPLOAD"
SftpLogTypeRead = "READ" SftpLogTypeRead = "READ"
SftpLogTypePreview = "PREVIEW" SftpLogTypePreview = "PREVIEW"
SftpLogTypeDelete = "DELETE"
) )
type SftpLogs []SftpLog type SftpLogs []SftpLog

1
model/sql/1.12.2.sql Normal file
View File

@ -0,0 +1 @@
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (76, 23, 'SFTPDeleteFile', 0, '');

View File

@ -455,6 +455,7 @@ INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALU
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (73, 23, 'DeleteServerProcess', 0, ''); INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (73, 23, 'DeleteServerProcess', 0, '');
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (74, 1, 'ShowOperationLogPage', 0, ''); INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (74, 1, 'ShowOperationLogPage', 0, '');
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (75, 23, 'SFTPTransferFile', 0, ''); INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (75, 23, 'SFTPTransferFile', 0, '');
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (76, 23, 'SFTPDeleteFile', 0, '');
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 13); INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 13);
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 14); INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 14);
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 15); INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 15);

View File

@ -80,4 +80,5 @@ const (
DeleteServerProcess = 73 DeleteServerProcess = 73
ShowOperationLogPage = 74 ShowOperationLogPage = 74
SFTPTransferFile = 75 SFTPTransferFile = 75
SFTPDeleteFile = 76
) )

View File

@ -394,6 +394,19 @@ export class ServerExecProcess extends Request {
} }
} }
export class ServerDeleteFile extends Request {
readonly url = '/server/deleteFile'
readonly method = 'delete'
readonly timeout = 0
public param: {
serverId: number
file: string
}
constructor(param: ServerDeleteFile['param']) {
super()
this.param = param
}
}
export class ServerTransferFile extends Request { export class ServerTransferFile extends Request {
readonly url = '/server/transferFile' readonly url = '/server/transferFile'
readonly method = 'post' readonly method = 'post'
@ -410,7 +423,6 @@ export class ServerTransferFile extends Request {
this.param = param this.param = param
} }
} }
export class ServerExecScript extends Request { export class ServerExecScript extends Request {
readonly url = '/server/execScript' readonly url = '/server/execScript'
readonly method = 'post' readonly method = 'post'

View File

@ -230,7 +230,8 @@
"AddServerProcess": "Add a server process", "AddServerProcess": "Add a server process",
"EditServerProcess": "Edit the server process", "EditServerProcess": "Edit the server process",
"DeleteServerProcess": "Delete the server process", "DeleteServerProcess": "Delete the server process",
"SFTPTransferFile": "Can transfer file via SFTP" "SFTPTransferFile": "Can transfer file via SFTP",
"SFTPDeleteFile": "Can delete file via SFTP"
}, },
"tagsView": { "tagsView": {
"refresh": "Refresh", "refresh": "Refresh",

View File

@ -230,7 +230,8 @@
"EditServerProcess": "编辑服务器进程", "EditServerProcess": "编辑服务器进程",
"DeleteServerProcess": "删除服务器进程", "DeleteServerProcess": "删除服务器进程",
"ShowOperationLogPage": "查看操作日志", "ShowOperationLogPage": "查看操作日志",
"SFTPTransferFile": "SFTP传输文件" "SFTPTransferFile": "SFTP传输文件",
"SFTPDeleteFile": "SFTP删除文件"
}, },
"tagsView": { "tagsView": {
"refresh": "刷新", "refresh": "刷新",

View File

@ -74,4 +74,5 @@ export default Object.freeze({
DeleteServerProcess: 73, DeleteServerProcess: 73,
ShowOperationLogPage: 74, ShowOperationLogPage: 74,
SFTPTransferFile: 75, SFTPTransferFile: 75,
SFTPDeleteFile: 76,
}) })

View File

@ -171,6 +171,13 @@
{{ $t('download') }} {{ $t('download') }}
</Link> </Link>
</el-dropdown-item> </el-dropdown-item>
<DropdownItem
v-if="selectedFile['isDir'] === false"
:permissions="[permission.SFTPDeleteFile]"
@click="deleteFile"
>
{{ $t('delete') }}
</DropdownItem>
<DropdownItem <DropdownItem
:permissions="[permission.SFTPTransferFile]" :permissions="[permission.SFTPTransferFile]"
@click="transferFile" @click="transferFile"
@ -188,9 +195,9 @@
</div> </div>
<div v-show="selectedFile['mode']"> <div v-show="selectedFile['mode']">
<span style="padding: 0 2px">{{ selectedFile['mode'] }}</span> <span style="padding: 0 2px">{{ selectedFile['mode'] }}</span>
<span style="padding: 0 2px">{{ <span style="padding: 0 2px">
humanSize(selectedFile['size']) {{ humanSize(selectedFile['size']) }}
}}</span> </span>
<span style="padding: 0 2px">{{ selectedFile['name'] }}</span> <span style="padding: 0 2px">{{ selectedFile['name'] }}</span>
</div> </div>
</el-row> </el-row>
@ -216,7 +223,7 @@ import path from 'path-browserify'
import { humanSize, parseTime } from '@/utils' import { humanSize, parseTime } from '@/utils'
import { NamespaceKey, getNamespaceId } from '@/utils/namespace' import { NamespaceKey, getNamespaceId } from '@/utils/namespace'
import type { ElUpload } from 'element-plus' import type { ElUpload } from 'element-plus'
import { ServerData, ServerSFTPFile } from '@/api/server' import { ServerData, ServerSFTPFile, ServerDeleteFile } from '@/api/server'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { HttpResponse } from '@/api/types' import { HttpResponse } from '@/api/types'
import { ref, PropType, computed, onBeforeUnmount } from 'vue' import { ref, PropType, computed, onBeforeUnmount } from 'vue'
@ -409,6 +416,33 @@ function dirOpen(dir: string) {
goto(dir) goto(dir)
} }
function deleteFile() {
const file = path.normalize(dir.value + '/' + selectedFile.value.name)
ElMessageBox.confirm(t('serverPage.deleteTips', { name: file }), t('tips'), {
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
})
.then(() => {
fileListLoading.value = true
new ServerDeleteFile({
serverId: serverId.value,
file: file,
})
.request()
.then(() => {
const pos = fileList.value.findIndex(
(item) => item.name === selectedFile.value.name
)
fileList.value.splice(pos, 1)
})
.finally(() => {
fileListLoading.value = false
})
})
.catch()
}
function transferFile() { function transferFile() {
emit('transfer-file', selectedFile.value) emit('transfer-file', selectedFile.value)
} }