mirror of
https://github.com/Forceu/Gokapi.git
synced 2026-01-03 15:29:33 -06:00
Breaking: Make API output less verbose #63, fixed hotlink not working with "duplicate" API call, added option to change filename with duplicate API call
This commit is contained in:
@@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
// File is a struct used for saving information about an uploaded file
|
||||
@@ -25,6 +26,26 @@ type File struct {
|
||||
RequiresClientSideDecryption bool `json:"RequiresClientSideDecryption"`
|
||||
}
|
||||
|
||||
// FileApiOutput will be displayed for public outputs from the ID, hiding sensitive information
|
||||
type FileApiOutput struct {
|
||||
Id string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
Size string `json:"Size"`
|
||||
SHA256 string `json:"SHA256"`
|
||||
HotlinkId string `json:"HotlinkId"`
|
||||
ContentType string `json:"ContentType"`
|
||||
ExpireAt int64 `json:"ExpireAt"`
|
||||
ExpireAtString string `json:"ExpireAtString"`
|
||||
DownloadsRemaining int `json:"DownloadsRemaining"`
|
||||
DownloadCount int `json:"DownloadCount"`
|
||||
UnlimitedDownloads bool `json:"UnlimitedDownloads"`
|
||||
UnlimitedTime bool `json:"UnlimitedTime"`
|
||||
RequiresClientSideDecryption bool `json:"RequiresClientSideDecryption"`
|
||||
IsEncrypted bool `json:"IsEncrypted"`
|
||||
IsPasswordProtected bool `json:"IsPasswordProtected"`
|
||||
IsSavedOnLocalStorage bool `json:"IsSavedOnLocalStorage"`
|
||||
}
|
||||
|
||||
// EncryptionInfo holds information about the encryption used on the file
|
||||
type EncryptionInfo struct {
|
||||
IsEncrypted bool `json:"IsEncrypted"`
|
||||
@@ -32,31 +53,51 @@ type EncryptionInfo struct {
|
||||
Nonce []byte `json:"Nonce"`
|
||||
}
|
||||
|
||||
func (f *File) ToFileApiOutput() (FileApiOutput, error) {
|
||||
var result FileApiOutput
|
||||
err := copier.Copy(&result, &f)
|
||||
if err != nil {
|
||||
return FileApiOutput{}, err
|
||||
}
|
||||
result.IsPasswordProtected = f.PasswordHash != ""
|
||||
result.IsEncrypted = f.Encryption.IsEncrypted
|
||||
result.IsSavedOnLocalStorage = f.AwsBucket == ""
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ToJsonResult converts the file info to a json String used for returning a result for an upload
|
||||
func (f *File) ToJsonResult(serverUrl string) string {
|
||||
info, err := f.ToFileApiOutput()
|
||||
if err != nil {
|
||||
return errorAsJson(err)
|
||||
}
|
||||
result := Result{
|
||||
Result: "OK",
|
||||
Url: serverUrl + "d?id=",
|
||||
HotlinkUrl: serverUrl + "hotlink/",
|
||||
GenericHotlinkUrl: serverUrl + "downloadFile?id=",
|
||||
FileInfo: f,
|
||||
FileInfo: info,
|
||||
}
|
||||
bytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return "{\"Result\":\"error\",\"ErrorMessage\":\"" + err.Error() + "\"}"
|
||||
return errorAsJson(err)
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func errorAsJson(err error) string {
|
||||
fmt.Println(err)
|
||||
return "{\"Result\":\"error\",\"ErrorMessage\":\"" + err.Error() + "\"}"
|
||||
}
|
||||
|
||||
// Result is the struct used for the result after an upload
|
||||
// swagger:model UploadResult
|
||||
type Result struct {
|
||||
Result string `json:"Result"`
|
||||
FileInfo *File `json:"FileInfo"`
|
||||
Url string `json:"Url"`
|
||||
HotlinkUrl string `json:"HotlinkUrl"`
|
||||
GenericHotlinkUrl string `json:"GenericHotlinkUrl"`
|
||||
Result string `json:"Result"`
|
||||
FileInfo FileApiOutput `json:"FileInfo"`
|
||||
Url string `json:"Url"`
|
||||
HotlinkUrl string `json:"HotlinkUrl"`
|
||||
GenericHotlinkUrl string `json:"GenericHotlinkUrl"`
|
||||
}
|
||||
|
||||
// DownloadStatus contains current downloads, so they do not get removed during cleanup
|
||||
|
||||
@@ -27,5 +27,5 @@ func TestToJsonResult(t *testing.T) {
|
||||
UnlimitedDownloads: true,
|
||||
UnlimitedTime: true,
|
||||
}
|
||||
test.IsEqualString(t, file.ToJsonResult("serverurl/"), `{"Result":"OK","FileInfo":{"Id":"testId","Name":"testName","Size":"10 B","SHA256":"sha256","ExpireAt":50,"ExpireAtString":"future","DownloadsRemaining":1,"DownloadCount":3,"PasswordHash":"pwhash","HotlinkId":"hotlinkid","ContentType":"text/html","AwsBucket":"test","Encryption":{"IsEncrypted":true,"DecryptionKey":"AQ==","Nonce":"Ag=="},"UnlimitedDownloads":true,"UnlimitedTime":true,"RequiresClientSideDecryption":false},"Url":"serverurl/d?id=","HotlinkUrl":"serverurl/hotlink/","GenericHotlinkUrl":"serverurl/downloadFile?id="}`)
|
||||
test.IsEqualString(t, file.ToJsonResult("serverurl/"), `{"Result":"OK","FileInfo":{"Id":"testId","Name":"testName","Size":"10 B","SHA256":"sha256","HotlinkId":"hotlinkid","ContentType":"text/html","ExpireAt":50,"ExpireAtString":"future","DownloadsRemaining":1,"DownloadCount":3,"UnlimitedDownloads":true,"UnlimitedTime":true,"RequiresClientSideDecryption":false,"IsEncrypted":true,"IsPasswordProtected":true,"IsSavedOnLocalStorage":false},"Url":"serverurl/d?id=","HotlinkUrl":"serverurl/hotlink/","GenericHotlinkUrl":"serverurl/downloadFile?id="}`)
|
||||
}
|
||||
|
||||
@@ -148,10 +148,11 @@ const (
|
||||
ParamExpiry int = 1 << iota
|
||||
ParamDownloads
|
||||
ParamPassword
|
||||
ParamName
|
||||
)
|
||||
|
||||
// DuplicateFile creates a copy of an existing file with new parameters
|
||||
func DuplicateFile(file models.File, parametersToChange int, fileParameters models.UploadRequest) (models.File, error) {
|
||||
func DuplicateFile(file models.File, parametersToChange int, newFileName string, fileParameters models.UploadRequest) (models.File, error) {
|
||||
var newFile models.File
|
||||
err := copier.Copy(&newFile, &file)
|
||||
if err != nil {
|
||||
@@ -161,6 +162,7 @@ func DuplicateFile(file models.File, parametersToChange int, fileParameters mode
|
||||
changeExpiry := parametersToChange&ParamExpiry != 0
|
||||
changeDownloads := parametersToChange&ParamDownloads != 0
|
||||
changePassword := parametersToChange&ParamPassword != 0
|
||||
changeName := parametersToChange&ParamName != 0
|
||||
|
||||
if changeExpiry {
|
||||
newFile.ExpireAt = fileParameters.ExpiryTimestamp
|
||||
@@ -174,8 +176,13 @@ func DuplicateFile(file models.File, parametersToChange int, fileParameters mode
|
||||
if changePassword {
|
||||
newFile.PasswordHash = configuration.HashPassword(fileParameters.Password, true)
|
||||
}
|
||||
if changeName {
|
||||
newFile.Name = newFileName
|
||||
}
|
||||
|
||||
newFile.Id = createNewId()
|
||||
newFile.DownloadCount = 0
|
||||
addHotlink(&file)
|
||||
|
||||
database.SaveMetaData(newFile)
|
||||
return newFile, nil
|
||||
|
||||
@@ -333,7 +333,7 @@ func TestDuplicateFile(t *testing.T) {
|
||||
retrievedFile.DownloadCount = 5
|
||||
database.SaveMetaData(retrievedFile)
|
||||
|
||||
newFile, err := DuplicateFile(retrievedFile, 0, models.UploadRequest{})
|
||||
newFile, err := DuplicateFile(retrievedFile, 0, "123", models.UploadRequest{})
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -341,6 +341,7 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
uploadRequest := models.UploadRequest{
|
||||
AllowedDownloads: 5,
|
||||
@@ -351,7 +352,7 @@ func TestDuplicateFile(t *testing.T) {
|
||||
UnlimitedTime: true,
|
||||
}
|
||||
|
||||
newFile, err = DuplicateFile(retrievedFile, 0, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, 0, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -359,8 +360,19 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamExpiry, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamName, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
test.IsEqualInt64(t, newFile.ExpireAt, 2147483600)
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "123")
|
||||
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamExpiry, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -368,8 +380,9 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, true)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamDownloads, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamDownloads, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 5)
|
||||
@@ -377,8 +390,9 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, true)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamPassword, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamPassword, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -386,9 +400,10 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsNotEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
retrievedFile.PasswordHash = "ahash"
|
||||
newFile, err = DuplicateFile(retrievedFile, 0, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, 0, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -396,9 +411,10 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "ahash")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
uploadRequest.Password = ""
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamPassword, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamPassword, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 1)
|
||||
@@ -406,9 +422,10 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, false)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, false)
|
||||
test.IsEqualString(t, newFile.Name, "test.dat")
|
||||
|
||||
uploadRequest.Password = "123"
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamExpiry|ParamPassword|ParamDownloads, uploadRequest)
|
||||
newFile, err = DuplicateFile(retrievedFile, ParamExpiry|ParamPassword|ParamDownloads|ParamName, "123", uploadRequest)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualInt(t, newFile.DownloadCount, 0)
|
||||
test.IsEqualInt(t, newFile.DownloadsRemaining, 5)
|
||||
@@ -416,6 +433,7 @@ func TestDuplicateFile(t *testing.T) {
|
||||
test.IsNotEqualString(t, newFile.PasswordHash, "")
|
||||
test.IsEqualBool(t, newFile.UnlimitedDownloads, true)
|
||||
test.IsEqualBool(t, newFile.UnlimitedTime, true)
|
||||
test.IsEqualString(t, newFile.Name, "123")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ type DownloadView struct {
|
||||
|
||||
// UploadView contains parameters for the admin menu template
|
||||
type UploadView struct {
|
||||
Items []models.File
|
||||
Items []models.FileApiOutput
|
||||
ApiKeys []models.ApiKey
|
||||
Url string
|
||||
HotlinkUrl string
|
||||
@@ -397,11 +397,13 @@ type UploadView struct {
|
||||
// Converts the globalConfig variable to an UploadView struct to pass the infos to
|
||||
// the admin template
|
||||
func (u *UploadView) convertGlobalConfig(isMainView bool) *UploadView {
|
||||
var result []models.File
|
||||
var result []models.FileApiOutput
|
||||
var resultApi []models.ApiKey
|
||||
if isMainView {
|
||||
for _, element := range database.GetAllMetadata() {
|
||||
result = append(result, element)
|
||||
fileInfo, err := element.ToFileApiOutput()
|
||||
helper.Check(err)
|
||||
result = append(result, fileInfo)
|
||||
}
|
||||
sort.Slice(result[:], func(i, j int) bool {
|
||||
if result[i].ExpireAt == result[j].ExpireAt {
|
||||
|
||||
@@ -88,11 +88,13 @@ func deleteFile(w http.ResponseWriter, request apiRequest) {
|
||||
}
|
||||
|
||||
func list(w http.ResponseWriter) {
|
||||
var validFiles []models.File
|
||||
var validFiles []models.FileApiOutput
|
||||
timeNow := time.Now().Unix()
|
||||
for _, element := range database.GetAllMetadata() {
|
||||
if !storage.IsExpiredFile(element, timeNow) {
|
||||
validFiles = append(validFiles, element)
|
||||
file, err := element.ToFileApiOutput()
|
||||
helper.Check(err)
|
||||
validFiles = append(validFiles, file)
|
||||
}
|
||||
}
|
||||
result, err := json.Marshal(validFiles)
|
||||
@@ -120,35 +122,38 @@ func duplicateFile(w http.ResponseWriter, request apiRequest) {
|
||||
sendError(w, http.StatusBadRequest, "Invalid id provided.")
|
||||
return
|
||||
}
|
||||
uploadRequest, paramsToChange, err := apiRequestToUploadRequest(request.request)
|
||||
uploadRequest, paramsToChange, filename, err := apiRequestToUploadRequest(request.request)
|
||||
if err != nil {
|
||||
sendError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
newFile, err := storage.DuplicateFile(file, paramsToChange, uploadRequest)
|
||||
newFile, err := storage.DuplicateFile(file, paramsToChange, filename, uploadRequest)
|
||||
if err != nil {
|
||||
sendError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
result, err := json.Marshal(newFile)
|
||||
publicOutput, err := newFile.ToFileApiOutput()
|
||||
helper.Check(err)
|
||||
result, err := json.Marshal(publicOutput)
|
||||
helper.Check(err)
|
||||
_, _ = w.Write(result)
|
||||
}
|
||||
|
||||
func apiRequestToUploadRequest(request *http.Request) (models.UploadRequest, int, error) {
|
||||
func apiRequestToUploadRequest(request *http.Request) (models.UploadRequest, int, string, error) {
|
||||
paramsToChange := 0
|
||||
allowedDownloads := 0
|
||||
daysExpiry := 0
|
||||
unlimitedTime := false
|
||||
unlimitedDownloads := false
|
||||
password := ""
|
||||
fileName := ""
|
||||
var err error
|
||||
|
||||
if request.Form.Get("allowedDownloads") != "" {
|
||||
paramsToChange = paramsToChange | storage.ParamDownloads
|
||||
allowedDownloads, err = strconv.Atoi(request.Form.Get("allowedDownloads"))
|
||||
if err != nil {
|
||||
return models.UploadRequest{}, 0, err
|
||||
return models.UploadRequest{}, 0, "", err
|
||||
}
|
||||
if allowedDownloads == 0 {
|
||||
unlimitedDownloads = true
|
||||
@@ -159,7 +164,7 @@ func apiRequestToUploadRequest(request *http.Request) (models.UploadRequest, int
|
||||
paramsToChange = paramsToChange | storage.ParamExpiry
|
||||
daysExpiry, err = strconv.Atoi(request.Form.Get("expiryDays"))
|
||||
if err != nil {
|
||||
return models.UploadRequest{}, 0, err
|
||||
return models.UploadRequest{}, 0, "", err
|
||||
}
|
||||
if daysExpiry == 0 {
|
||||
unlimitedTime = true
|
||||
@@ -171,6 +176,11 @@ func apiRequestToUploadRequest(request *http.Request) (models.UploadRequest, int
|
||||
password = request.Form.Get("password")
|
||||
}
|
||||
|
||||
if request.Form.Get("filename") != "" {
|
||||
paramsToChange = paramsToChange | storage.ParamName
|
||||
fileName = request.Form.Get("filename")
|
||||
}
|
||||
|
||||
return models.UploadRequest{
|
||||
AllowedDownloads: allowedDownloads,
|
||||
Expiry: daysExpiry,
|
||||
@@ -178,7 +188,7 @@ func apiRequestToUploadRequest(request *http.Request) (models.UploadRequest, int
|
||||
UnlimitedDownload: unlimitedDownloads,
|
||||
Password: password,
|
||||
ExpiryTimestamp: time.Now().Add(time.Duration(daysExpiry) * time.Hour * 24).Unix(),
|
||||
}, paramsToChange, nil
|
||||
}, paramsToChange, fileName, nil
|
||||
}
|
||||
|
||||
func isAuthorisedForApi(w http.ResponseWriter, request apiRequest) bool {
|
||||
|
||||
@@ -192,7 +192,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
test.IsEqualString(t, result.Result, "OK")
|
||||
test.IsEqualString(t, result.FileInfo.Size, "3 B")
|
||||
test.IsEqualInt(t, result.FileInfo.DownloadsRemaining, 200)
|
||||
test.IsNotEqualString(t, result.FileInfo.PasswordHash, "")
|
||||
test.IsEqualBool(t, result.FileInfo.IsPasswordProtected, true)
|
||||
test.IsEqualString(t, result.Url, "http://127.0.0.1:53843/d?id=")
|
||||
newFileId := result.FileInfo.Id
|
||||
|
||||
@@ -238,7 +238,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication := models.File{}
|
||||
resultDuplication := models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
@@ -247,7 +247,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
test.IsEqualBool(t, resultDuplication.UnlimitedTime, false)
|
||||
test.IsEqualBool(t, resultDuplication.UnlimitedDownloads, false)
|
||||
test.IsEqualInt(t, resultDuplication.DownloadCount, 0)
|
||||
test.IsEqualString(t, resultDuplication.PasswordHash, "")
|
||||
test.IsEqualBool(t, resultDuplication.IsPasswordProtected, false)
|
||||
|
||||
data = url.Values{}
|
||||
data.Set("id", newFileId)
|
||||
@@ -259,7 +259,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
@@ -277,7 +277,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
@@ -318,7 +318,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
@@ -335,7 +335,7 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
@@ -352,12 +352,12 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
test.IsNil(t, err)
|
||||
test.IsNotEqualString(t, resultDuplication.PasswordHash, "")
|
||||
test.IsEqualBool(t, resultDuplication.IsPasswordProtected, true)
|
||||
|
||||
data = url.Values{}
|
||||
data.Set("id", newFileId)
|
||||
@@ -368,12 +368,12 @@ func TestUploadAndDuplication(t *testing.T) {
|
||||
{Name: "Content-type", Value: "application/x-www-form-urlencoded"}},
|
||||
strings.NewReader(data.Encode()))
|
||||
Process(w, r, maxMemory)
|
||||
resultDuplication = models.File{}
|
||||
resultDuplication = models.FileApiOutput{}
|
||||
response, err = io.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
err = json.Unmarshal(response, &resultDuplication)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualString(t, resultDuplication.PasswordHash, "")
|
||||
test.IsEqualBool(t, resultDuplication.IsPasswordProtected, false)
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
|
||||
@@ -217,12 +217,23 @@
|
||||
"File": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ContentType": {
|
||||
"Id": {
|
||||
"type": "string"
|
||||
},
|
||||
"DownloadsRemaining": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
"Name": {
|
||||
"type": "string"
|
||||
},
|
||||
"Size": {
|
||||
"type": "string"
|
||||
},
|
||||
"SHA256": {
|
||||
"type": "string"
|
||||
},
|
||||
"HotlinkId": {
|
||||
"type": "string"
|
||||
},
|
||||
"ContentType": {
|
||||
"type": "string"
|
||||
},
|
||||
"ExpireAt": {
|
||||
"type": "integer",
|
||||
@@ -231,23 +242,31 @@
|
||||
"ExpireAtString": {
|
||||
"type": "string"
|
||||
},
|
||||
"HotlinkId": {
|
||||
"type": "string"
|
||||
"DownloadsRemaining": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"Id": {
|
||||
"type": "string"
|
||||
"DownloadCount": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"Name": {
|
||||
"type": "string"
|
||||
"UnlimitedDownloads": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"PasswordHash": {
|
||||
"type": "string"
|
||||
"UnlimitedTime": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"SHA256": {
|
||||
"type": "string"
|
||||
"RequiresClientSideDecryption": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Size": {
|
||||
"type": "string"
|
||||
"IsEncrypted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"IsPasswordProtected": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"IsSavedOnLocalStorage": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"description": "File is a struct used for saving information about an uploaded file",
|
||||
@@ -316,11 +335,15 @@
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "Password for this file to be set. No password will be used if empty-"
|
||||
"description": "Password for this file to be set. No password will be used if empty."
|
||||
},
|
||||
"originalPassword": {
|
||||
"type": "boolean",
|
||||
"description": "Set to true to use original password. Field \"password\" will be ignored if set."
|
||||
},
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"description": "Sets a new filename. Filename will be unchanged if empty."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ function addRow(jsonText) {
|
||||
let cellButtons = row.insertCell(6);
|
||||
let lockIcon = "";
|
||||
|
||||
if (item.PasswordHash !== "") {
|
||||
if (item.IsPasswordProtected === true) {
|
||||
lockIcon = " 🔒";
|
||||
}
|
||||
cellFilename.innerText = item.Name;
|
||||
@@ -113,7 +113,7 @@ function addRow(jsonText) {
|
||||
if (item.HotlinkId !== "") {
|
||||
buttons = buttons + '<button type="button" data-clipboard-text="' + jsonObject.HotlinkUrl + item.HotlinkId + '" class="copyurl btn btn-outline-light btn-sm">Copy Hotlink</button> ';
|
||||
} else {
|
||||
if (item.RequiresClientSideDecryption === false && item.PasswordHash === "") {
|
||||
if (item.RequiresClientSideDecryption === false && item.IsPasswordProtected === false) {
|
||||
buttons = buttons + '<button type="button" data-clipboard-text="' + jsonObject.GenericHotlinkUrl + item.Id + '" class="copyurl btn btn-outline-light btn-sm">Copy Hotlink</button> ';
|
||||
} else {
|
||||
buttons = buttons + '<button type="button"class="copyurl btn btn-outline-light btn-sm disabled">Copy Hotlink</button> ';
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
<td scope="col">{{ .ExpireAtString }}</td>
|
||||
{{ end }}
|
||||
<td scope="col">{{ .DownloadCount }}</td>
|
||||
<td scope="col"><a target="_blank" href="{{ $.Url }}{{ .Id }}">{{ $.Url }}{{ .Id }}</a>{{ if ne .PasswordHash "" }} 🔒{{ end }}</td>
|
||||
<td scope="col"><a target="_blank" href="{{ $.Url }}{{ .Id }}">{{ $.Url }}{{ .Id }}</a>{{ if .IsPasswordProtected }} 🔒{{ end }}</td>
|
||||
<td scope="col"><button type="button" data-clipboard-text="{{ $.Url }}{{ .Id }}" class="copyurl btn btn-outline-light btn-sm">Copy URL</button>
|
||||
{{ if ne .HotlinkId "" }}
|
||||
<button type="button" data-clipboard-text="{{ $.HotlinkUrl }}{{ .HotlinkId }}" class="copyurl btn btn-outline-light btn-sm">Copy Hotlink</button>
|
||||
{{ else }}
|
||||
{{ if and (not .RequiresClientSideDecryption) (eq .PasswordHash "") }}
|
||||
{{ if and (not .IsPasswordProtected) (not .RequiresClientSideDecryption) }}
|
||||
<button type="button" data-clipboard-text="{{ $.GenericHotlinkUrl }}{{ .Id }}" class="copyurl btn btn-outline-light btn-sm">Copy Hotlink</button>
|
||||
{{ else }}
|
||||
<button type="button"class="copyurl btn btn-outline-light btn-sm disabled">Copy Hotlink</button>
|
||||
@@ -95,7 +95,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="./js/admin.js?v=11"></script>
|
||||
<script src="./js/admin.js?v=12"></script>
|
||||
<script>
|
||||
Dropzone.options.uploaddropzone["maxFilesize"] = {{ .MaxFileSize }};
|
||||
Dropzone.options.uploaddropzone["dictDefaultMessage"] = "Drop files, paste or click here to upload";
|
||||
|
||||
57
openapi.json
57
openapi.json
@@ -217,12 +217,23 @@
|
||||
"File": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ContentType": {
|
||||
"Id": {
|
||||
"type": "string"
|
||||
},
|
||||
"DownloadsRemaining": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
"Name": {
|
||||
"type": "string"
|
||||
},
|
||||
"Size": {
|
||||
"type": "string"
|
||||
},
|
||||
"SHA256": {
|
||||
"type": "string"
|
||||
},
|
||||
"HotlinkId": {
|
||||
"type": "string"
|
||||
},
|
||||
"ContentType": {
|
||||
"type": "string"
|
||||
},
|
||||
"ExpireAt": {
|
||||
"type": "integer",
|
||||
@@ -231,23 +242,31 @@
|
||||
"ExpireAtString": {
|
||||
"type": "string"
|
||||
},
|
||||
"HotlinkId": {
|
||||
"type": "string"
|
||||
"DownloadsRemaining": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"Id": {
|
||||
"type": "string"
|
||||
"DownloadCount": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"Name": {
|
||||
"type": "string"
|
||||
"UnlimitedDownloads": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"PasswordHash": {
|
||||
"type": "string"
|
||||
"UnlimitedTime": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"SHA256": {
|
||||
"type": "string"
|
||||
"RequiresClientSideDecryption": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Size": {
|
||||
"type": "string"
|
||||
"IsEncrypted": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"IsPasswordProtected": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"IsSavedOnLocalStorage": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"description": "File is a struct used for saving information about an uploaded file",
|
||||
@@ -316,11 +335,15 @@
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "Password for this file to be set. No password will be used if empty-"
|
||||
"description": "Password for this file to be set. No password will be used if empty."
|
||||
},
|
||||
"originalPassword": {
|
||||
"type": "boolean",
|
||||
"description": "Set to true to use original password. Field \"password\" will be ignored if set."
|
||||
},
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"description": "Sets a new filename. Filename will be unchanged if empty."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user