mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
fix(clients): сохранять авторизацию при ошибке записи базы
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
@@ -61,16 +62,18 @@ func (db *DB) Add(clientID, comment string) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
db.data.Clients[clientID] = ClientInfo{Comment: comment}
|
||||
return db.save()
|
||||
next := Data{Clients: maps.Clone(db.data.Clients)}
|
||||
next.Clients[clientID] = ClientInfo{Comment: comment}
|
||||
return db.save(next)
|
||||
}
|
||||
|
||||
func (db *DB) Remove(clientID string) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
delete(db.data.Clients, clientID)
|
||||
return db.save()
|
||||
next := Data{Clients: maps.Clone(db.data.Clients)}
|
||||
delete(next.Clients, clientID)
|
||||
return db.save(next)
|
||||
}
|
||||
|
||||
func (db *DB) List() map[string]ClientInfo {
|
||||
@@ -126,8 +129,8 @@ func (db *DB) loadIfModified() {
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) save() error {
|
||||
b, err := json.MarshalIndent(db.data, "", " ")
|
||||
func (db *DB) save(next Data) error {
|
||||
b, err := json.MarshalIndent(next, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,6 +141,8 @@ func (db *DB) save() error {
|
||||
err = os.Rename(tmpFile, db.path)
|
||||
}
|
||||
if err == nil {
|
||||
// Авторизация меняется только после успешной замены файла.
|
||||
db.data = next
|
||||
stat, _ := os.Stat(db.path)
|
||||
if stat != nil {
|
||||
db.lastModified = stat.ModTime()
|
||||
|
||||
@@ -2,11 +2,55 @@ package clientsdb
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFailedSavePreservesAuthorization(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "clients.json")
|
||||
db, err := New(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.Add("existing", "original"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Каталог вместо временного файла воспроизводит отказ записи без прав root.
|
||||
if err := os.Mkdir(path+".tmp", 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
operations := []struct {
|
||||
name string
|
||||
run func() error
|
||||
}{
|
||||
{"add", func() error { return db.Add("new", "new") }},
|
||||
{"update", func() error { return db.Add("existing", "changed") }},
|
||||
{"remove", func() error { return db.Remove("existing") }},
|
||||
}
|
||||
for _, op := range operations {
|
||||
t.Run(op.name, func(t *testing.T) {
|
||||
if err := op.run(); err == nil {
|
||||
t.Fatal("save unexpectedly succeeded")
|
||||
}
|
||||
if !db.IsAuthorized("existing") || db.IsAuthorized("new") {
|
||||
t.Fatal("failed save changed authorization")
|
||||
}
|
||||
if got := db.List(); len(got) != 1 || got["existing"].Comment != "original" {
|
||||
t.Fatalf("failed save changed clients: %+v", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
loaded, err := New(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := loaded.List(); len(got) != 1 || got["existing"].Comment != "original" {
|
||||
t.Fatalf("disk changed: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientsDB(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
dbPath := filepath.Join(tmpDir, "clients.json")
|
||||
|
||||
Reference in New Issue
Block a user