Minor refactoring and adding of comments

This commit is contained in:
Marc Ole Bulling
2025-05-25 17:07:06 +02:00
parent 6d68134240
commit 20ee8cbfa4
10 changed files with 85 additions and 53 deletions

View File

@@ -71,26 +71,25 @@ func updateConfig(settings *models.Configuration, env *environment.Environment)
fmt.Println("--> See the release notes for more information")
osExit(1)
return
} else {
fmt.Println("Setting admin user to " + adminUser)
settings.Authentication.Username = adminUser
}
if settings.Authentication.Method == models.AuthenticationOAuth2 && len(oldAuth.Authentication.OAuthUsers) > 0 {
LegacyUsersHeaderOauth = oldAuth.Authentication.OAuthUsers
settings.Authentication.OnlyRegisteredUsers = true
}
if settings.Authentication.Method == models.AuthenticationHeader && len(oldAuth.Authentication.HeaderUsers) > 0 {
LegacyUsersHeaderOauth = oldAuth.Authentication.HeaderUsers
settings.Authentication.OnlyRegisteredUsers = true
}
for _, user := range LegacyUsersHeaderOauth {
if strings.Contains(user, "*") {
fmt.Println("FAILED UPDATE")
fmt.Println("--> If using Oauth or Header authentication and restricting the users, please remove any wildcards before upgrading.")
fmt.Println("--> See the release notes for more information")
osExit(1)
return
}
fmt.Println("Setting admin user to " + adminUser)
settings.Authentication.Username = adminUser
}
if settings.Authentication.Method == models.AuthenticationOAuth2 && len(oldAuth.Authentication.OAuthUsers) > 0 {
LegacyUsersHeaderOauth = oldAuth.Authentication.OAuthUsers
settings.Authentication.OnlyRegisteredUsers = true
}
if settings.Authentication.Method == models.AuthenticationHeader && len(oldAuth.Authentication.HeaderUsers) > 0 {
LegacyUsersHeaderOauth = oldAuth.Authentication.HeaderUsers
settings.Authentication.OnlyRegisteredUsers = true
}
for _, user := range LegacyUsersHeaderOauth {
if strings.Contains(user, "*") {
fmt.Println("FAILED UPDATE")
fmt.Println("--> If using Oauth or Header authentication and restricting the users, please remove any wildcards before upgrading.")
fmt.Println("--> See the release notes for more information")
osExit(1)
return
}
}
}

View File

