added mutexes to users.json
authorPhiTux <redacted>
Wed, 13 Aug 2025 12:53:01 +0000 (14:53 +0200)
committerPhiTux <redacted>
Wed, 13 Aug 2025 12:53:01 +0000 (14:53 +0200)
backend/handlers/users.go
backend/utils/file_handling.go
backend/utils/helpers.go
backend/utils/migration.go
backend/utils/security.go

index 648d520693cc4834b5c57ce75048ffb9efd9c013..5d9ef2f9cbb6cf92f2073c6ea711cda6b909d0bc 100644 (file)
@@ -39,8 +39,6 @@ func Login(w http.ResponseWriter, r *http.Request) {
        usersList, ok := users["users"].([]any)
        if !ok || len(usersList) == 0 {
                utils.Logger.Printf("Login failed. User '%s' not found", req.Username)
-               /* http.Error(w, "User/Password combination not found", http.StatusNotFound)
-               return */
        }
 
        // Find user
@@ -233,6 +231,7 @@ type RegisterRequest struct {
 }
 
 // Register handles user registration
+// The API endpoint
 func RegisterHandler(w http.ResponseWriter, r *http.Request) {
        // Parse the request body
        var req RegisterRequest
@@ -252,7 +251,11 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) {
        })
 }
 
+// The actual register function (can also be called from migration)
 func Register(username string, password string) (bool, error) {
+       utils.UsersFileMutex.Lock()
+       defer utils.UsersFileMutex.Unlock()
+
        // Get users
        users, err := utils.GetUsers()
        if err != nil {
@@ -685,6 +688,9 @@ func ChangePassword(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       utils.UsersFileMutex.Lock()
+       defer utils.UsersFileMutex.Unlock()
+
        // Get user data
        users, err := utils.GetUsers()
        if err != nil {
@@ -883,6 +889,9 @@ func DeleteAccount(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       utils.UsersFileMutex.Lock()
+       defer utils.UsersFileMutex.Unlock()
+
        // Get User data
        users, err := utils.GetUsers()
        if err != nil {
@@ -924,6 +933,8 @@ func DeleteAccount(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       utils.UsersFileMutex.Unlock()
+
        // Delete directory of the user with all his data
        if err := utils.DeleteUserData(userID); err != nil {
                utils.JSONResponse(w, http.StatusOK, map[string]any{
index 54ddaf5a90d51dc06494491ae3814ebda5f4a7c0..39dc79c81d026265160cb197b435435198d5cf62 100644 (file)
@@ -13,15 +13,12 @@ import (
 
 // Mutexes für Dateizugriffe
 var (
-       usersFileMutex    sync.RWMutex // Für users.json
+       UsersFileMutex    sync.RWMutex // Für users.json
        userSettingsMutex sync.RWMutex // Für Benutzereinstellungen
 )
 
 // GetUsers retrieves the users from the users.json file
 func GetUsers() (map[string]any, error) {
-       usersFileMutex.RLock()
-       defer usersFileMutex.RUnlock()
-
        // Try to open the users.json file
        filePath := filepath.Join(Settings.DataPath, "users.json")
        file, err := os.Open(filePath)
@@ -51,8 +48,6 @@ func GetUsers() (map[string]any, error) {
 
 // WriteUsers writes the users to the users.json file
 func WriteUsers(content map[string]any) error {
-       usersFileMutex.Lock()
-       defer usersFileMutex.Unlock()
 
        // Create the users.json file
        filePath := filepath.Join(Settings.DataPath, "users.json")
@@ -461,6 +456,9 @@ func DeleteUserData(userID int) error {
 
 // saves the hash, salt and encrypted derived key of the backup codes to the users.json file
 func SaveBackupCodes(userID int, codes []map[string]any) error {
+       UsersFileMutex.Lock()
+       defer UsersFileMutex.Unlock()
+
        // Get the current users
        users, err := GetUsers()
        if err != nil {
index 5cfa4526cc1bde21bc2487ee6062a768688820b9..6fee5fdb62542dcecf78c62b17d753bcc1f9ed4a 100644 (file)
@@ -7,6 +7,7 @@ import (
        "log"
        "net/http"
        "os"
+       "strings"
 )
 
 // Global logger
@@ -81,6 +82,16 @@ func InitSettings() error {
        }
        fmt.Printf("Logout After Days: %d\n", Settings.LogoutAfterDays)
 
+       if allowedHosts := os.Getenv("ALLOWED_HOSTS"); allowedHosts != "" {
+               // Split allowedHosts by comma and trim spaces
+               hosts := strings.Split(allowedHosts, ",")
+               for i, host := range hosts {
+                       hosts[i] = strings.TrimSpace(host)
+               }
+               Settings.AllowedHosts = hosts
+       }
+       fmt.Printf("Allowed Hosts: %v\n", Settings.AllowedHosts)
+
        if indent := os.Getenv("INDENT"); indent != "" {
                // Parse indent to int
                var ind int
index 7c9b59c6cb4d308ce22de64fc6b1c4c8b2bbd423..f86f6fe719a299cbe4c3edb1aef7ffd7b0b324fd 100644 (file)
@@ -52,8 +52,7 @@ func SetUserMigrating(username string, migrating bool) {
 // Reference: https://github.com/fernet/spec/blob/master/Spec.md
 
 const (
-       fernetVersion byte  = 0x80
-       maxClockSkew  int64 = 60 // seconds
+       fernetVersion byte = 0x80
 )
 
 // FernetDecrypt decrypts a Fernet token using the given key
@@ -75,26 +74,12 @@ func FernetDecrypt(token string, key []byte) (string, error) {
        }
 
        // Extract parts
-       // timestamp := tokenBytes[1:9]
        iv := tokenBytes[9:25]
        ciphertext := tokenBytes[25 : len(tokenBytes)-32]
-       // hmacValue := tokenBytes[len(tokenBytes)-32:]
 
        // Generate encryption key from the master key
-       // signingKey := key[:16] // Unused for now, will be needed if HMAC verification is enabled
        encryptionKey := key[16:32]
 
-       // Verify HMAC (optional for migration, commented out for now)
-       // TODO: Uncomment if signature verification is needed
-       /*
-               h := hmac.New(sha256.New, signingKey)
-               h.Write(tokenBytes[:len(tokenBytes)-32])
-               calculatedHMAC := h.Sum(nil)
-               if subtle.ConstantTimeCompare(calculatedHMAC, hmacValue) != 1 {
-                       return "", fmt.Errorf("invalid token signature")
-               }
-       */
-
        // Create cipher
        block, err := aes.NewCipher(encryptionKey)
        if err != nil {
index 8a3642c405a0b9bf6ef57bdd55faa943c9822c21..67959f41ac80dc5d3e652ef89876b7410edd07f3 100644 (file)
@@ -413,6 +413,9 @@ func GetEncryptionKey(userID int, derivedKey string) (string, error) {
 // Returns the derivedKey, if successfully validating password, otherwise empty string
 // Return the amount of backup codes available for the user (-1 if password does not match or if backup code was NOT used).
 func CheckPasswordForUser(userID int, password string) (string, int, error) {
+       UsersFileMutex.Lock()
+       defer UsersFileMutex.Unlock()
+
        // Get users
        users, err := GetUsers()
        if err != nil {
git clone https://git.99rst.org/PROJECT