Better error handling for permission errors or other file related errors #326

This commit is contained in:
Marc Ole Bulling
2025-10-19 21:10:35 +02:00
parent 077570c0ff
commit f68efc57a2
14 changed files with 122 additions and 62 deletions
+15 -9
View File
@@ -5,12 +5,13 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"strings"
"github.com/forceu/gokapi/cmd/cli-uploader/cliapi"
"github.com/forceu/gokapi/cmd/cli-uploader/cliconstants"
"github.com/forceu/gokapi/cmd/cli-uploader/cliflags"
"github.com/forceu/gokapi/internal/helper"
"os"
"strings"
)
type configFile struct {
@@ -135,17 +136,16 @@ func save(url, apikey string, e2ekey []byte) error {
// Verifies the existence of the configuration file and validates its integrity, terminating on errors.
func Load() {
configPath, _ := cliflags.GetConfigLocation()
if !helper.FileExists(configPath) {
exists, err := helper.FileExists(configPath)
helper.Check(err)
if !exists {
fmt.Println("ERROR: No login information found")
fmt.Println("Please run 'gokapi-cli login' to create a login")
os.Exit(1)
}
data, err := os.ReadFile(configPath)
if err != nil {
fmt.Println("ERROR: Could not read login information")
os.Exit(1)
}
helper.Check(err)
var config configFile
err = json.Unmarshal(data, &config)
if err != nil {
@@ -160,7 +160,13 @@ func Load() {
// It will return an error if the file exists but could not be deleted.
func Delete() error {
configPath, _ := cliflags.GetConfigLocation()
if !helper.FileExists(configPath) {
exists, err := helper.FileExists(configPath)
if err != nil {
fmt.Println("ERROR: Could not check if login information exists")
fmt.Println(err)
os.Exit(1)
}
if exists {
return nil
}
return os.Remove(configPath)
+7 -4
View File
@@ -11,6 +11,10 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"strings"
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
"github.com/forceu/gokapi/internal/configuration/configupgrade"
"github.com/forceu/gokapi/internal/configuration/database"
@@ -19,9 +23,6 @@ import (
"github.com/forceu/gokapi/internal/logging"
"github.com/forceu/gokapi/internal/models"
"github.com/forceu/gokapi/internal/storage/filesystem"
"io"
"os"
"strings"
)
// MinLengthPassword is the required length of admin password in characters
@@ -38,7 +39,9 @@ var usesHttps bool
// Exists returns true if configuration files are present
func Exists() bool {
configPath, _, _, _ := environment.GetConfigPaths()
return helper.FileExists(configPath)
exists, err := helper.FileExists(configPath)
helper.Check(err)
return exists
}
// loadFromFile parses the given file and adds salts, if they are invalid
@@ -2,12 +2,13 @@ package cloudconfig
import (
"fmt"
"io/ioutil"
"os"
"github.com/forceu/gokapi/internal/environment"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
)
// CloudConfig contains all configuration values / credentials for cloud storage
@@ -22,7 +23,9 @@ func Load() (CloudConfig, bool) {
return loadFromEnv(&env), true
}
path := env.ConfigDir + "/cloudconfig.yml"
if helper.FileExists(path) {
exists, err := helper.FileExists(path)
helper.Check(err)
if exists {
return loadFromFile(path)
}
return CloudConfig{}, false
@@ -49,8 +52,10 @@ func Write(config CloudConfig) error {
// Delete removes the cloud config file from the set config path
func Delete() error {
_, _, _, awsConfigPath := environment.GetConfigPaths()
if helper.FileExists(awsConfigPath) {
err := os.Remove(awsConfigPath)
exists, err := helper.FileExists(awsConfigPath)
helper.Check(err)
if exists {
err = os.Remove(awsConfigPath)
if err != nil {
return err
}
+11 -4
View File
@@ -3,12 +3,13 @@ package database
import (
"errors"
"fmt"
"net/url"
"strings"
"github.com/forceu/gokapi/internal/configuration/database/dbabstraction"
"github.com/forceu/gokapi/internal/configuration/database/dbcache"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
"net/url"
"strings"
)
var db dbabstraction.Database
@@ -37,8 +38,14 @@ func ParseUrl(dbUrl string, mustExist bool) (models.DbConnection, error) {
case "sqlite":
result.Type = dbabstraction.TypeSqlite
result.HostUrl = strings.TrimPrefix(dbUrl, "sqlite://")
if mustExist && !helper.FileExists(result.HostUrl) {
return models.DbConnection{}, fmt.Errorf("file %s does not exist\n", result.HostUrl)
if mustExist {
exist, errEx := helper.FileExists(result.HostUrl)
if errEx != nil {
return models.DbConnection{}, errEx
}
if !exist {
return models.DbConnection{}, fmt.Errorf("file %s does not exist\n", result.HostUrl)
}
}
case "redis":
result.Type = dbabstraction.TypeRedis
@@ -4,10 +4,11 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
"os"
"path/filepath"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
// Required for sqlite driver
_ "modernc.org/sqlite"
)
@@ -82,7 +83,9 @@ func (p DatabaseProvider) init(dbConfig models.DbConnection) (DatabaseProvider,
p.sqliteDb.SetMaxOpenConns(5)
p.sqliteDb.SetMaxIdleConns(5)
if !helper.FileExists(dbConfig.HostUrl) {
exists, err := helper.FileExists(dbConfig.HostUrl)
helper.Check(err)
if !exists {
return p, p.createNewDatabase()
}
err = p.sqliteDb.Ping()
+8 -4
View File
@@ -7,10 +7,11 @@ Simplified OS functions
import (
"bufio"
"errors"
"golang.org/x/term"
"log"
"os"
"syscall"
"golang.org/x/term"
)
// FolderExists returns true if a folder exists
@@ -23,12 +24,15 @@ func FolderExists(folder string) bool {
}
// FileExists returns true if a file exists
func FileExists(filename string) bool {
func FileExists(filename string) (bool, error) {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
return false, nil
}
return !info.IsDir()
if err != nil {
return false, err
}
return !info.IsDir(), nil
}
// CreateDir creates the data folder if it does not exist
+10 -5
View File
@@ -2,9 +2,10 @@ package helper
import (
"errors"
"github.com/forceu/gokapi/internal/test"
"os"
"testing"
"github.com/forceu/gokapi/internal/test"
)
func TestIsInArray(t *testing.T) {
@@ -15,16 +16,20 @@ func TestIsInArray(t *testing.T) {
func TestFolderCreation(t *testing.T) {
test.IsEqualBool(t, FolderExists("invalid"), false)
test.FileDoesNotExist(t, "invalid/file")
test.IsEqualBool(t, FileExists("invalid/file"), false)
exists, err := FileExists("invalid/file")
test.IsEqualBool(t, exists, false)
test.IsNil(t, err)
CreateDir("invalid")
test.IsEqualBool(t, FolderExists("invalid"), true)
err := os.WriteFile("invalid/file", []byte("test"), 0644)
err = os.WriteFile("invalid/file", []byte("test"), 0644)
if err != nil {
t.Error(err)
}
test.FileExists(t, "invalid/file")
test.IsEqualBool(t, FileExists("invalid/file"), true)
os.RemoveAll("invalid")
exists, err = FileExists("invalid/file")
test.IsNil(t, err)
test.IsEqualBool(t, exists, true)
_ = os.RemoveAll("invalid")
}
func TestReadLine(t *testing.T) {
+7 -4
View File
@@ -3,15 +3,16 @@ package logging
import (
"bufio"
"fmt"
"github.com/forceu/gokapi/internal/environment"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
"net"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/forceu/gokapi/internal/environment"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
)
var logPath = "config/log.txt"
@@ -35,7 +36,9 @@ func Init(filePath string) {
// GetAll returns all log entries as a single string and if the log file exists
func GetAll() (string, bool) {
if helper.FileExists(logPath) {
exists, err := helper.FileExists(logPath)
helper.Check(err)
if exists {
content, err := os.ReadFile(logPath)
helper.Check(err)
return string(content), true
+13 -10
View File
@@ -10,6 +10,16 @@ import (
"encoding/hex"
"errors"
"fmt"
"io"
"log"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/forceu/gokapi/internal/configuration"
"github.com/forceu/gokapi/internal/configuration/database"
"github.com/forceu/gokapi/internal/encryption"
@@ -25,15 +35,6 @@ import (
"github.com/forceu/gokapi/internal/webserver/headers"
"github.com/forceu/gokapi/internal/webserver/sse"
"github.com/jinzhu/copier"
"io"
"log"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
// ErrorFileTooLarge is an error that is called when a file larger than the set maximum is uploaded
@@ -668,7 +669,9 @@ func FileExists(file models.File, dataDir string) bool {
}
return true
}
return helper.FileExists(dataDir + "/" + file.SHA1)
exists, err := helper.FileExists(dataDir + "/" + file.SHA1)
helper.Check(err)
return exists
}
// CleanUp removes expired files from the config and from the filesystem if they are not referenced by other files anymore
+6 -3
View File
@@ -2,8 +2,6 @@ package chunking
import (
"errors"
"github.com/forceu/gokapi/internal/configuration"
"github.com/forceu/gokapi/internal/helper"
"io"
"mime/multipart"
"net/http"
@@ -12,6 +10,9 @@ import (
"regexp"
"strconv"
"strings"
"github.com/forceu/gokapi/internal/configuration"
"github.com/forceu/gokapi/internal/helper"
)
// ChunkInfo contains info about the current chunk
@@ -173,7 +174,9 @@ func GetFileByChunkId(id string) (*os.File, error) {
// FileExists returns true if a file exists for the given chunk ID
func FileExists(id string) bool {
return helper.FileExists(getChunkFilePath(id))
exists, err := helper.FileExists(getChunkFilePath(id))
helper.Check(err)
return exists
}
// NewChunk allocates the space for the new file and writes the chunk
@@ -2,11 +2,12 @@ package localstorage
import (
"errors"
"os"
"strings"
"github.com/forceu/gokapi/internal/helper"
"github.com/forceu/gokapi/internal/models"
fileInterfaces "github.com/forceu/gokapi/internal/storage/filesystem/interfaces"
"os"
"strings"
)
// GetDriver returns a driver for the local file system
@@ -95,7 +96,9 @@ type localFile struct {
// Exists returns true if the file exists
func (f *localFile) Exists() bool {
return helper.FileExists(f.Directory + f.Filename)
exists, err := helper.FileExists(f.Directory + f.Filename)
helper.Check(err)
return exists
}
// GetName returns the name of the file
+12 -4
View File
@@ -38,9 +38,15 @@ func loadCustomCssJsInfo(webserverDir fs.FS) {
return
}
customStaticInfo.Version = strconv.Itoa(readCustomStaticVersion())
customStaticInfo.UseCustomCss = helper.FileExists(pathCustomCss)
customStaticInfo.UseCustomPublicJs = helper.FileExists(pathCustomPublicJs)
customStaticInfo.UseCustomAdminJs = helper.FileExists(pathCustomAdminJs)
exists, err := helper.FileExists(pathCustomCss)
helper.Check(err)
customStaticInfo.UseCustomCss = exists
exists, err = helper.FileExists(pathCustomPublicJs)
helper.Check(err)
customStaticInfo.UseCustomPublicJs = exists
exists, err = helper.FileExists(pathCustomAdminJs)
helper.Check(err)
customStaticInfo.UseCustomAdminJs = exists
}
func addMuxForCustomContent(mux *http.ServeMux) {
@@ -78,7 +84,9 @@ func serveCustomFile(filePath string, w http.ResponseWriter, r *http.Request) {
}
func readCustomStaticVersion() int {
if !helper.FileExists(pathCustomVersioning) {
exists, err := helper.FileExists(pathCustomVersioning)
helper.Check(err)
if !exists {
return 0
}
file, err := os.Open(pathCustomVersioning)
+3 -1
View File
@@ -29,7 +29,9 @@ var faviconPng512x512 []byte
func Init(pathCustomIcon string, fsDefault fs.FS) {
var imageContent []byte
if helper.FileExists(pathCustomIcon) {
exists, err := helper.FileExists(pathCustomIcon)
helper.Check(err)
if exists {
content, err := os.ReadFile(pathCustomIcon)
helper.Check(err)
imageContent = content
+8 -3
View File
@@ -10,8 +10,6 @@ import (
"encoding/hex"
"encoding/pem"
"fmt"
"github.com/forceu/gokapi/internal/environment"
"github.com/forceu/gokapi/internal/helper"
"io"
"math"
"math/big"
@@ -20,13 +18,20 @@ import (
"os"
"strings"
"time"
"github.com/forceu/gokapi/internal/environment"
"github.com/forceu/gokapi/internal/helper"
)
var configDir string
func isCertificatePresent() bool {
certificate, key := GetCertificateLocations()
return helper.FileExists(certificate) && helper.FileExists(key)
existsCert, err := helper.FileExists(certificate)
helper.Check(err)
existsKey, err := helper.FileExists(key)
helper.Check(err)
return existsCert && existsKey
}
// GetCertificateLocations returns the filepath of the public certificate and private key