@@ -39,9 +39,8 @@ func GetAll() (string, bool) {
content, err := os.ReadFile(logPath)
helper.Check(err)
return string(content), true
} else {
return fmt.Sprintf("[%s] No log file found!", categoryWarning), false
}
return fmt.Sprintf("[%s] No log file found!", categoryWarning), false
}
// createLogEntry adds a line to the logfile including the current date. Also outputs to Stdout if set.
@@ -159,6 +158,8 @@ func UpgradeToV2() {
defer mutex.Unlock()
}
// DeleteLogs removes all logs before the cutoff timestamp and inserts a new log that the user
// deleted the previous logs
func DeleteLogs(userName string, userId int, cutoff int64, r *http.Request) {
if cutoff == 0 {
deleteAllLogs(userName, userId, r)

View File

@@ -45,6 +45,7 @@ type ApiKey struct {
UserId int `json:"UserId" redis:"UserId"`
}
// ApiPermission contains zero or more permissions as an uint8 format
type ApiPermission uint8
// GetReadableDate returns the date as YYYY-MM-DD HH:MM:SS

View File

@@ -32,27 +32,27 @@ type File struct {
// FileApiOutput will be displayed for public outputs from the ID, hiding sensitive information
type FileApiOutput struct {
Id string `json:"Id"` // The internal ID of the file
Name string `json:"Name"` // The filename. Will be 'Encrypted file' for end-to-end encrypted files
Size string `json:"Size"` // Filesize in a human-readable format
HotlinkId string `json:"HotlinkId"` // If file is a picture file and can be hotlinked, this is the ID for the hotlink
ContentType string `json:"ContentType"` // The MIME type for the file
ExpireAtString string `json:"ExpireAtString"` // Time expiry in a human-readable format in local time
UrlDownload string `json:"UrlDownload"` // The public download URL for the file
UrlHotlink string `json:"UrlHotlink"` // The public hotlink URL for the file
UploadDate int64 `json:"UploadDate" redis:"UploadDate"` // UTC timestamp of upload time
ExpireAt int64 `json:"ExpireAt"` // "UTC timestamp of file expiry
SizeBytes int64 `json:"SizeBytes"` // Filesize in bytes
DownloadsRemaining int `json:"DownloadsRemaining"` // The remaining downloads for this file
DownloadCount int `json:"DownloadCount"` // The amount of times the file has been downloaded
UnlimitedDownloads bool `json:"UnlimitedDownloads"` // True if the uploader did not limit the downloads
UnlimitedTime bool `json:"UnlimitedTime"` // True if the uploader did not limit the time
RequiresClientSideDecryption bool `json:"RequiresClientSideDecryption"` // True if the file has to be decrypted client-side
IsEncrypted bool `json:"IsEncrypted"` // True if the file is encrypted
IsEndToEndEncrypted bool `json:"IsEndToEndEncrypted"` // True if the file is end-to-end encrypted
IsPasswordProtected bool `json:"IsPasswordProtected"` // True if a password has to be entered before downloading the file
IsSavedOnLocalStorage bool `json:"IsSavedOnLocalStorage"` // True if the file does not use cloud storage
UploaderId int `json:"UploaderId"` // The user ID of the uploader
Id string `json:"Id"` // The internal ID of the file
Name string `json:"Name"` // The filename. Will be 'Encrypted file' for end-to-end encrypted files
Size string `json:"Size"` // Filesize in a human-readable format
HotlinkId string `json:"HotlinkId"` // If file is a picture file and can be hotlinked, this is the ID for the hotlink
ContentType string `json:"ContentType"` // The MIME type for the file
ExpireAtString string `json:"ExpireAtString"` // Time expiry in a human-readable format in local time
UrlDownload string `json:"UrlDownload"` // The public download URL for the file
UrlHotlink string `json:"UrlHotlink"` // The public hotlink URL for the file
UploadDate int64 `json:"UploadDate"` // UTC timestamp of upload time
ExpireAt int64 `json:"ExpireAt"` // "UTC timestamp of file expiry
SizeBytes int64 `json:"SizeBytes"` // Filesize in bytes
DownloadsRemaining int `json:"DownloadsRemaining"` // The remaining downloads for this file
DownloadCount int `json:"DownloadCount"` // The amount of times the file has been downloaded
UnlimitedDownloads bool `json:"UnlimitedDownloads"` // True if the uploader did not limit the downloads
UnlimitedTime bool `json:"UnlimitedTime"` // True if the uploader did not limit the time
RequiresClientSideDecryption bool `json:"RequiresClientSideDecryption"` // True if the file has to be decrypted client-side
IsEncrypted bool `json:"IsEncrypted"` // True if the file is encrypted
IsEndToEndEncrypted bool `json:"IsEndToEndEncrypted"` // True if the file is end-to-end encrypted
IsPasswordProtected bool `json:"IsPasswordProtected"` // True if a password has to be entered before downloading the file
IsSavedOnLocalStorage bool `json:"IsSavedOnLocalStorage"` // True if the file does not use cloud storage
UploaderId int `json:"UploaderId"` // The user ID of the uploader
}
// EncryptionInfo holds information about the encryption used on the file

View File

@@ -6,8 +6,10 @@ import (
"time"
)
// UserPermission contains zero or more permissions as uint16
type UserPermission uint16
// User contains information about the Gokapi user
type User struct {
Id int `json:"id" redis:"id"`
Name string `json:"name" redis:"Name"`
@@ -50,30 +52,51 @@ func (u *User) ToJson() string {
return string(result)
}
// UserLevelSuperAdmin indicates that this is the single user with the most permissions
const UserLevelSuperAdmin UserRank = 0
// UserLevelAdmin indicates that this user has by default all permissions (unless they affect the super-admin)
const UserLevelAdmin UserRank = 1
// UserLevelUser indicates that this user has only basic permissions by default
const UserLevelUser UserRank = 2
// UserRank indicates the rank that is assigned to the user
type UserRank uint8
// IsSuperAdmin returns true if the user has the Rank UserLevelSuperAdmin
func (u *User) IsSuperAdmin() bool {
return u.UserLevel == UserLevelSuperAdmin
}
// IsSameUser returns true, if the user has the same ID
func (u *User) IsSameUser(userId int) bool {
return u.Id == userId
}
const (
// UserPermReplaceUploads allows to replace uploads
UserPermReplaceUploads UserPermission = 1 << iota
// UserPermListOtherUploads allows to also list uploads by other users
UserPermListOtherUploads
// UserPermEditOtherUploads allows editing of uploads by other users
UserPermEditOtherUploads
// UserPermReplaceOtherUploads allows replacing of uploads by other users
UserPermReplaceOtherUploads
// UserPermDeleteOtherUploads allows deleting uploads by other users
UserPermDeleteOtherUploads
// UserPermManageLogs allows viewing and deleting logs
UserPermManageLogs
// UserPermManageApiKeys allows editing and deleting of API keys by other users
UserPermManageApiKeys
// UserPermManageUsers allows creating and editing of users, including granting and revoking permissions
UserPermManageUsers
)
// UserPermissionNone means that the user has no permissions
const UserPermissionNone UserPermission = 0
// UserPermissionAll means that the user has all permissions
const UserPermissionAll UserPermission = 255
// GrantPermission grants one or more permissions

View File

@@ -921,8 +921,7 @@ func requireLogin(next http.HandlerFunc, isUiCall, isPwChangeView bool) http.Han
return
}
}
c := context.WithValue(r.Context(), "user", user)
r = r.WithContext(c)
r = authentication.SetUserInRequest(r, user)
next.ServeHTTP(w, r)
return
}

View File

@@ -373,10 +373,8 @@ func apiChunkComplete(w http.ResponseWriter, r requestParser, user models.User)
go doBlockingPartCompleteChunk(nil, request, user)
_, _ = io.WriteString(w, "{\"result\":\"OK\"}")
return
} else {
doBlockingPartCompleteChunk(w, request, user)
}
doBlockingPartCompleteChunk(w, request, user)
}
func doBlockingPartCompleteChunk(w http.ResponseWriter, request *paramChunkComplete, user models.User) {

View File

@@ -824,7 +824,7 @@ func getApiPermMap(t *testing.T) map[models.ApiPermission]string {
result[models.ApiPermManageLogs] = "PERM_MANAGE_LOGS"
sum := 0
for perm, _ := range result {
for perm := range result {
sum = sum + int(perm)
}
if sum != int(models.ApiPermAll) {
@@ -846,7 +846,7 @@ func getUserPermMap(t *testing.T) map[models.UserPermission]string {
result[models.UserPermManageUsers] = "PERM_USERS"
sum := 0
for perm, _ := range result {
for perm := range result {
sum = sum + int(perm)
}
if sum != int(models.UserPermissionAll) {

View File

@@ -1,6 +1,7 @@
package authentication
import (
"context"
"crypto/subtle"
"encoding/json"
"errors"
@@ -18,9 +19,13 @@ import (
"strings"
)
type userNameContext string
// CookieOauth is the cookie name used for login
const CookieOauth = "state"
const userNameContextKey userNameContext = "userName"
var authSettings models.AuthenticationConfig
// Init needs to be called first to process the authentication configuration
@@ -71,15 +76,22 @@ func checkAuthConfig(config models.AuthenticationConfig) error {
}
}
// GetUserFromRequest returns the user that has been authenticated with the request
func GetUserFromRequest(r *http.Request) (models.User, error) {
c := r.Context()
user, ok := c.Value("user").(models.User)
user, ok := c.Value(userNameContextKey).(models.User)
if !ok {
return models.User{}, errors.New("user not found in context")
}
return user, nil
}
// SetUserInRequest saves the user that has been authenticated with the request
func SetUserInRequest(r *http.Request, user models.User) *http.Request {
c := context.WithValue(r.Context(), userNameContextKey, user)
return r.WithContext(c)
}
// IsAuthenticated returns true and the user ID if authenticated
func IsAuthenticated(w http.ResponseWriter, r *http.Request) (models.User, bool) {
switch authSettings.Method {

View File

@@ -195,7 +195,7 @@ func TestGetUserFromRequest(t *testing.T) {
_, r := test.GetRecorder("GET", "/", nil, nil, nil)
_, err := GetUserFromRequest(r)
test.IsNotNil(t, err)
c := context.WithValue(r.Context(), "user", "invalid")
c := context.WithValue(r.Context(), userNameContextKey, "invalid")
rInvalid := r.WithContext(c)
_, err = GetUserFromRequest(rInvalid)
test.IsNotNil(t, err)
@@ -210,8 +210,7 @@ func TestGetUserFromRequest(t *testing.T) {
ResetPassword: true,
}
c = context.WithValue(r.Context(), "user", user)
rValid := r.WithContext(c)
rValid := SetUserInRequest(r, user)
retrievedUser, err := GetUserFromRequest(rValid)
test.IsNil(t, err)
test.IsEqual(t, retrievedUser, user)