Skip to content

Commit 69843bc

Browse files
committed
Fix user update regression in 1a26f0a
1 parent 1a26f0a commit 69843bc

File tree

4 files changed

+34
-32
lines changed

4 files changed

+34
-32
lines changed

auth/memory.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package auth
22

33
import (
4+
"context"
45
"errors"
56
"log"
67
"net/http"
@@ -10,18 +11,18 @@ import (
1011

1112
// MemoryAuthenticator is an Authenticator implementation using an array to store tokens.
1213
type MemoryAuthenticator struct {
13-
Users *xsync.MapOf[string, string]
14-
userUpdates chan []byte
15-
Tokens *xsync.MapOf[string, string]
14+
Users *xsync.MapOf[string, string]
15+
stopUserUpdates context.CancelFunc
16+
Tokens *xsync.MapOf[string, string]
1617
}
1718

1819
// NewMemoryAuthenticator initializes an authenticator using memory for token storage.
1920
func NewMemoryAuthenticator(usersJsonPath string) *MemoryAuthenticator {
20-
users, userUpdates := createUserStore(usersJsonPath)
21+
users, stopUserUpdates := createUserStore(usersJsonPath)
2122
return &MemoryAuthenticator{
22-
Users: users,
23-
userUpdates: userUpdates,
24-
Tokens: xsync.NewMapOf[string, string](),
23+
Users: users,
24+
stopUserUpdates: stopUserUpdates,
25+
Tokens: xsync.NewMapOf[string, string](),
2526
}
2627
}
2728

@@ -100,6 +101,6 @@ func (a *MemoryAuthenticator) Logout(token string) (bool, error) {
100101

101102
// Close closes the authenticator. Once closed, the authenticator should not be used.
102103
func (a *MemoryAuthenticator) Close() error {
103-
close(a.userUpdates)
104+
a.stopUserUpdates()
104105
return nil
105106
}

auth/redis.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package auth
22

33
import (
4+
"context"
45
"errors"
56
"log"
67
"net/http"
@@ -12,15 +13,15 @@ import (
1213

1314
// RedisAuthenticator is an Authenticator implementation using Redis to store tokens.
1415
type RedisAuthenticator struct {
15-
Users *xsync.MapOf[string, string]
16-
userUpdates chan []byte
17-
Redis *redis.Pool
18-
URL string
16+
Users *xsync.MapOf[string, string]
17+
stopUserUpdates context.CancelFunc
18+
Redis *redis.Pool
19+
URL string
1920
}
2021

2122
// NewRedisAuthenticator initializes an authenticator using Redis for token storage.
2223
func NewRedisAuthenticator(usersJsonPath string, url string) *RedisAuthenticator {
23-
users, userUpdates := createUserStore(usersJsonPath)
24+
users, stopUserUpdates := createUserStore(usersJsonPath)
2425
pool := &redis.Pool{
2526
Wait: true,
2627
MaxIdle: 5,
@@ -33,7 +34,7 @@ func NewRedisAuthenticator(usersJsonPath string, url string) *RedisAuthenticator
3334
return conn, err
3435
},
3536
}
36-
return &RedisAuthenticator{Redis: pool, URL: url, Users: users, userUpdates: userUpdates}
37+
return &RedisAuthenticator{Redis: pool, URL: url, Users: users, stopUserUpdates: stopUserUpdates}
3738
}
3839

3940
// GetUser returns info about the user with the given username.
@@ -126,6 +127,6 @@ func (a *RedisAuthenticator) Logout(token string) (bool, error) {
126127

127128
// Close closes the authenticator. Once closed, the authenticator should not be used.
128129
func (a *RedisAuthenticator) Close() error {
129-
close(a.userUpdates)
130+
a.stopUserUpdates()
130131
return a.Redis.Close()
131132
}

auth/users.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package auth
22

33
import (
4+
"context"
45
"crypto/rand"
56
"encoding/base64"
67
"encoding/json"
@@ -24,7 +25,7 @@ func ValidateUsername(username string) string {
2425
return ""
2526
}
2627

27-
func createUserStore(usersJsonPath string) (*xsync.MapOf[string, string], chan []byte) {
28+
func createUserStore(usersJsonPath string) (*xsync.MapOf[string, string], context.CancelFunc) {
2829
// Create default users.json file
2930
_, err := os.Stat(usersJsonPath)
3031
if os.IsNotExist(err) {
@@ -42,13 +43,17 @@ func createUserStore(usersJsonPath string) (*xsync.MapOf[string, string], chan [
4243
}
4344

4445
users := xsync.NewMapOf[string, string]()
45-
initialFile, updates, err := system.ReadAndWatchFile(usersJsonPath)
46+
fileUpdates, cancel, err := system.ReadAndWatchFile(usersJsonPath)
4647
if err != nil {
48+
// panic here, as this is critical for authenticator and we don't want to continue without it
4749
log.Panicln("An error occurred while reading " + usersJsonPath + "! " + err.Error())
4850
}
4951
go (func() {
5052
for {
51-
newFile := <-updates
53+
newFile, ok := <-fileUpdates
54+
if !ok {
55+
return
56+
}
5257
var usersJson map[string]string
5358
err = json.Unmarshal(newFile, &usersJson)
5459
if err != nil {
@@ -58,14 +63,7 @@ func createUserStore(usersJsonPath string) (*xsync.MapOf[string, string], chan [
5863
updateUserStoreFromMap(users, usersJson)
5964
}
6065
})()
61-
var usersJson map[string]string
62-
err = json.Unmarshal(initialFile, &usersJson)
63-
if err != nil {
64-
log.Println("An error occurred while parsing " + usersJsonPath + "! " + err.Error())
65-
return users, updates
66-
}
67-
updateUserStoreFromMap(users, usersJson)
68-
return users, updates
66+
return users, cancel
6967
}
7068

7169
func updateUserStoreFromMap(users *xsync.MapOf[string, string], userMap map[string]string) error {

system/watch.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@ package system
22

33
import (
44
"bytes"
5+
"context"
56
"log"
67
"os"
78
"time"
89
)
910

1011
// ReadAndWatchFile reads a file and returns its contents.
1112
// It also starts a goroutine that watches for changes to the file and sends updates on a channel.
12-
func ReadAndWatchFile(filePath string) ([]byte, chan []byte, error) {
13+
func ReadAndWatchFile(filePath string) (<-chan []byte, context.CancelFunc, error) {
1314
file, err := os.ReadFile(filePath)
1415
if err != nil {
1516
return nil, nil, err
1617
}
18+
ctx, cancel := context.WithCancel(context.Background())
1719
channel := make(chan []byte, 1)
20+
channel <- file // Send the initial file content to the channel
1821
go (func() {
1922
for {
2023
select {
21-
case _, more := <-channel:
22-
if !more {
23-
return
24-
}
24+
case <-ctx.Done():
25+
close(channel)
26+
return
2527
case <-time.After(1 * time.Second):
2628
}
2729
newFile, err := os.ReadFile(filePath)
@@ -35,5 +37,5 @@ func ReadAndWatchFile(filePath string) ([]byte, chan []byte, error) {
3537
}
3638
}
3739
})()
38-
return file, channel, nil
40+
return channel, cancel, nil
3941
}

0 commit comments

Comments
 (0)