mirror of
https://github.com/Forceu/Gokapi.git
synced 2026-03-01 13:31:00 -06:00
Refactoring, enhancing unit tests
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Gokapi
|
||||
[](https://goreportcard.com/report/github.com/forceu/gokapi)
|
||||
<a href='https://github.com/jpoles1/gopherbadger' target='_blank'></a>
|
||||
<a href='https://github.com/jpoles1/gopherbadger' target='_blank'></a>
|
||||
[](https://hub.docker.com/r/f0rc3/gokapi/)
|
||||
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
|
||||
// Version is the current version in readable form.
|
||||
// The go generate call below needs to be modified as well
|
||||
const Version = "1.1.4-dev"
|
||||
const Version = "1.2.0-dev"
|
||||
|
||||
//go:generate sh "../../build/setVersionTemplate.sh" "1.1.4-dev"
|
||||
//go:generate sh "../../build/setVersionTemplate.sh" "1.2.0-dev"
|
||||
|
||||
// Main routine that is called on startup
|
||||
func main() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"Gokapi/pkg/test"
|
||||
"Gokapi/internal/test"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -7,14 +7,12 @@ Loading and saving of the persistent configuration
|
||||
import (
|
||||
"Gokapi/internal/environment"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/internal/webserver/sessionstructure"
|
||||
"Gokapi/internal/models"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -35,30 +33,31 @@ var Environment environment.Environment
|
||||
var ServerSettings Configuration
|
||||
|
||||
// Version of the configuration structure. Used for upgrading
|
||||
const currentConfigVersion = 5
|
||||
const currentConfigVersion = 6
|
||||
|
||||
// For locking the Files variable
|
||||
var mutex sync.Mutex
|
||||
// For locking this object to prevent race conditions
|
||||
var mutexSessions sync.Mutex
|
||||
|
||||
// Configuration is a struct that contains the global configuration
|
||||
type Configuration struct {
|
||||
Port string `json:"Port"`
|
||||
AdminName string `json:"AdminName"`
|
||||
AdminPassword string `json:"AdminPassword"`
|
||||
ServerUrl string `json:"ServerUrl"`
|
||||
DefaultDownloads int `json:"DefaultDownloads"`
|
||||
DefaultExpiry int `json:"DefaultExpiry"`
|
||||
DefaultPassword string `json:"DefaultPassword"`
|
||||
RedirectUrl string `json:"RedirectUrl"`
|
||||
Sessions map[string]sessionstructure.Session `json:"Sessions"`
|
||||
Files map[string]filestructure.File `json:"Files"`
|
||||
Hotlinks map[string]filestructure.Hotlink `json:"Hotlinks"`
|
||||
DownloadStatus map[string]filestructure.DownloadStatus `json:"DownloadStatus"`
|
||||
ConfigVersion int `json:"ConfigVersion"`
|
||||
SaltAdmin string `json:"SaltAdmin"`
|
||||
SaltFiles string `json:"SaltFiles"`
|
||||
LengthId int `json:"LengthId"`
|
||||
DataDir string `json:"DataDir"`
|
||||
Port string `json:"Port"`
|
||||
AdminName string `json:"AdminName"`
|
||||
AdminPassword string `json:"AdminPassword"`
|
||||
ServerUrl string `json:"ServerUrl"`
|
||||
DefaultDownloads int `json:"DefaultDownloads"`
|
||||
DefaultExpiry int `json:"DefaultExpiry"`
|
||||
DefaultPassword string `json:"DefaultPassword"`
|
||||
RedirectUrl string `json:"RedirectUrl"`
|
||||
Sessions map[string]models.Session `json:"Sessions"`
|
||||
Files map[string]models.File `json:"Files"`
|
||||
Hotlinks map[string]models.Hotlink `json:"Hotlinks"`
|
||||
DownloadStatus map[string]models.DownloadStatus `json:"DownloadStatus"`
|
||||
ApiKeys map[string]models.ApiKey `json:"ApiKeys"`
|
||||
ConfigVersion int `json:"ConfigVersion"`
|
||||
SaltAdmin string `json:"SaltAdmin"`
|
||||
SaltFiles string `json:"SaltFiles"`
|
||||
LengthId int `json:"LengthId"`
|
||||
DataDir string `json:"DataDir"`
|
||||
}
|
||||
|
||||
// Load loads the configuration or creates the folder structure and a default configuration
|
||||
@@ -69,29 +68,25 @@ func Load() {
|
||||
generateDefaultConfig()
|
||||
}
|
||||
file, err := os.Open(Environment.ConfigPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
helper.Check(err)
|
||||
defer file.Close()
|
||||
decoder := json.NewDecoder(file)
|
||||
ServerSettings = Configuration{}
|
||||
err = decoder.Decode(&ServerSettings)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
helper.Check(err)
|
||||
updateConfig()
|
||||
helper.CreateDir(ServerSettings.DataDir)
|
||||
}
|
||||
|
||||
// Lock locks configuration to prevent race conditions (blocking)
|
||||
func Lock() {
|
||||
mutex.Lock()
|
||||
// LockSessions locks sessions to prevent race conditions (blocking)
|
||||
func LockSessions() {
|
||||
mutexSessions.Lock()
|
||||
}
|
||||
|
||||
// UnlockAndSave unlocks and saves the configuration
|
||||
func UnlockAndSave() {
|
||||
// UnlockSessionsAndSave unlocks sessions and saves the configuration
|
||||
func UnlockSessionsAndSave() {
|
||||
Save()
|
||||
mutex.Unlock()
|
||||
mutexSessions.Unlock()
|
||||
}
|
||||
|
||||
// Upgrades the ServerSettings if saved with a previous version
|
||||
@@ -105,18 +100,21 @@ func updateConfig() {
|
||||
}
|
||||
// < v1.1.3
|
||||
if ServerSettings.ConfigVersion < 4 {
|
||||
ServerSettings.Hotlinks = make(map[string]filestructure.Hotlink)
|
||||
ServerSettings.Hotlinks = make(map[string]models.Hotlink)
|
||||
}
|
||||
|
||||
// < v1.1.4
|
||||
if ServerSettings.ConfigVersion < 5 {
|
||||
ServerSettings.LengthId = 15
|
||||
ServerSettings.DownloadStatus = make(map[string]filestructure.DownloadStatus)
|
||||
ServerSettings.DownloadStatus = make(map[string]models.DownloadStatus)
|
||||
for _, file := range ServerSettings.Files {
|
||||
file.ContentType = "application/octet-stream"
|
||||
ServerSettings.Files[file.Id] = file
|
||||
}
|
||||
}
|
||||
// < v1.2.0
|
||||
if ServerSettings.ConfigVersion < 6 {
|
||||
ServerSettings.ApiKeys = make(map[string]models.ApiKey)
|
||||
}
|
||||
|
||||
if ServerSettings.ConfigVersion < currentConfigVersion {
|
||||
fmt.Println("Successfully upgraded database")
|
||||
@@ -158,9 +156,11 @@ func generateDefaultConfig() {
|
||||
DefaultDownloads: 1,
|
||||
DefaultExpiry: 14,
|
||||
RedirectUrl: redirect,
|
||||
Files: make(map[string]filestructure.File),
|
||||
Sessions: make(map[string]sessionstructure.Session),
|
||||
Hotlinks: make(map[string]filestructure.Hotlink),
|
||||
Files: make(map[string]models.File),
|
||||
Sessions: make(map[string]models.Session),
|
||||
Hotlinks: make(map[string]models.Hotlink),
|
||||
ApiKeys: make(map[string]models.ApiKey),
|
||||
DownloadStatus: make(map[string]models.DownloadStatus),
|
||||
ConfigVersion: currentConfigVersion,
|
||||
SaltAdmin: saltAdmin,
|
||||
SaltFiles: saltFiles,
|
||||
|
||||
@@ -3,27 +3,48 @@ package configuration
|
||||
import (
|
||||
"Gokapi/internal/environment"
|
||||
testconfiguration "Gokapi/internal/test"
|
||||
"Gokapi/pkg/test"
|
||||
testconfiguration2 "Gokapi/internal/test/testconfiguration"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testconfiguration.Create(false)
|
||||
testconfiguration2.Create(false)
|
||||
exitVal := m.Run()
|
||||
testconfiguration.Delete()
|
||||
testconfiguration2.Delete()
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
Load()
|
||||
test.IsEqualString(t, Environment.ConfigDir, "test")
|
||||
test.IsEqualString(t, ServerSettings.Port, "127.0.0.1:53843")
|
||||
test.IsEqualString(t, ServerSettings.AdminName, "test")
|
||||
test.IsEqualString(t, ServerSettings.ServerUrl, "http://127.0.0.1:53843/")
|
||||
test.IsEqualString(t, ServerSettings.AdminPassword, "10340aece68aa4fb14507ae45b05506026f276cf")
|
||||
test.IsEqualString(t, HashPassword("testtest", false), "10340aece68aa4fb14507ae45b05506026f276cf")
|
||||
test.IsEqualInt(t, ServerSettings.LengthId, 20)
|
||||
testconfiguration.IsEqualString(t, Environment.ConfigDir, "test")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.Port, "127.0.0.1:53843")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.AdminName, "test")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.ServerUrl, "http://127.0.0.1:53843/")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.AdminPassword, "10340aece68aa4fb14507ae45b05506026f276cf")
|
||||
testconfiguration.IsEqualString(t, HashPassword("testtest", false), "10340aece68aa4fb14507ae45b05506026f276cf")
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.LengthId, 20)
|
||||
}
|
||||
|
||||
func TestMutex(t *testing.T) {
|
||||
finished := make(chan bool)
|
||||
oldValue := ServerSettings.ConfigVersion
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
LockSessions()
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.ConfigVersion, -9)
|
||||
ServerSettings.ConfigVersion = oldValue
|
||||
UnlockSessionsAndSave()
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.ConfigVersion, oldValue)
|
||||
finished <- true
|
||||
}()
|
||||
LockSessions()
|
||||
ServerSettings.ConfigVersion = -9
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.ConfigVersion, -9)
|
||||
UnlockSessionsAndSave()
|
||||
<-finished
|
||||
}
|
||||
|
||||
func TestCreateNewConfig(t *testing.T) {
|
||||
@@ -36,112 +57,121 @@ func TestCreateNewConfig(t *testing.T) {
|
||||
os.Setenv("GOKAPI_SALT_ADMIN", "salt123")
|
||||
os.Setenv("GOKAPI_LOCALHOST", "false")
|
||||
Load()
|
||||
test.IsEqualString(t, Environment.ConfigDir, "test")
|
||||
test.IsEqualString(t, ServerSettings.Port, ":1234")
|
||||
test.IsEqualString(t, ServerSettings.AdminName, "test2")
|
||||
test.IsEqualString(t, ServerSettings.ServerUrl, "http://test.com/")
|
||||
test.IsEqualString(t, ServerSettings.RedirectUrl, "http://test2.com")
|
||||
test.IsEqualString(t, ServerSettings.AdminPassword, "5bbf5684437a4c658d2e0890d784694afb63f715")
|
||||
test.IsEqualString(t, HashPassword("testtest2", false), "5bbf5684437a4c658d2e0890d784694afb63f715")
|
||||
test.IsEqualInt(t, ServerSettings.LengthId, 15)
|
||||
testconfiguration.IsEqualString(t, Environment.ConfigDir, "test")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.Port, ":1234")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.AdminName, "test2")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.ServerUrl, "http://test.com/")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.RedirectUrl, "http://test2.com")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.AdminPassword, "5bbf5684437a4c658d2e0890d784694afb63f715")
|
||||
testconfiguration.IsEqualString(t, HashPassword("testtest2", false), "5bbf5684437a4c658d2e0890d784694afb63f715")
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.LengthId, 15)
|
||||
os.Remove("test/config.json")
|
||||
os.Unsetenv("GOKAPI_SALT_ADMIN")
|
||||
Load()
|
||||
testconfiguration.IsEqualInt(t, len(ServerSettings.SaltAdmin), 30)
|
||||
testconfiguration.IsNotEqualString(t, ServerSettings.SaltAdmin, "eefwkjqweduiotbrkl##$2342brerlk2321")
|
||||
os.Unsetenv("GOKAPI_USERNAME")
|
||||
os.Unsetenv("GOKAPI_PASSWORD")
|
||||
os.Unsetenv("GOKAPI_PORT")
|
||||
os.Unsetenv("GOKAPI_EXTERNAL_URL")
|
||||
os.Unsetenv("GOKAPI_REDIRECT_URL")
|
||||
os.Unsetenv("GOKAPI_SALT_ADMIN")
|
||||
os.Unsetenv("GOKAPI_LOCALHOST")
|
||||
}
|
||||
|
||||
func TestUpgradeDb(t *testing.T) {
|
||||
testconfiguration2.WriteUpgradeConfigFile()
|
||||
Load()
|
||||
ServerSettings.ConfigVersion = 0
|
||||
updateConfig()
|
||||
testconfiguration.IsEqualString(t, ServerSettings.SaltAdmin, "eefwkjqweduiotbrkl##$2342brerlk2321")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.SaltFiles, "P1UI5sRNDwuBgOvOYhNsmucZ2pqo4KEvOoqqbpdu")
|
||||
testconfiguration.IsEqualString(t, ServerSettings.DataDir, Environment.DataDir)
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.LengthId, 15)
|
||||
testconfiguration.IsEqualBool(t, ServerSettings.Hotlinks == nil, false)
|
||||
testconfiguration.IsEqualBool(t, ServerSettings.DownloadStatus == nil, false)
|
||||
testconfiguration.IsEqualString(t, ServerSettings.Files["MgXJLe4XLfpXcL12ec4i"].ContentType, "application/octet-stream")
|
||||
testconfiguration.IsEqualInt(t, ServerSettings.ConfigVersion, currentConfigVersion)
|
||||
testconfiguration2.Create(false)
|
||||
Load()
|
||||
test.IsEqualString(t, ServerSettings.SaltAdmin, "eefwkjqweduiotbrkl##$2342brerlk2321")
|
||||
test.IsEqualInt(t, ServerSettings.LengthId, 15)
|
||||
test.IsEqualInt(t, ServerSettings.ConfigVersion, currentConfigVersion)
|
||||
}
|
||||
|
||||
func TestAskForUsername(t *testing.T) {
|
||||
original := testconfiguration.StartMockInputStdin(t, "admin")
|
||||
original := testconfiguration2.StartMockInputStdin("admin")
|
||||
output := askForUsername()
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
test.IsEqualString(t, output, "admin")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
testconfiguration.IsEqualString(t, output, "admin")
|
||||
}
|
||||
|
||||
func TestIsValidPortNumber(t *testing.T) {
|
||||
test.IsEqualBool(t, isValidPortNumber("invalid"), false)
|
||||
test.IsEqualBool(t, isValidPortNumber("-1"), false)
|
||||
test.IsEqualBool(t, isValidPortNumber("0"), true)
|
||||
test.IsEqualBool(t, isValidPortNumber("100"), true)
|
||||
test.IsEqualBool(t, isValidPortNumber("65353"), true)
|
||||
test.IsEqualBool(t, isValidPortNumber("65354"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("invalid"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("-1"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("0"), true)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("100"), true)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("65353"), true)
|
||||
testconfiguration.IsEqualBool(t, isValidPortNumber("65354"), false)
|
||||
}
|
||||
|
||||
func TestHashPassword(t *testing.T) {
|
||||
test.IsEqualString(t, HashPassword("123", false), "45dcdc57b6a50bd0020fabc958ae254406713559")
|
||||
test.IsEqualString(t, HashPassword("", false), "")
|
||||
test.IsEqualString(t, HashPassword("123", true), "e143a1801faba4c5c6fdc2e823127c988940f72e")
|
||||
testconfiguration.IsEqualString(t, HashPassword("123", false), "423b63a68c68bd7e07b14590927c1e9a473fe035")
|
||||
testconfiguration.IsEqualString(t, HashPassword("", false), "")
|
||||
testconfiguration.IsEqualString(t, HashPassword("123", true), "7b30508aa9b233ab4b8a11b2af5816bdb58ca3e7")
|
||||
}
|
||||
|
||||
func TestIsValidUrl(t *testing.T) {
|
||||
test.IsEqualBool(t, isValidUrl("http://"), false)
|
||||
test.IsEqualBool(t, isValidUrl("https://"), false)
|
||||
test.IsEqualBool(t, isValidUrl("invalid"), false)
|
||||
test.IsEqualBool(t, isValidUrl("http://abc"), true)
|
||||
test.IsEqualBool(t, isValidUrl("https://abc"), true)
|
||||
testconfiguration.IsEqualBool(t, isValidUrl("http://"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidUrl("https://"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidUrl("invalid"), false)
|
||||
testconfiguration.IsEqualBool(t, isValidUrl("http://abc"), true)
|
||||
testconfiguration.IsEqualBool(t, isValidUrl("https://abc"), true)
|
||||
}
|
||||
|
||||
func TestAddTrailingSlash(t *testing.T) {
|
||||
test.IsEqualString(t, addTrailingSlash("abc"), "abc/")
|
||||
test.IsEqualString(t, addTrailingSlash("abc/"), "abc/")
|
||||
test.IsEqualString(t, addTrailingSlash("/"), "/")
|
||||
test.IsEqualString(t, addTrailingSlash(""), "/")
|
||||
testconfiguration.IsEqualString(t, addTrailingSlash("abc"), "abc/")
|
||||
testconfiguration.IsEqualString(t, addTrailingSlash("abc/"), "abc/")
|
||||
testconfiguration.IsEqualString(t, addTrailingSlash("/"), "/")
|
||||
testconfiguration.IsEqualString(t, addTrailingSlash(""), "/")
|
||||
}
|
||||
|
||||
func TestAskForRedirect(t *testing.T) {
|
||||
original := testconfiguration.StartMockInputStdin(t, "")
|
||||
original := testconfiguration2.StartMockInputStdin("")
|
||||
url := askForRedirect()
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
test.IsEqualString(t, url, "https://github.com/Forceu/Gokapi/")
|
||||
original = testconfiguration.StartMockInputStdin(t, "https://test.com")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
testconfiguration.IsEqualString(t, url, "https://github.com/Forceu/Gokapi/")
|
||||
original = testconfiguration2.StartMockInputStdin("https://test.com")
|
||||
url = askForRedirect()
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
test.IsEqualString(t, url, "https://test.com")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
testconfiguration.IsEqualString(t, url, "https://test.com")
|
||||
}
|
||||
|
||||
func TestAskForLocalOnly(t *testing.T) {
|
||||
environment.IsDocker = "true"
|
||||
test.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
testconfiguration.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
environment.IsDocker = "false"
|
||||
original := testconfiguration.StartMockInputStdin(t, "")
|
||||
test.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original = testconfiguration.StartMockInputStdin(t, "no")
|
||||
test.IsEqualString(t, askForLocalOnly(), environment.IsFalse)
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original = testconfiguration.StartMockInputStdin(t, "yes")
|
||||
test.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original = testconfiguration.StartMockInputStdin(t, "n")
|
||||
test.IsEqualString(t, askForLocalOnly(), environment.IsFalse)
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original := testconfiguration2.StartMockInputStdin("")
|
||||
testconfiguration.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
original = testconfiguration2.StartMockInputStdin("no")
|
||||
testconfiguration.IsEqualString(t, askForLocalOnly(), environment.IsFalse)
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
original = testconfiguration2.StartMockInputStdin("yes")
|
||||
testconfiguration.IsEqualString(t, askForLocalOnly(), environment.IsTrue)
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
original = testconfiguration2.StartMockInputStdin("n")
|
||||
testconfiguration.IsEqualString(t, askForLocalOnly(), environment.IsFalse)
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
}
|
||||
|
||||
func TestAskForPort(t *testing.T) {
|
||||
original := testconfiguration.StartMockInputStdin(t, "8000")
|
||||
test.IsEqualString(t, askForPort(), "8000")
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original = testconfiguration.StartMockInputStdin(t, "")
|
||||
test.IsEqualString(t, askForPort(), defaultPort)
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original := testconfiguration2.StartMockInputStdin("8000")
|
||||
testconfiguration.IsEqualString(t, askForPort(), "8000")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
original = testconfiguration2.StartMockInputStdin("")
|
||||
testconfiguration.IsEqualString(t, askForPort(), defaultPort)
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
}
|
||||
func TestAskForUrl(t *testing.T) {
|
||||
original := testconfiguration.StartMockInputStdin(t, "https://test.com")
|
||||
test.IsEqualString(t, askForUrl("1234"), "https://test.com/")
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original = testconfiguration.StartMockInputStdin(t, "")
|
||||
test.IsEqualString(t, askForUrl("1234"), "http://127.0.0.1:1234/")
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
original := testconfiguration2.StartMockInputStdin("https://test.com")
|
||||
testconfiguration.IsEqualString(t, askForUrl("1234"), "https://test.com/")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
original = testconfiguration2.StartMockInputStdin("")
|
||||
testconfiguration.IsEqualString(t, askForUrl("1234"), "http://127.0.0.1:1234/")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package downloadstatus
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/internal/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SetDownload creates a new DownloadStatus struct and returns its Id
|
||||
func SetDownload(file filestructure.File) string {
|
||||
func SetDownload(file models.File) string {
|
||||
status := newDownloadStatus(file)
|
||||
configuration.ServerSettings.DownloadStatus[status.Id] = status
|
||||
return status.Id
|
||||
@@ -30,8 +30,8 @@ func Clean() {
|
||||
}
|
||||
|
||||
// newDownloadStatus initialises the a new DownloadStatus item
|
||||
func newDownloadStatus(file filestructure.File) filestructure.DownloadStatus {
|
||||
s := filestructure.DownloadStatus{
|
||||
func newDownloadStatus(file models.File) models.DownloadStatus {
|
||||
s := models.DownloadStatus{
|
||||
Id: helper.GenerateRandomString(30),
|
||||
FileId: file.Id,
|
||||
ExpireAt: time.Now().Add(24 * time.Hour).Unix(),
|
||||
@@ -40,7 +40,7 @@ func newDownloadStatus(file filestructure.File) filestructure.DownloadStatus {
|
||||
}
|
||||
|
||||
// IsCurrentlyDownloading returns true if file is currently being downloaded
|
||||
func IsCurrentlyDownloading(file filestructure.File) bool {
|
||||
func IsCurrentlyDownloading(file models.File) bool {
|
||||
for _, status := range configuration.ServerSettings.DownloadStatus {
|
||||
if status.FileId == file.Id {
|
||||
if status.ExpireAt > time.Now().Unix() {
|
||||
|
||||
@@ -2,19 +2,19 @@ package downloadstatus
|
||||
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/pkg/test"
|
||||
"Gokapi/internal/models"
|
||||
"Gokapi/internal/test"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var testFile filestructure.File
|
||||
var testFile models.File
|
||||
var statusId string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
configuration.ServerSettings.DownloadStatus = make(map[string]filestructure.DownloadStatus)
|
||||
testFile = filestructure.File{
|
||||
configuration.ServerSettings.DownloadStatus = make(map[string]models.DownloadStatus)
|
||||
testFile = models.File{
|
||||
Id: "test",
|
||||
Name: "testName",
|
||||
Size: "3 B",
|
||||
@@ -28,7 +28,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestNewDownloadStatus(t *testing.T) {
|
||||
status := newDownloadStatus(filestructure.File{Id: "testId"})
|
||||
status := newDownloadStatus(models.File{Id: "testId"})
|
||||
test.IsNotEmpty(t, status.Id)
|
||||
test.IsEqualString(t, status.FileId, "testId")
|
||||
test.IsEqualBool(t, status.ExpireAt > time.Now().Unix(), true)
|
||||
@@ -54,7 +54,7 @@ func TestSetComplete(t *testing.T) {
|
||||
func TestIsCurrentlyDownloading(t *testing.T) {
|
||||
statusId = SetDownload(testFile)
|
||||
test.IsEqualBool(t, IsCurrentlyDownloading(testFile), true)
|
||||
test.IsEqualBool(t, IsCurrentlyDownloading(filestructure.File{Id: "notDownloading"}), false)
|
||||
test.IsEqualBool(t, IsCurrentlyDownloading(models.File{Id: "notDownloading"}), false)
|
||||
}
|
||||
|
||||
func TestClean(t *testing.T) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package environment
|
||||
|
||||
import (
|
||||
"Gokapi/pkg/test"
|
||||
"Gokapi/internal/test"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
@@ -25,4 +25,9 @@ func TestEnvLoad(t *testing.T) {
|
||||
env = New()
|
||||
test.IsEqualString(t, env.WebserverLocalhost, "")
|
||||
os.Setenv("GOKAPI_LENGTH_ID", "15")
|
||||
os.Setenv("GOKAPI_LOCALHOST", "invalid")
|
||||
os.Setenv("GOKAPI_LENGTH_ID", "invalid")
|
||||
env = New()
|
||||
test.IsEqualString(t, env.WebserverLocalhost, "")
|
||||
test.IsEqualInt(t, env.LengthId, -1)
|
||||
}
|
||||
|
||||
@@ -2,35 +2,35 @@ package helper
|
||||
|
||||
import (
|
||||
testconfiguration "Gokapi/internal/test"
|
||||
"Gokapi/pkg/test"
|
||||
testconfiguration2 "Gokapi/internal/test/testconfiguration"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsInArray(t *testing.T) {
|
||||
test.IsEqualBool(t, IsInArray([]string{"test", "test2", "test3"}, "test2"), true)
|
||||
test.IsEqualBool(t, IsInArray([]string{"test", "test2", "test3"}, "invalid"), false)
|
||||
testconfiguration.IsEqualBool(t, IsInArray([]string{"test", "test2", "test3"}, "test2"), true)
|
||||
testconfiguration.IsEqualBool(t, IsInArray([]string{"test", "test2", "test3"}, "invalid"), false)
|
||||
}
|
||||
|
||||
func TestFolderCreation(t *testing.T) {
|
||||
test.IsEqualBool(t, FolderExists("invalid"), false)
|
||||
test.IsEqualBool(t, FileExists("invalid/file"), false)
|
||||
testconfiguration.IsEqualBool(t, FolderExists("invalid"), false)
|
||||
testconfiguration.IsEqualBool(t, FileExists("invalid/file"), false)
|
||||
CreateDir("invalid")
|
||||
test.IsEqualBool(t, FolderExists("invalid"), true)
|
||||
testconfiguration.IsEqualBool(t, FolderExists("invalid"), true)
|
||||
err := ioutil.WriteFile("invalid/file", []byte("test"), 0644)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
test.IsEqualBool(t, FileExists("invalid/file"), true)
|
||||
testconfiguration.IsEqualBool(t, FileExists("invalid/file"), true)
|
||||
os.RemoveAll("invalid")
|
||||
}
|
||||
|
||||
func TestReadLine(t *testing.T) {
|
||||
original := testconfiguration.StartMockInputStdin(t, "test")
|
||||
original := testconfiguration2.StartMockInputStdin("test")
|
||||
output := ReadLine()
|
||||
testconfiguration.StopMockInputStdin(original)
|
||||
test.IsEqualString(t, output, "test")
|
||||
testconfiguration2.StopMockInputStdin(original)
|
||||
testconfiguration.IsEqualString(t, output, "test")
|
||||
}
|
||||
|
||||
func TestGetFileSize(t *testing.T) {
|
||||
@@ -40,12 +40,12 @@ func TestGetFileSize(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
size, _ := GetFileSize(file)
|
||||
test.IsEqualInt(t, int(size), 0)
|
||||
testconfiguration.IsEqualInt(t, int(size), 0)
|
||||
os.WriteFile("testfile", []byte("123"), 0777)
|
||||
size, _ = GetFileSize(file)
|
||||
test.IsEqualInt(t, int(size), 3)
|
||||
testconfiguration.IsEqualInt(t, int(size), 3)
|
||||
file, _ = os.OpenFile("invalid", os.O_RDONLY, 0644)
|
||||
size, _ = GetFileSize(file)
|
||||
test.IsEqualInt(t, int(size), 0)
|
||||
testconfiguration.IsEqualInt(t, int(size), 0)
|
||||
os.Remove("testfile")
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"Gokapi/pkg/test"
|
||||
"Gokapi/internal/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
16
internal/models/Api.go
Normal file
16
internal/models/Api.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
type ApiKey struct {
|
||||
Id string `json:"Id"`
|
||||
FriendlyName string `json:"FriendlyName"`
|
||||
LastUsed int64 `json:"LastUsed"`
|
||||
}
|
||||
|
||||
type UploadItem struct {
|
||||
Id string `json:"Id"`
|
||||
Name string `json:"Name"`
|
||||
Filesize int64 `json:"Filesize"`
|
||||
Expiry int64 `json:"Expiry"`
|
||||
DownloadsRemaining int `json:"DownloadsRemaining"`
|
||||
Url string `json:"Url"`
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package filestructure
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -1,7 +1,7 @@
|
||||
package filestructure
|
||||
package models
|
||||
|
||||
import (
|
||||
"Gokapi/pkg/test"
|
||||
"Gokapi/internal/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package sessionstructure
|
||||
package models
|
||||
|
||||
// Session contains cookie parameter
|
||||
type Session struct {
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/configuration/downloadstatus"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/internal/models"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
@@ -25,20 +26,15 @@ import (
|
||||
// NewFile creates a new file in the system. Called after an upload has been completed. If a file with the same sha256 hash
|
||||
// already exists, it is deduplicated. This function gathers information about the file, creates an ID and saves
|
||||
// it into the global configuration.
|
||||
func NewFile(fileContent *multipart.File, fileHeader *multipart.FileHeader, expireAt int64, downloads int, password string) (filestructure.File, error) {
|
||||
fileBytes, err := ioutil.ReadAll(*fileContent)
|
||||
func NewFile(fileContent io.Reader, fileHeader *multipart.FileHeader, expireAt int64, downloads int, password string) (models.File, error) {
|
||||
fileBytes, err := ioutil.ReadAll(fileContent)
|
||||
if err != nil {
|
||||
return filestructure.File{}, err
|
||||
return models.File{}, err
|
||||
}
|
||||
return processUpload(&fileBytes, fileHeader, expireAt, downloads, password)
|
||||
}
|
||||
|
||||
// Called by NewFile, split into second function to make unit testing easier
|
||||
func processUpload(fileContent *[]byte, fileHeader *multipart.FileHeader, expireAt int64, downloads int, password string) (filestructure.File, error) {
|
||||
id := helper.GenerateRandomString(configuration.ServerSettings.LengthId)
|
||||
hash := sha1.New()
|
||||
hash.Write(*fileContent)
|
||||
file := filestructure.File{
|
||||
hash.Write(fileBytes)
|
||||
file := models.File{
|
||||
Id: id,
|
||||
Name: fileHeader.Filename,
|
||||
SHA256: hex.EncodeToString(hash.Sum(nil)),
|
||||
@@ -55,10 +51,10 @@ func processUpload(fileContent *[]byte, fileHeader *multipart.FileHeader, expire
|
||||
if !helper.FileExists(configuration.ServerSettings.DataDir + "/" + file.SHA256) {
|
||||
destinationFile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return filestructure.File{}, err
|
||||
return models.File{}, err
|
||||
}
|
||||
defer destinationFile.Close()
|
||||
destinationFile.Write(*fileContent)
|
||||
destinationFile.Write(fileBytes)
|
||||
}
|
||||
configuration.Save()
|
||||
return file, nil
|
||||
@@ -67,14 +63,14 @@ func processUpload(fileContent *[]byte, fileHeader *multipart.FileHeader, expire
|
||||
var imageFileExtensions = []string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"}
|
||||
|
||||
// If file is an image, create link for hotlinking
|
||||
func addHotlink(file *filestructure.File) {
|
||||
func addHotlink(file *models.File) {
|
||||
extension := strings.ToLower(filepath.Ext(file.Name))
|
||||
if !helper.IsInArray(imageFileExtensions, extension) {
|
||||
return
|
||||
}
|
||||
link := helper.GenerateRandomString(40) + extension
|
||||
file.HotlinkId = link
|
||||
configuration.ServerSettings.Hotlinks[link] = filestructure.Hotlink{
|
||||
configuration.ServerSettings.Hotlinks[link] = models.Hotlink{
|
||||
Id: link,
|
||||
FileId: file.Id,
|
||||
}
|
||||
@@ -82,8 +78,8 @@ func addHotlink(file *filestructure.File) {
|
||||
|
||||
// GetFile gets the file by id. Returns (empty File, false) if invalid / expired file
|
||||
// or (file, true) if valid file
|
||||
func GetFile(id string) (filestructure.File, bool) {
|
||||
var emptyResult = filestructure.File{}
|
||||
func GetFile(id string) (models.File, bool) {
|
||||
var emptyResult = models.File{}
|
||||
if id == "" {
|
||||
return emptyResult, false
|
||||
}
|
||||
@@ -99,8 +95,8 @@ func GetFile(id string) (filestructure.File, bool) {
|
||||
|
||||
// GetFileByHotlink gets the file by hotlink id. Returns (empty File, false) if invalid / expired file
|
||||
// or (file, true) if valid file
|
||||
func GetFileByHotlink(id string) (filestructure.File, bool) {
|
||||
var emptyResult = filestructure.File{}
|
||||
func GetFileByHotlink(id string) (models.File, bool) {
|
||||
var emptyResult = models.File{}
|
||||
if id == "" {
|
||||
return emptyResult, false
|
||||
}
|
||||
@@ -109,7 +105,7 @@ func GetFileByHotlink(id string) (filestructure.File, bool) {
|
||||
}
|
||||
|
||||
// ServeFile subtracts a download allowance and serves the file to the browser
|
||||
func ServeFile(file filestructure.File, w http.ResponseWriter, r *http.Request, forceDownload bool) {
|
||||
func ServeFile(file models.File, w http.ResponseWriter, r *http.Request, forceDownload bool) {
|
||||
file.DownloadsRemaining = file.DownloadsRemaining - 1
|
||||
configuration.ServerSettings.Files[file.Id] = file
|
||||
storageData, err := os.OpenFile(configuration.ServerSettings.DataDir+"/"+file.SHA256, os.O_RDONLY, 0644)
|
||||
|
||||
@@ -3,9 +3,10 @@ package storage
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/internal/models"
|
||||
testconfiguration "Gokapi/internal/test"
|
||||
"Gokapi/pkg/test"
|
||||
testconfiguration2 "Gokapi/internal/test/testconfiguration"
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http/httptest"
|
||||
@@ -15,10 +16,10 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testconfiguration.Create(true)
|
||||
testconfiguration2.Create(true)
|
||||
configuration.Load()
|
||||
exitVal := m.Run()
|
||||
testconfiguration.Delete()
|
||||
testconfiguration2.Delete()
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
@@ -26,42 +27,42 @@ var idNewFile string
|
||||
|
||||
func TestGetFile(t *testing.T) {
|
||||
_, result := GetFile("invalid")
|
||||
test.IsEqualBool(t, result, false)
|
||||
testconfiguration.IsEqualBool(t, result, false)
|
||||
file, result := GetFile("Wzol7LyY2QVczXynJtVo")
|
||||
test.IsEqualBool(t, result, true)
|
||||
test.IsEqualString(t, file.Id, "Wzol7LyY2QVczXynJtVo")
|
||||
test.IsEqualString(t, file.Name, "smallfile2")
|
||||
test.IsEqualString(t, file.Size, "8 B")
|
||||
test.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
testconfiguration.IsEqualBool(t, result, true)
|
||||
testconfiguration.IsEqualString(t, file.Id, "Wzol7LyY2QVczXynJtVo")
|
||||
testconfiguration.IsEqualString(t, file.Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, file.Size, "8 B")
|
||||
testconfiguration.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
_, result = GetFile("deletedfile1234")
|
||||
test.IsEqualBool(t, result, false)
|
||||
testconfiguration.IsEqualBool(t, result, false)
|
||||
|
||||
}
|
||||
|
||||
func TestGetFileByHotlink(t *testing.T) {
|
||||
_, result := GetFileByHotlink("invalid")
|
||||
test.IsEqualBool(t, result, false)
|
||||
testconfiguration.IsEqualBool(t, result, false)
|
||||
_, result = GetFileByHotlink("")
|
||||
test.IsEqualBool(t, result, false)
|
||||
testconfiguration.IsEqualBool(t, result, false)
|
||||
file, result := GetFileByHotlink("PhSs6mFtf8O5YGlLMfNw9rYXx9XRNkzCnJZpQBi7inunv3Z4A.jpg")
|
||||
test.IsEqualBool(t, result, true)
|
||||
test.IsEqualString(t, file.Id, "n1tSTAGj8zan9KaT4u6p")
|
||||
test.IsEqualString(t, file.Name, "picture.jpg")
|
||||
test.IsEqualString(t, file.Size, "4 B")
|
||||
test.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
testconfiguration.IsEqualBool(t, result, true)
|
||||
testconfiguration.IsEqualString(t, file.Id, "n1tSTAGj8zan9KaT4u6p")
|
||||
testconfiguration.IsEqualString(t, file.Name, "picture.jpg")
|
||||
testconfiguration.IsEqualString(t, file.Size, "4 B")
|
||||
testconfiguration.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
}
|
||||
|
||||
func TestAddHotlink(t *testing.T) {
|
||||
file := filestructure.File{Name: "test.dat", Id: "testIdE"}
|
||||
file := models.File{Name: "test.dat", Id: "testIdE"}
|
||||
addHotlink(&file)
|
||||
test.IsEqualString(t, file.HotlinkId, "")
|
||||
file = filestructure.File{Name: "test.jpg", Id: "testId"}
|
||||
testconfiguration.IsEqualString(t, file.HotlinkId, "")
|
||||
file = models.File{Name: "test.jpg", Id: "testId"}
|
||||
addHotlink(&file)
|
||||
test.IsEqualInt(t, len(file.HotlinkId), 44)
|
||||
testconfiguration.IsEqualInt(t, len(file.HotlinkId), 44)
|
||||
lastCharacters := file.HotlinkId[len(file.HotlinkId)-4:]
|
||||
test.IsEqualBool(t, lastCharacters == ".jpg", true)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Hotlinks[file.HotlinkId].FileId, "testId")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Hotlinks[file.HotlinkId].Id, file.HotlinkId)
|
||||
testconfiguration.IsEqualBool(t, lastCharacters == ".jpg", true)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Hotlinks[file.HotlinkId].FileId, "testId")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Hotlinks[file.HotlinkId].Id, file.HotlinkId)
|
||||
}
|
||||
|
||||
func TestNewFile(t *testing.T) {
|
||||
@@ -75,79 +76,78 @@ func TestNewFile(t *testing.T) {
|
||||
Header: mimeHeader,
|
||||
Size: int64(len(content)),
|
||||
}
|
||||
file, err := processUpload(&content, &header, 2147483600, 1, "")
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualString(t, file.Name, "test.dat")
|
||||
test.IsEqualString(t, file.SHA256, "f1474c19eff0fc8998fa6e1b1f7bf31793b103a6")
|
||||
test.IsEqualString(t, file.HotlinkId, "")
|
||||
test.IsEqualString(t, file.PasswordHash, "")
|
||||
test.IsEqualString(t, file.Size, "35 B")
|
||||
test.IsEqualString(t, file.ExpireAtString, "2038-01-19 03:13")
|
||||
test.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
test.IsEqualInt(t, len(file.Id), 20)
|
||||
test.IsEqualInt(t, int(file.ExpireAt), 2147483600)
|
||||
file, err := NewFile(bytes.NewReader(content), &header, 2147483600, 1, "")
|
||||
testconfiguration.IsNil(t, err)
|
||||
testconfiguration.IsEqualString(t, file.Name, "test.dat")
|
||||
testconfiguration.IsEqualString(t, file.SHA256, "f1474c19eff0fc8998fa6e1b1f7bf31793b103a6")
|
||||
testconfiguration.IsEqualString(t, file.HotlinkId, "")
|
||||
testconfiguration.IsEqualString(t, file.PasswordHash, "")
|
||||
testconfiguration.IsEqualString(t, file.Size, "35 B")
|
||||
testconfiguration.IsEqualString(t, file.ExpireAtString, "2038-01-19 03:13")
|
||||
testconfiguration.IsEqualInt(t, file.DownloadsRemaining, 1)
|
||||
testconfiguration.IsEqualInt(t, len(file.Id), 20)
|
||||
testconfiguration.IsEqualInt(t, int(file.ExpireAt), 2147483600)
|
||||
idNewFile = file.Id
|
||||
}
|
||||
|
||||
func TestServeFile(t *testing.T) {
|
||||
file, result := GetFile(idNewFile)
|
||||
test.IsEqualBool(t, result, true)
|
||||
testconfiguration.IsEqualBool(t, result, true)
|
||||
r := httptest.NewRequest("GET", "/upload", nil)
|
||||
w := httptest.NewRecorder()
|
||||
ServeFile(file, w, r, true)
|
||||
_, result = GetFile(idNewFile)
|
||||
test.IsEqualBool(t, result, false)
|
||||
testconfiguration.IsEqualBool(t, result, false)
|
||||
|
||||
test.IsEqualString(t, w.Result().Header.Get("Content-Disposition"), "attachment; filename=\"test.dat\"")
|
||||
test.IsEqualString(t, w.Result().Header.Get("Content-Length"), "35")
|
||||
test.IsEqualString(t, w.Result().Header.Get("Content-Type"), "text")
|
||||
testconfiguration.IsEqualString(t, w.Result().Header.Get("Content-Disposition"), "attachment; filename=\"test.dat\"")
|
||||
testconfiguration.IsEqualString(t, w.Result().Header.Get("Content-Length"), "35")
|
||||
testconfiguration.IsEqualString(t, w.Result().Header.Get("Content-Type"), "text")
|
||||
content, err := ioutil.ReadAll(w.Result().Body)
|
||||
test.IsNil(t, err)
|
||||
test.IsEqualString(t, string(content), "This is a file for testing purposes")
|
||||
|
||||
testconfiguration.IsNil(t, err)
|
||||
testconfiguration.IsEqualString(t, string(content), "This is a file for testing purposes")
|
||||
}
|
||||
|
||||
func TestCleanUp(t *testing.T) {
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "picture.jpg")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "DeletedFile")
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "picture.jpg")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "DeletedFile")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
|
||||
CleanUp(false)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "picture.jpg")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "picture.jpg")
|
||||
|
||||
file, _ := GetFile("n1tSTAGj8zan9KaT4u6p")
|
||||
file.DownloadsRemaining = 0
|
||||
configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"] = file
|
||||
|
||||
CleanUp(false)
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0"), false)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0"), false)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
|
||||
file, _ = GetFile("Wzol7LyY2QVczXynJtVo")
|
||||
file.DownloadsRemaining = 0
|
||||
configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"] = file
|
||||
|
||||
CleanUp(false)
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/e017693e4a04a59d0b0f400fe98177fe7ee13cf7"), true)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/e017693e4a04a59d0b0f400fe98177fe7ee13cf7"), true)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "smallfile2")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "smallfile3")
|
||||
|
||||
file, _ = GetFile("e4TjE7CokWK0giiLNxDL")
|
||||
file.DownloadsRemaining = 0
|
||||
@@ -157,17 +157,17 @@ func TestCleanUp(t *testing.T) {
|
||||
configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"] = file
|
||||
|
||||
CleanUp(false)
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/e017693e4a04a59d0b0f400fe98177fe7ee13cf7"), false)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "")
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/e017693e4a04a59d0b0f400fe98177fe7ee13cf7"), false)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["Wzol7LyY2QVczXynJtVo"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["n1tSTAGj8zan9KaT4u6p"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["deletedfile123456789"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["e4TjE7CokWK0giiLNxDL"].Name, "")
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["wefffewhtrhhtrhtrhtr"].Name, "")
|
||||
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
configuration.ServerSettings.DownloadStatus = make(map[string]filestructure.DownloadStatus)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "cleanup")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), true)
|
||||
configuration.ServerSettings.DownloadStatus = make(map[string]models.DownloadStatus)
|
||||
CleanUp(false)
|
||||
test.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "")
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), false)
|
||||
testconfiguration.IsEqualString(t, configuration.ServerSettings.Files["cleanuptest123456789"].Name, "")
|
||||
testconfiguration.IsEqualBool(t, helper.FileExists("test/data/2341354656543213246465465465432456898794"), false)
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package testconfiguration
|
||||
|
||||
import (
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/pkg/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
Create(true)
|
||||
test.IsEqualBool(t, helper.FolderExists("test"), true)
|
||||
test.IsEqualBool(t, helper.FileExists("test/config.json"), true)
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0"), true)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
Delete()
|
||||
test.IsEqualBool(t, helper.FolderExists("test"), false)
|
||||
}
|
||||
|
||||
func TestMockInputStdin(t *testing.T) {
|
||||
original := StartMockInputStdin(t, "test")
|
||||
result := helper.ReadLine()
|
||||
StopMockInputStdin(original)
|
||||
test.IsEqualString(t, result, "test")
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build test
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
@@ -12,53 +14,70 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type MockT interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// IsEqualString fails test if got and want are not identical
|
||||
func IsEqualString(t *testing.T, got, want string) {
|
||||
func IsEqualString(t MockT, got, want string) {
|
||||
if got != want {
|
||||
t.Errorf("Assertion failed, got: %s, want: %s.", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotEqualString fails test if got and want are not identical
|
||||
func IsNotEqualString(t MockT, got, want string) {
|
||||
if got == want {
|
||||
t.Errorf("Assertion failed, got: %s, want: not %s.", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// IsEqualBool fails test if got and want are not identical
|
||||
func IsEqualBool(t *testing.T, got, want bool) {
|
||||
func IsEqualBool(t MockT, got, want bool) {
|
||||
if got != want {
|
||||
t.Errorf("Assertion failed, got: %t, want: %t.", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// IsEqualInt fails test if got and want are not identical
|
||||
func IsEqualInt(t *testing.T, got, want int) {
|
||||
func IsEqualInt(t MockT, got, want int) {
|
||||
if got != want {
|
||||
t.Errorf("Assertion failed, got: %d, want: %d.", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotEmpty fails test if string is empty
|
||||
func IsNotEmpty(t *testing.T, s string) {
|
||||
func IsNotEmpty(t MockT, s string) {
|
||||
if s == "" {
|
||||
t.Errorf("Assertion failed, got: %s, want: empty.", s)
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty fails test if string is not empty
|
||||
func IsEmpty(t *testing.T, s string) {
|
||||
func IsEmpty(t MockT, s string) {
|
||||
if s != "" {
|
||||
t.Errorf("Assertion failed, got: %s, want: empty.", s)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil fails test if error not nil
|
||||
func IsNil(t *testing.T, got error) {
|
||||
func IsNil(t MockT, got error) {
|
||||
if got != nil {
|
||||
t.Errorf("Assertion failed, got: %s, want: nil.", got.Error())
|
||||
t.Errorf("Assertion failed, got: %s, want: nil.", got.(error).Error())
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotNil fails test if error is nil
|
||||
func IsNotNil(t MockT, got error) {
|
||||
if got == nil {
|
||||
t.Errorf("Assertion failed, got: nil, want: not nil.")
|
||||
}
|
||||
}
|
||||
|
||||
// HttpPageResult tests if a http server is outputting the correct result
|
||||
func HttpPageResult(t *testing.T, config HttpTestConfig) []*http.Cookie {
|
||||
func HttpPageResult(t MockT, config HttpTestConfig) []*http.Cookie {
|
||||
config.init()
|
||||
client := &http.Client{}
|
||||
|
||||
@@ -86,16 +105,16 @@ func HttpPageResult(t *testing.T, config HttpTestConfig) []*http.Cookie {
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
IsNil(t, err)
|
||||
if config.IsHtml && !bytes.Contains(content, []byte("</html>")) {
|
||||
t.Error(config.Url + ": Incorrect response")
|
||||
t.Errorf(config.Url + ": Incorrect response")
|
||||
}
|
||||
for _, requiredString := range config.RequiredContent {
|
||||
if !bytes.Contains(content, []byte(requiredString)) {
|
||||
t.Error(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
t.Errorf(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
}
|
||||
}
|
||||
for _, excludedString := range config.ExcludedContent {
|
||||
if bytes.Contains(content, []byte(excludedString)) {
|
||||
t.Error(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
t.Errorf(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
}
|
||||
}
|
||||
resp.Body.Close()
|
||||
@@ -141,7 +160,7 @@ type PostBody struct {
|
||||
}
|
||||
|
||||
// HttpPostRequest sends a post request
|
||||
func HttpPostRequest(t *testing.T, config HttpTestConfig) {
|
||||
func HttpPostRequest(t MockT, config HttpTestConfig) {
|
||||
file, err := os.Open(config.UploadFileName)
|
||||
IsNil(t, err)
|
||||
defer file.Close()
|
||||
@@ -170,12 +189,12 @@ func HttpPostRequest(t *testing.T, config HttpTestConfig) {
|
||||
|
||||
for _, requiredString := range config.RequiredContent {
|
||||
if !bytes.Contains(content, []byte(requiredString)) {
|
||||
t.Error(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
t.Errorf(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
}
|
||||
}
|
||||
for _, excludedString := range config.ExcludedContent {
|
||||
if bytes.Contains(content, []byte(excludedString)) {
|
||||
t.Error(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
t.Errorf(config.Url + ": Incorrect response. Got:\n" + string(content))
|
||||
}
|
||||
}
|
||||
}
|
||||
73
internal/test/TestHelper_test.go
Normal file
73
internal/test/TestHelper_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
wantFail bool
|
||||
isFailed = false
|
||||
)
|
||||
|
||||
type MockTest struct {
|
||||
reference *testing.T
|
||||
}
|
||||
|
||||
func (t MockTest) Errorf(format string, args ...interface{}) {
|
||||
isFailed = true
|
||||
}
|
||||
|
||||
func (t *MockTest) WantFail() {
|
||||
t.Check()
|
||||
isFailed = false
|
||||
wantFail = true
|
||||
}
|
||||
func (t *MockTest) WantNoFail() {
|
||||
t.Check()
|
||||
isFailed = false
|
||||
wantFail = false
|
||||
}
|
||||
|
||||
func (t *MockTest) Check() {
|
||||
if wantFail != isFailed {
|
||||
t.reference.Error("Test failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFunctions(t *testing.T) {
|
||||
mockT := MockTest{reference: t}
|
||||
mockT.WantNoFail()
|
||||
IsEqualString(mockT, "test", "test")
|
||||
mockT.WantNoFail()
|
||||
IsNotEqualString(mockT, "test", "test2")
|
||||
mockT.WantNoFail()
|
||||
IsEqualBool(mockT, true, true)
|
||||
mockT.WantNoFail()
|
||||
IsEqualInt(mockT, 1, 1)
|
||||
mockT.WantNoFail()
|
||||
IsNotEmpty(mockT, "notEmpty")
|
||||
mockT.WantNoFail()
|
||||
IsEmpty(mockT, "")
|
||||
mockT.WantNoFail()
|
||||
IsNil(mockT, nil)
|
||||
mockT.WantNoFail()
|
||||
IsNotNil(mockT, errors.New("hello"))
|
||||
mockT.WantFail()
|
||||
IsEqualString(mockT, "test", "test2")
|
||||
mockT.WantFail()
|
||||
IsNotEqualString(mockT, "test", "test")
|
||||
mockT.WantFail()
|
||||
IsEqualBool(mockT, true, false)
|
||||
mockT.WantFail()
|
||||
IsEqualInt(mockT, 1, 2)
|
||||
mockT.WantFail()
|
||||
IsNotEmpty(mockT, "")
|
||||
mockT.WantFail()
|
||||
IsEmpty(mockT, "notEmpty")
|
||||
mockT.WantFail()
|
||||
IsNil(mockT, errors.New("hello"))
|
||||
mockT.WantFail()
|
||||
IsNotNil(mockT, nil)
|
||||
mockT.Check()
|
||||
}
|
||||
@@ -4,15 +4,19 @@ package testconfiguration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
dataDir = "test"
|
||||
configFile = dataDir + "/config.json"
|
||||
)
|
||||
|
||||
// Create creates a configuration for unit testing
|
||||
func Create(initFiles bool) {
|
||||
os.Setenv("GOKAPI_CONFIG_DIR", "test")
|
||||
os.Setenv("GOKAPI_DATA_DIR", "test")
|
||||
os.Mkdir("test", 0777)
|
||||
os.WriteFile("test/config.json", configTestFile, 0777)
|
||||
os.Mkdir(dataDir, 0777)
|
||||
os.WriteFile(configFile, configTestFile, 0777)
|
||||
if initFiles {
|
||||
os.Mkdir("test/data", 0777)
|
||||
os.WriteFile("test/data/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0", []byte("123"), 0777)
|
||||
@@ -23,21 +27,26 @@ func Create(initFiles bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// WriteUpgradeConfigFile writes a Gokapi v1.1.0 config file
|
||||
func WriteUpgradeConfigFile() {
|
||||
os.Mkdir(dataDir, 0777)
|
||||
os.WriteFile(configFile, configUpgradeTestFile, 0777)
|
||||
}
|
||||
|
||||
// Delete deletes the configuration for unit testing
|
||||
func Delete() {
|
||||
os.RemoveAll("test")
|
||||
os.RemoveAll(dataDir)
|
||||
}
|
||||
|
||||
// StartMockInputStdin simulates a user input on stdin. Call StopMockInputStdin afterwards!
|
||||
func StartMockInputStdin(t *testing.T, input string) *os.File {
|
||||
func StartMockInputStdin(input string) *os.File {
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte(input))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
w.Close()
|
||||
|
||||
@@ -189,9 +198,65 @@ var configTestFile = []byte(`{
|
||||
"ExpireAt":2147483646
|
||||
}
|
||||
},
|
||||
"ConfigVersion":5,
|
||||
"ApiKeys":{
|
||||
"validkey":{
|
||||
"Id":"validkey",
|
||||
"FriendlyName":"Test Key",
|
||||
"LastUsed":1619367972
|
||||
}
|
||||
},
|
||||
"ConfigVersion":6,
|
||||
"SaltAdmin":"LW6fW4Pjv8GtdWVLSZD66gYEev6NAaXxOVBw7C",
|
||||
"SaltFiles":"lL5wMTtnVCn5TPbpRaSe4vAQodWW0hgk00WCZE",
|
||||
"LengthId":20,
|
||||
"DataDir":"test/data"
|
||||
}`)
|
||||
|
||||
var configUpgradeTestFile = []byte(`{
|
||||
"Port":"127.0.0.1:53842",
|
||||
"AdminName":"admin",
|
||||
"AdminPassword":"7450c2403ab85f0e8d5436818b66b99fdd287ac6",
|
||||
"ServerUrl":"https://gokapi.url/",
|
||||
"DefaultDownloads":1,
|
||||
"DefaultExpiry":14,
|
||||
"DefaultPassword":"123",
|
||||
"RedirectUrl":"https://github.com/Forceu/Gokapi/",
|
||||
"Sessions":{
|
||||
"y0t-OQGF5UPFHyFOLab38SNjrc_a4xdIHTsZclkLpxuSwwTzS_qEETsinkgVIdWNMnQjhcaZtgCoJdpu":{
|
||||
"RenewAt":1619774155,
|
||||
"ValidUntil":1622362555
|
||||
}
|
||||
},
|
||||
"Files":{
|
||||
"MgXJLe4XLfpXcL12ec4i":{
|
||||
"Id":"MgXJLe4XLfpXcL12ec4i",
|
||||
"Name":"gokapi-linux_amd64",
|
||||
"Size":"10.2 MB",
|
||||
"SHA256":"b08f5989e1c6d57b45fffe39a8edc5da715799b7",
|
||||
"ExpireAt":1620980170,
|
||||
"ExpireAtString":"2021-05-14 10:16",
|
||||
"DownloadsRemaining":1,
|
||||
"PasswordHash":"e143a1801faba4c5c6fdc2e823127c988940f72e"
|
||||
},
|
||||
"doLN1pgbb945DfhGottx":{
|
||||
"Id":"doLN1pgbb945DfhGottx",
|
||||
"Name":"config.json",
|
||||
"Size":"945 B",
|
||||
"SHA256":"d2d6fd5fbf4a4bb1b1ae2f19130dd75b5adc0a0b",
|
||||
"ExpireAt":1620980181,
|
||||
"ExpireAtString":"2021-05-14 10:16",
|
||||
"DownloadsRemaining":1,
|
||||
"PasswordHash":"e143a1801faba4c5c6fdc2e823127c988940f72e"
|
||||
},
|
||||
"q06tcBco9gdJTf_pZ8xf":{
|
||||
"Id":"q06tcBco9gdJTf_pZ8xf",
|
||||
"Name":"gokapi-linux_amd64",
|
||||
"Size":"10.2 MB",
|
||||
"SHA256":"b08f5989e1c6d57b45fffe39a8edc5da715799b7",
|
||||
"ExpireAt":1620980160,
|
||||
"ExpireAtString":"2021-05-14 10:16",
|
||||
"DownloadsRemaining":1,
|
||||
"PasswordHash":""
|
||||
}
|
||||
}
|
||||
}`)
|
||||
33
internal/test/testconfiguration/TestConfiguration_test.go
Normal file
33
internal/test/testconfiguration/TestConfiguration_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package testconfiguration
|
||||
|
||||
import (
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/test"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
Create(true)
|
||||
test.IsEqualBool(t, helper.FolderExists(dataDir), true)
|
||||
test.IsEqualBool(t, helper.FileExists(configFile), true)
|
||||
test.IsEqualBool(t, helper.FileExists("test/data/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0"), true)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
Delete()
|
||||
test.IsEqualBool(t, helper.FolderExists(dataDir), false)
|
||||
}
|
||||
|
||||
func TestMockInputStdin(t *testing.T) {
|
||||
original := StartMockInputStdin(dataDir)
|
||||
result := helper.ReadLine()
|
||||
StopMockInputStdin(original)
|
||||
test.IsEqualString(t, result, dataDir)
|
||||
}
|
||||
func TestSetUpgradeConfigFile(t *testing.T) {
|
||||
os.Remove(configFile)
|
||||
WriteUpgradeConfigFile()
|
||||
test.IsEqualBool(t, helper.FileExists(configFile), true)
|
||||
TestDelete(t)
|
||||
}
|
||||
@@ -7,8 +7,9 @@ Handling of webserver and requests / uploads
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/models"
|
||||
"Gokapi/internal/storage"
|
||||
"Gokapi/internal/storage/filestructure"
|
||||
"Gokapi/internal/webserver/sessionmanager"
|
||||
"embed"
|
||||
"fmt"
|
||||
"html/template"
|
||||
@@ -101,7 +102,7 @@ func redirect(w http.ResponseWriter, url string) {
|
||||
|
||||
// Handling of /logout
|
||||
func doLogout(w http.ResponseWriter, r *http.Request) {
|
||||
logoutSession(w, r)
|
||||
sessionmanager.LogoutSession(w, r)
|
||||
redirect(w, "login")
|
||||
}
|
||||
|
||||
@@ -134,7 +135,7 @@ func showLogin(w http.ResponseWriter, r *http.Request) {
|
||||
failedLogin := false
|
||||
if pw != "" && user != "" {
|
||||
if strings.ToLower(user) == strings.ToLower(configuration.ServerSettings.AdminName) && configuration.HashPassword(pw, false) == configuration.ServerSettings.AdminPassword {
|
||||
createSession(w, false)
|
||||
sessionmanager.CreateSession(w, false)
|
||||
redirect(w, "admin")
|
||||
return
|
||||
}
|
||||
@@ -261,7 +262,7 @@ type DownloadView struct {
|
||||
|
||||
// UploadView contains parameters for the admin menu template
|
||||
type UploadView struct {
|
||||
Items []filestructure.File
|
||||
Items []models.File
|
||||
Url string
|
||||
HotlinkUrl string
|
||||
TimeNow int64
|
||||
@@ -276,7 +277,7 @@ type UploadView struct {
|
||||
// Converts the globalConfig variable to an UploadView struct to pass the infos to
|
||||
// the admin template
|
||||
func (u *UploadView) convertGlobalConfig() *UploadView {
|
||||
var result []filestructure.File
|
||||
var result []models.File
|
||||
for _, element := range configuration.ServerSettings.Files {
|
||||
result = append(result, element)
|
||||
}
|
||||
@@ -323,7 +324,7 @@ func uploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
configuration.ServerSettings.DefaultPassword = password
|
||||
file, header, err := r.FormFile("file")
|
||||
responseError(w, err)
|
||||
result, err := storage.NewFile(&file, header, time.Now().Add(time.Duration(expiryDaysInt)*time.Hour*24).Unix(), allowedDownloadsInt, password)
|
||||
result, err := storage.NewFile(file, header, time.Now().Add(time.Duration(expiryDaysInt)*time.Hour*24).Unix(), allowedDownloadsInt, password)
|
||||
responseError(w, err)
|
||||
defer file.Close()
|
||||
_, err = fmt.Fprint(w, result.ToJsonResult(configuration.ServerSettings.ServerUrl))
|
||||
@@ -357,7 +358,7 @@ func downloadFile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Checks if the user is logged in as an admin
|
||||
func isAuthenticated(w http.ResponseWriter, r *http.Request, isUpload bool) bool {
|
||||
if isValidSession(w, r) {
|
||||
if sessionmanager.IsValidSession(w, r) {
|
||||
return true
|
||||
}
|
||||
if isUpload {
|
||||
@@ -370,7 +371,7 @@ func isAuthenticated(w http.ResponseWriter, r *http.Request, isUpload bool) bool
|
||||
}
|
||||
|
||||
// Write a cookie if the user has entered a correct password for a password-protected file
|
||||
func writeFilePwCookie(w http.ResponseWriter, file filestructure.File) {
|
||||
func writeFilePwCookie(w http.ResponseWriter, file models.File) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "p" + file.Id,
|
||||
Value: file.PasswordHash,
|
||||
@@ -380,7 +381,7 @@ func writeFilePwCookie(w http.ResponseWriter, file filestructure.File) {
|
||||
|
||||
// Checks if a cookie contains the correct password hash for a password-protected file
|
||||
// If incorrect, a 3 second delay is introduced unless the cookie was empty.
|
||||
func isValidPwCookie(r *http.Request, file filestructure.File) bool {
|
||||
func isValidPwCookie(r *http.Request, file models.File) bool {
|
||||
cookie, err := r.Cookie("p" + file.Id)
|
||||
if err == nil {
|
||||
if cookie.Value == file.PasswordHash {
|
||||
|
||||
@@ -3,7 +3,7 @@ package webserver
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
testconfiguration "Gokapi/internal/test"
|
||||
"Gokapi/pkg/test"
|
||||
testconfiguration2 "Gokapi/internal/test/testconfiguration"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testconfiguration.Create(true)
|
||||
testconfiguration2.Create(true)
|
||||
configuration.Load()
|
||||
go Start()
|
||||
time.Sleep(1 * time.Second)
|
||||
exitVal := m.Run()
|
||||
testconfiguration.Delete()
|
||||
testconfiguration2.Delete()
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestEmbedFs(t *testing.T) {
|
||||
|
||||
func TestIndexRedirect(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/",
|
||||
RequiredContent: []string{"<html><head><meta http-equiv=\"Refresh\" content=\"0; URL=./index\"></head></html>"},
|
||||
IsHtml: true,
|
||||
@@ -46,7 +46,7 @@ func TestIndexRedirect(t *testing.T) {
|
||||
}
|
||||
func TestIndexFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/index",
|
||||
RequiredContent: []string{configuration.ServerSettings.RedirectUrl},
|
||||
IsHtml: true,
|
||||
@@ -54,14 +54,14 @@ func TestIndexFile(t *testing.T) {
|
||||
}
|
||||
func TestStaticDirs(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/css/cover.css",
|
||||
RequiredContent: []string{".btn-secondary:hover"},
|
||||
})
|
||||
}
|
||||
func TestLogin(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/login",
|
||||
RequiredContent: []string{"id=\"uname_hidden\""},
|
||||
IsHtml: true,
|
||||
@@ -69,7 +69,7 @@ func TestLogin(t *testing.T) {
|
||||
}
|
||||
func TestAdminNoAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"URL=./login\""},
|
||||
IsHtml: true,
|
||||
@@ -77,11 +77,11 @@ func TestAdminNoAuth(t *testing.T) {
|
||||
}
|
||||
func TestAdminAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"Downloads remaining"},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession",
|
||||
}},
|
||||
@@ -89,11 +89,11 @@ func TestAdminAuth(t *testing.T) {
|
||||
}
|
||||
func TestAdminExpiredAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"URL=./login\""},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "expiredsession",
|
||||
}},
|
||||
@@ -102,11 +102,11 @@ func TestAdminExpiredAuth(t *testing.T) {
|
||||
|
||||
func TestAdminRenewalAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
cookies := test.HttpPageResult(t, test.HttpTestConfig{
|
||||
cookies := testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"Downloads remaining"},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "needsRenewal",
|
||||
}},
|
||||
@@ -121,11 +121,11 @@ func TestAdminRenewalAuth(t *testing.T) {
|
||||
if sessionCookie == "needsRenewal" {
|
||||
t.Error("Session not renewed")
|
||||
}
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"Downloads remaining"},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: sessionCookie,
|
||||
}},
|
||||
@@ -134,11 +134,11 @@ func TestAdminRenewalAuth(t *testing.T) {
|
||||
|
||||
func TestAdminInvalidAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"URL=./login\""},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "invalid",
|
||||
}},
|
||||
@@ -147,7 +147,7 @@ func TestAdminInvalidAuth(t *testing.T) {
|
||||
|
||||
func TestInvalidLink(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/d?id=123",
|
||||
RequiredContent: []string{"URL=./error\""},
|
||||
IsHtml: true,
|
||||
@@ -155,7 +155,7 @@ func TestInvalidLink(t *testing.T) {
|
||||
}
|
||||
func TestError(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/error",
|
||||
RequiredContent: []string{"this file cannot be found"},
|
||||
IsHtml: true,
|
||||
@@ -163,7 +163,7 @@ func TestError(t *testing.T) {
|
||||
}
|
||||
func TestForgotPw(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/forgotpw",
|
||||
RequiredContent: []string{"--reset-pw"},
|
||||
IsHtml: true,
|
||||
@@ -171,63 +171,63 @@ func TestForgotPw(t *testing.T) {
|
||||
}
|
||||
func TestLoginCorrect(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/login",
|
||||
RequiredContent: []string{"URL=./admin\""},
|
||||
IsHtml: true,
|
||||
Method: "POST",
|
||||
PostValues: []test.PostBody{{"username", "test"}, {"password", "testtest"}},
|
||||
PostValues: []testconfiguration.PostBody{{"username", "test"}, {"password", "testtest"}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoginIncorrectPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/login",
|
||||
RequiredContent: []string{"Incorrect username or password"},
|
||||
IsHtml: true,
|
||||
Method: "POST",
|
||||
PostValues: []test.PostBody{{"username", "test"}, {"password", "incorrect"}},
|
||||
PostValues: []testconfiguration.PostBody{{"username", "test"}, {"password", "incorrect"}},
|
||||
})
|
||||
}
|
||||
func TestLoginIncorrectUsername(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/login",
|
||||
RequiredContent: []string{"Incorrect username or password"},
|
||||
IsHtml: true,
|
||||
Method: "POST",
|
||||
PostValues: []test.PostBody{{"username", "incorrect"}, {"password", "incorrect"}},
|
||||
PostValues: []testconfiguration.PostBody{{"username", "incorrect"}, {"password", "incorrect"}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestLogout(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"Downloads remaining"},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "logoutsession",
|
||||
}},
|
||||
})
|
||||
// Logout
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/logout",
|
||||
RequiredContent: []string{"URL=./login\""},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "logoutsession",
|
||||
}},
|
||||
})
|
||||
// Admin after logout
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://localhost:53843/admin",
|
||||
RequiredContent: []string{"URL=./login\""},
|
||||
IsHtml: true,
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "logoutsession",
|
||||
}},
|
||||
@@ -236,12 +236,12 @@ func TestLogout(t *testing.T) {
|
||||
|
||||
func TestDownloadHotlink(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/hotlink/PhSs6mFtf8O5YGlLMfNw9rYXx9XRNkzCnJZpQBi7inunv3Z4A.jpg",
|
||||
RequiredContent: []string{"123"},
|
||||
})
|
||||
// Download expired hotlink
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/hotlink/PhSs6mFtf8O5YGlLMfNw9rYXx9XRNkzCnJZpQBi7inunv3Z4A.jpg",
|
||||
RequiredContent: []string{"Created with GIMP"},
|
||||
})
|
||||
@@ -250,24 +250,24 @@ func TestDownloadHotlink(t *testing.T) {
|
||||
func TestDownloadNoPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Show download page
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=Wzol7LyY2QVczXynJtVo",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"smallfile2"},
|
||||
})
|
||||
// Download
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/downloadFile?id=Wzol7LyY2QVczXynJtVo",
|
||||
RequiredContent: []string{"789"},
|
||||
})
|
||||
// Show download page expired file
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=Wzol7LyY2QVczXynJtVo",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./error\""},
|
||||
})
|
||||
// Download expired file
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/downloadFile?id=Wzol7LyY2QVczXynJtVo",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./error\""},
|
||||
@@ -276,7 +276,7 @@ func TestDownloadNoPassword(t *testing.T) {
|
||||
|
||||
func TestDownloadPagePassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=jpLXGJKigM4hjtA6T6sN",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"Password required"},
|
||||
@@ -284,44 +284,44 @@ func TestDownloadPagePassword(t *testing.T) {
|
||||
}
|
||||
func TestDownloadPageIncorrectPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=jpLXGJKigM4hjtA6T6sN",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"Incorrect password!"},
|
||||
Method: "POST",
|
||||
PostValues: []test.PostBody{{"password", "incorrect"}},
|
||||
PostValues: []testconfiguration.PostBody{{"password", "incorrect"}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestDownloadIncorrectPasswordCookie(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=jpLXGJKigM4hjtA6T6sN",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"Password required"},
|
||||
Cookies: []test.Cookie{{"pjpLXGJKigM4hjtA6T6sN", "invalid"}},
|
||||
Cookies: []testconfiguration.Cookie{{"pjpLXGJKigM4hjtA6T6sN", "invalid"}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestDownloadIncorrectPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/downloadFile?id=jpLXGJKigM4hjtA6T6sN",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./d?id=jpLXGJKigM4hjtA6T6sN"},
|
||||
Cookies: []test.Cookie{{"pjpLXGJKigM4hjtA6T6sN", "invalid"}},
|
||||
Cookies: []testconfiguration.Cookie{{"pjpLXGJKigM4hjtA6T6sN", "invalid"}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestDownloadCorrectPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Submit download page correct password
|
||||
cookies := test.HttpPageResult(t, test.HttpTestConfig{
|
||||
cookies := testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=jpLXGJKigM4hjtA6T6sN2",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./d?id=jpLXGJKigM4hjtA6T6sN2"},
|
||||
Method: "POST",
|
||||
PostValues: []test.PostBody{{"password", "123"}},
|
||||
PostValues: []testconfiguration.PostBody{{"password", "123"}},
|
||||
})
|
||||
pwCookie := ""
|
||||
for _, cookie := range cookies {
|
||||
@@ -334,23 +334,23 @@ func TestDownloadCorrectPassword(t *testing.T) {
|
||||
t.Error("Cookie not set")
|
||||
}
|
||||
// Show download page correct password
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/d?id=jpLXGJKigM4hjtA6T6sN2",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"smallfile"},
|
||||
Cookies: []test.Cookie{{"pjpLXGJKigM4hjtA6T6sN2", pwCookie}},
|
||||
Cookies: []testconfiguration.Cookie{{"pjpLXGJKigM4hjtA6T6sN2", pwCookie}},
|
||||
})
|
||||
// Download correct password
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/downloadFile?id=jpLXGJKigM4hjtA6T6sN2",
|
||||
RequiredContent: []string{"456"},
|
||||
Cookies: []test.Cookie{{"pjpLXGJKigM4hjtA6T6sN2", pwCookie}},
|
||||
Cookies: []testconfiguration.Cookie{{"pjpLXGJKigM4hjtA6T6sN2", pwCookie}},
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteFileNonAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/delete?id=e4TjE7CokWK0giiLNxDL",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./login"},
|
||||
@@ -359,20 +359,20 @@ func TestDeleteFileNonAuth(t *testing.T) {
|
||||
|
||||
func TestDeleteFileInvalidKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/delete",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./admin"},
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession",
|
||||
}},
|
||||
})
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/delete?id=",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./admin"},
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession",
|
||||
}},
|
||||
@@ -381,11 +381,11 @@ func TestDeleteFileInvalidKey(t *testing.T) {
|
||||
|
||||
func TestDeleteFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPageResult(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPageResult(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/delete?id=e4TjE7CokWK0giiLNxDL",
|
||||
IsHtml: true,
|
||||
RequiredContent: []string{"URL=./admin"},
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession",
|
||||
}},
|
||||
@@ -394,7 +394,7 @@ func TestDeleteFile(t *testing.T) {
|
||||
|
||||
func TestPostUploadNoAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.HttpPostRequest(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPostRequest(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/upload",
|
||||
UploadFileName: "test/fileupload.jpg",
|
||||
UploadFieldName: "file",
|
||||
@@ -402,13 +402,13 @@ func TestPostUploadNoAuth(t *testing.T) {
|
||||
})
|
||||
}
|
||||
func TestPostUpload(t *testing.T) {
|
||||
test.HttpPostRequest(t, test.HttpTestConfig{
|
||||
testconfiguration.HttpPostRequest(t, testconfiguration.HttpTestConfig{
|
||||
Url: "http://127.0.0.1:53843/upload",
|
||||
UploadFileName: "test/fileupload.jpg",
|
||||
UploadFieldName: "file",
|
||||
RequiredContent: []string{"{\"Result\":\"OK\"", "\"Name\":\"fileupload.jpg\"", "\"SHA256\":\"a9993e364706816aba3e25717850c26c9cd0d89d\"", "DownloadsRemaining\":3"},
|
||||
ExcludedContent: []string{"\"Id\":\"\"", "HotlinkId\":\"\""},
|
||||
Cookies: []test.Cookie{{
|
||||
Cookies: []testconfiguration.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession",
|
||||
}},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package webserver
|
||||
package sessionmanager
|
||||
|
||||
/**
|
||||
Manages the sessions for the admin user or to access password protected files
|
||||
@@ -7,7 +7,7 @@ Manages the sessions for the admin user or to access password protected files
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/helper"
|
||||
"Gokapi/internal/webserver/sessionstructure"
|
||||
"Gokapi/internal/models"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@@ -15,67 +15,63 @@ import (
|
||||
// If no login occurred during this time, the admin session will be deleted. Default 30 days
|
||||
const cookieLifeAdmin = 30 * 24 * time.Hour
|
||||
|
||||
// Checks if the user is submitting a valid session token
|
||||
// IsValidSession checks if the user is submitting a valid session token
|
||||
// If valid session is found, useSession will be called
|
||||
// Returns true if authenticated, otherwise false
|
||||
func isValidSession(w http.ResponseWriter, r *http.Request) bool {
|
||||
func IsValidSession(w http.ResponseWriter, r *http.Request) bool {
|
||||
cookie, err := r.Cookie("session_token")
|
||||
if err == nil {
|
||||
sessionString := cookie.Value
|
||||
if sessionString != "" {
|
||||
configuration.Lock()
|
||||
defer func() { configuration.UnlockAndSave() }()
|
||||
configuration.LockSessions()
|
||||
defer func() { configuration.UnlockSessionsAndSave() }()
|
||||
_, ok := configuration.ServerSettings.Sessions[sessionString]
|
||||
if ok {
|
||||
return useSession(w, sessionString, true)
|
||||
return useSession(w, sessionString)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks if a session is still valid. Changes the session string if it has
|
||||
// been used for more than an hour to limit session hijacking
|
||||
// useSession checks if a session is still valid. It Changes the session string
|
||||
// if it has // been used for more than an hour to limit session hijacking
|
||||
// Returns true if session is still valid
|
||||
// Returns false if session is invalid (and deletes it)
|
||||
func useSession(w http.ResponseWriter, sessionString string, isLocked bool) bool {
|
||||
if !isLocked {
|
||||
configuration.Lock()
|
||||
defer func() { configuration.UnlockAndSave() }()
|
||||
}
|
||||
func useSession(w http.ResponseWriter, sessionString string) bool {
|
||||
session := configuration.ServerSettings.Sessions[sessionString]
|
||||
if session.ValidUntil < time.Now().Unix() {
|
||||
delete(configuration.ServerSettings.Sessions, sessionString)
|
||||
return false
|
||||
}
|
||||
if session.RenewAt < time.Now().Unix() {
|
||||
createSession(w, true)
|
||||
CreateSession(w, true)
|
||||
delete(configuration.ServerSettings.Sessions, sessionString)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Creates a new session - called after login with correct username / password
|
||||
func createSession(w http.ResponseWriter, isLocked bool) {
|
||||
// CreateSession creates a new session - called after login with correct username / password
|
||||
func CreateSession(w http.ResponseWriter, isLocked bool) {
|
||||
if !isLocked {
|
||||
configuration.Lock()
|
||||
defer func() { configuration.UnlockAndSave() }()
|
||||
configuration.LockSessions()
|
||||
defer func() { configuration.UnlockSessionsAndSave() }()
|
||||
}
|
||||
sessionString := helper.GenerateRandomString(60)
|
||||
configuration.ServerSettings.Sessions[sessionString] = sessionstructure.Session{
|
||||
configuration.ServerSettings.Sessions[sessionString] = models.Session{
|
||||
RenewAt: time.Now().Add(time.Hour).Unix(),
|
||||
ValidUntil: time.Now().Add(cookieLifeAdmin).Unix(),
|
||||
}
|
||||
writeSessionCookie(w, sessionString, time.Now().Add(cookieLifeAdmin))
|
||||
}
|
||||
|
||||
// Logs out user and deletes session
|
||||
func logoutSession(w http.ResponseWriter, r *http.Request) {
|
||||
// LogoutSession logs out user and deletes session
|
||||
func LogoutSession(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie("session_token")
|
||||
if err == nil {
|
||||
configuration.Lock()
|
||||
configuration.LockSessions()
|
||||
delete(configuration.ServerSettings.Sessions, cookie.Value)
|
||||
configuration.UnlockAndSave()
|
||||
configuration.UnlockSessionsAndSave()
|
||||
}
|
||||
writeSessionCookie(w, "", time.Now())
|
||||
}
|
||||
92
internal/webserver/sessionmanager/SessionManager_test.go
Normal file
92
internal/webserver/sessionmanager/SessionManager_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package sessionmanager
|
||||
|
||||
import (
|
||||
"Gokapi/internal/configuration"
|
||||
"Gokapi/internal/test"
|
||||
"Gokapi/internal/test/testconfiguration"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var newSession string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testconfiguration.Create(true)
|
||||
configuration.Load()
|
||||
exitVal := m.Run()
|
||||
testconfiguration.Delete()
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
func getRecorder(cookies []test.Cookie) (*httptest.ResponseRecorder, *http.Request) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
if cookies != nil {
|
||||
for _, cookie := range cookies {
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: cookie.Name,
|
||||
Value: cookie.Value,
|
||||
Path: "/",
|
||||
})
|
||||
}
|
||||
}
|
||||
return w, r
|
||||
}
|
||||
|
||||
func TestIsValidSession(t *testing.T) {
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder(nil)), false)
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "invalid"},
|
||||
})), false)
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "expiredsession"},
|
||||
})), false)
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "validsession"},
|
||||
})), true)
|
||||
w, r := getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: "needsRenewal"},
|
||||
})
|
||||
test.IsEqualBool(t, IsValidSession(w, r), true)
|
||||
cookies := w.Result().Cookies()
|
||||
test.IsEqualInt(t, len(cookies), 1)
|
||||
test.IsEqualString(t, cookies[0].Name, "session_token")
|
||||
session := cookies[0].Value
|
||||
test.IsEqualInt(t, len(session), 60)
|
||||
test.IsNotEqualString(t, session, "needsRenewal")
|
||||
}
|
||||
|
||||
func TestCreateSession(t *testing.T) {
|
||||
w, _ := getRecorder(nil)
|
||||
CreateSession(w, false)
|
||||
cookies := w.Result().Cookies()
|
||||
test.IsEqualInt(t, len(cookies), 1)
|
||||
test.IsEqualString(t, cookies[0].Name, "session_token")
|
||||
newSession = cookies[0].Value
|
||||
test.IsEqualInt(t, len(newSession), 60)
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: newSession},
|
||||
})), true)
|
||||
}
|
||||
|
||||
func TestLogoutSession(t *testing.T) {
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: newSession},
|
||||
})), true)
|
||||
LogoutSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: newSession},
|
||||
}))
|
||||
test.IsEqualBool(t, IsValidSession(getRecorder([]test.Cookie{{
|
||||
Name: "session_token",
|
||||
Value: newSession},
|
||||
})), false)
|
||||
}
|
||||
Reference in New Issue
Block a user