mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 00:09:16 +08:00
fix: 解决越权下载文件的问题 (#1813)
This commit is contained in:
parent
202a2ad7ae
commit
f6b84d384e
@ -246,7 +246,8 @@ func (b *BaseApi) TargetDownload(c *gin.Context) {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, filePath)
|
||||
|
||||
c.File(filePath)
|
||||
}
|
||||
|
||||
// @Tags Cronjob
|
||||
|
@ -544,28 +544,6 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Download file with path
|
||||
// @Description 下载指定文件
|
||||
// @Accept json
|
||||
// @Param request body dto.FilePath true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/download/bypath [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载文件 [path]","formatEN":"Download file [path]"}
|
||||
func (b *BaseApi) DownloadFile(c *gin.Context) {
|
||||
var req dto.FilePath
|
||||
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
|
||||
}
|
||||
c.File(req.Path)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Load file size
|
||||
// @Description 获取文件夹大小
|
||||
|
@ -3,6 +3,8 @@ package v1
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
@ -134,6 +136,22 @@ func (b *BaseApi) LoadFromCert(c *gin.Context) {
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Download system cert
|
||||
// @Description 下载证书
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/ssl/download [post]
|
||||
func (b *BaseApi) DownloadSSL(c *gin.Context) {
|
||||
pathItem := path.Join(global.CONF.System.BaseDir, "1panel/secret/server.crt")
|
||||
if _, err := os.Stat(pathItem); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.File(pathItem)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Update system port
|
||||
// @Description 更新系统端口
|
||||
|
@ -141,12 +141,8 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
|
||||
if record.ID == 0 {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
cronjob, _ := cronjobRepo.Get(commonRepo.WithByID(record.CronjobID))
|
||||
if cronjob.ID == 0 {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
backup, _ := backupRepo.Get(commonRepo.WithByID(down.BackupAccountID))
|
||||
if cronjob.ID == 0 {
|
||||
if backup.ID == 0 {
|
||||
return "", constant.ErrRecordNotFound
|
||||
}
|
||||
if backup.Type == "LOCAL" || record.FromLocal {
|
||||
@ -155,15 +151,17 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
|
||||
}
|
||||
return record.File, nil
|
||||
}
|
||||
client, err := NewIBackupService().NewClient(&backup)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tempPath := fmt.Sprintf("%s/download/%s", constant.DataDir, record.File)
|
||||
_ = os.MkdirAll(path.Dir(tempPath), os.ModePerm)
|
||||
isOK, err := client.Download(record.File, tempPath)
|
||||
if !isOK || err != nil {
|
||||
return "", err
|
||||
if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) {
|
||||
client, err := NewIBackupService().NewClient(&backup)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_ = os.MkdirAll(path.Dir(tempPath), os.ModePerm)
|
||||
isOK, err := client.Download(record.File, tempPath)
|
||||
if !isOK || err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return tempPath, nil
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ func loadInfoFromCert() (*dto.SSLInfo, error) {
|
||||
return &dto.SSLInfo{
|
||||
Domain: strings.Join(domains, ","),
|
||||
Timeout: certObj.NotAfter.Format("2006-01-02 15:04:05"),
|
||||
RootPath: global.CONF.System.BaseDir + "/1panel/secret/server.crt",
|
||||
RootPath: path.Join(global.CONF.System.BaseDir, "1panel/secret/server.crt"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) {
|
||||
fileRouter.POST("/wget", baseApi.WgetFile)
|
||||
fileRouter.POST("/move", baseApi.MoveFile)
|
||||
fileRouter.GET("/download", baseApi.Download)
|
||||
fileRouter.POST("/download/bypath", baseApi.DownloadFile)
|
||||
fileRouter.POST("/chunkdownload", baseApi.DownloadChunkFiles)
|
||||
fileRouter.POST("/size", baseApi.Size)
|
||||
fileRouter.GET("/ws", baseApi.Ws)
|
||||
|
@ -25,6 +25,7 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.POST("/port/update", baseApi.UpdatePort)
|
||||
settingRouter.POST("/ssl/update", baseApi.UpdateSSL)
|
||||
settingRouter.GET("/ssl/info", baseApi.LoadFromCert)
|
||||
settingRouter.POST("/ssl/download", baseApi.DownloadSSL)
|
||||
settingRouter.POST("/password/update", baseApi.UpdatePassword)
|
||||
settingRouter.GET("/time/option", baseApi.LoadTimeZone)
|
||||
settingRouter.POST("/time/sync", baseApi.SyncTime)
|
||||
|
@ -5093,48 +5093,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/download/bypath": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载指定文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Download file with path",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.FilePath"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "Download file [path]",
|
||||
"formatZH": "下载文件 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/mode": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -8823,6 +8781,25 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/ssl/download": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载证书",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Download system cert",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/ssl/info": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -12520,17 +12497,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.FilePath": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.FirewallBaseInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -5086,48 +5086,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/download/bypath": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载指定文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"File"
|
||||
],
|
||||
"summary": "Download file with path",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.FilePath"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"path"
|
||||
],
|
||||
"formatEN": "Download file [path]",
|
||||
"formatZH": "下载文件 [path]",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/mode": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -8816,6 +8774,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/ssl/download": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "下载证书",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Download system cert",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/ssl/info": {
|
||||
"get": {
|
||||
"security": [
|
||||
@ -12513,17 +12490,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.FilePath": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"path"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.FirewallBaseInfo": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -747,13 +747,6 @@ definitions:
|
||||
- fileName
|
||||
- source
|
||||
type: object
|
||||
dto.FilePath:
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
dto.FirewallBaseInfo:
|
||||
properties:
|
||||
name:
|
||||
@ -7084,33 +7077,6 @@ paths:
|
||||
formatEN: Download file [name]
|
||||
formatZH: 下载文件 [name]
|
||||
paramKeys: []
|
||||
/files/download/bypath:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 下载指定文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.FilePath'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Download file with path
|
||||
tags:
|
||||
- File
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys:
|
||||
- path
|
||||
formatEN: Download file [path]
|
||||
formatZH: 下载文件 [path]
|
||||
paramKeys: []
|
||||
/files/mode:
|
||||
post:
|
||||
consumes:
|
||||
@ -9454,6 +9420,17 @@ paths:
|
||||
summary: Page system snapshot
|
||||
tags:
|
||||
- System Setting
|
||||
/settings/ssl/download:
|
||||
post:
|
||||
description: 下载证书
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Download system cert
|
||||
tags:
|
||||
- System Setting
|
||||
/settings/ssl/info:
|
||||
get:
|
||||
description: 获取证书信息
|
||||
|
@ -38,8 +38,11 @@ export const updateStatus = (params: Cronjob.UpdateStatus) => {
|
||||
return http.post(`cronjobs/status`, params);
|
||||
};
|
||||
|
||||
export const download = (params: Cronjob.Download) => {
|
||||
return http.post<string>(`cronjobs/download`, params);
|
||||
export const downloadRecordCheck = (params: Cronjob.Download) => {
|
||||
return http.post<string>(`cronjobs/download`, params, 40000);
|
||||
};
|
||||
export const downloadRecord = (params: Cronjob.Download) => {
|
||||
return http.download<BlobPart>(`cronjobs/download`, params, { responseType: 'blob', timeout: 40000 });
|
||||
};
|
||||
|
||||
export const handleOnce = (id: number) => {
|
||||
|
@ -79,10 +79,6 @@ export const DownloadFile = (params: File.FileDownload) => {
|
||||
return http.download<BlobPart>('files/download', params, { responseType: 'blob', timeout: 20000 });
|
||||
};
|
||||
|
||||
export const DownloadByPath = (path: string) => {
|
||||
return http.download<BlobPart>('files/download/bypath', { path: path }, { responseType: 'blob', timeout: 40000 });
|
||||
};
|
||||
|
||||
export const ComputeDirSize = (params: File.DirSizeReq) => {
|
||||
return http.post<File.DirSizeRes>('files/size', params);
|
||||
};
|
||||
|
@ -30,6 +30,9 @@ export const updateSSL = (param: Setting.SSLUpdate) => {
|
||||
export const loadSSLInfo = () => {
|
||||
return http.get<Setting.SSLInfo>(`/settings/ssl/info`);
|
||||
};
|
||||
export const downloadSSL = () => {
|
||||
return http.download<any>(`settings/ssl/download`);
|
||||
};
|
||||
|
||||
export const handleExpired = (param: Setting.PasswordUpdate) => {
|
||||
return http.post(`/settings/expired/handle`, param);
|
||||
|
@ -358,11 +358,18 @@
|
||||
import { onBeforeUnmount, reactive, ref } from 'vue';
|
||||
import { Cronjob } from '@/api/interface/cronjob';
|
||||
import { loadZero } from '@/utils/util';
|
||||
import { searchRecords, download, handleOnce, updateStatus, cleanRecords, getRecordLog } from '@/api/modules/cronjob';
|
||||
import {
|
||||
searchRecords,
|
||||
downloadRecord,
|
||||
handleOnce,
|
||||
updateStatus,
|
||||
cleanRecords,
|
||||
getRecordLog,
|
||||
downloadRecordCheck,
|
||||
} from '@/api/modules/cronjob';
|
||||
import { dateFormat } from '@/utils/util';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
import { DownloadByPath } from '@/api/modules/files';
|
||||
import { Codemirror } from 'vue-codemirror';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
@ -562,8 +569,8 @@ const onDownload = async (record: any, backupID: number) => {
|
||||
recordID: record.id,
|
||||
backupAccountID: backupID,
|
||||
};
|
||||
await download(params).then(async (res) => {
|
||||
const file = await DownloadByPath(res.data);
|
||||
await downloadRecordCheck(params).then(async () => {
|
||||
const file = await downloadRecord(params);
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([file]));
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
|
@ -107,8 +107,7 @@ import { ListSSL } from '@/api/modules/website';
|
||||
import { reactive, ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { updateSSL } from '@/api/modules/setting';
|
||||
import { DownloadByPath } from '@/api/modules/files';
|
||||
import { downloadSSL, updateSSL } from '@/api/modules/setting';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||
import { Setting } from '@/api/interface/setting';
|
||||
@ -178,14 +177,15 @@ const changeSSl = (sslid: number) => {
|
||||
};
|
||||
|
||||
const onDownload = async () => {
|
||||
const file = await DownloadByPath(form.rootPath);
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([file]));
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = downloadUrl;
|
||||
a.download = 'server.crt';
|
||||
const event = new MouseEvent('click');
|
||||
a.dispatchEvent(event);
|
||||
await downloadSSL().then(async (file) => {
|
||||
const downloadUrl = window.URL.createObjectURL(new Blob([file]));
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none';
|
||||
a.href = downloadUrl;
|
||||
a.download = 'server.crt';
|
||||
const event = new MouseEvent('click');
|
||||
a.dispatchEvent(event);
|
||||
});
|
||||
};
|
||||
|
||||
const onSaveSSL = async (formEl: FormInstance | undefined) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user