Spaces:
Paused
Paused
fix: total rebuild of key handler for stability
Browse files- internal/handler/keys.go +24 -50
internal/handler/keys.go
CHANGED
|
@@ -6,65 +6,39 @@ import (
|
|
| 6 |
"net/http"
|
| 7 |
"os"
|
| 8 |
"sync"
|
| 9 |
-
"time"
|
| 10 |
)
|
| 11 |
-
type KeyData struct {
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
Tokens int `json:"tokens"`
|
| 16 |
-
}
|
| 17 |
-
type KeyStore struct {
|
| 18 |
-
mu sync.RWMutex
|
| 19 |
-
Keys map[string]*KeyData `json:"keys"`
|
| 20 |
-
}
|
| 21 |
-
var store = &KeyStore{Keys: make(map[string]*KeyData)}
|
| 22 |
-
const storePath = "/data/keys.json"
|
| 23 |
func init() {
|
| 24 |
os.MkdirAll("/data", 0755)
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
}
|
| 29 |
-
if store.Keys == nil { store.Keys = make(map[string]*KeyData) }
|
| 30 |
-
}
|
| 31 |
-
func save() {
|
| 32 |
-
data, _ := json.Marshal(store)
|
| 33 |
-
os.WriteFile(storePath, data, 0644)
|
| 34 |
}
|
| 35 |
-
func
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
store.mu.Lock()
|
| 41 |
-
defer store.mu.Unlock()
|
| 42 |
-
store.Keys[key] = &KeyData{Name: name, Key: key}
|
| 43 |
-
save()
|
| 44 |
-
return key
|
| 45 |
}
|
| 46 |
func HandleGenKey(w http.ResponseWriter, r *http.Request) {
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
key := GenerateKey(name)
|
| 50 |
-
fmt.Fprintf(w, "Key creada para %s", name)
|
| 51 |
}
|
| 52 |
func HandleStats(w http.ResponseWriter, r *http.Request) {
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
json.NewEncoder(w).Encode(map[string]interface{}{"keys": res})
|
| 59 |
}
|
| 60 |
func HandleSecretReveal(w http.ResponseWriter, r *http.Request) {
|
| 61 |
-
if r.URL.Query().Get("pass") != "RWPX_S3cr3t_M0d3_#2026_NzQ!" {
|
| 62 |
-
|
| 63 |
-
}
|
| 64 |
-
store.mu.RLock()
|
| 65 |
-
defer store.mu.RUnlock()
|
| 66 |
w.Header().Set("Content-Type", "text/html")
|
| 67 |
-
fmt.Fprint(w, "<body style='background:#000;color:#0f0;font-family:monospace;'>
|
| 68 |
-
for _, k := range
|
| 69 |
-
fmt.Fprint(w, "</body>")
|
| 70 |
}
|
|
|
|
| 6 |
"net/http"
|
| 7 |
"os"
|
| 8 |
"sync"
|
|
|
|
| 9 |
)
|
| 10 |
+
type KeyData struct { Name string; Key string; Tokens int }
|
| 11 |
+
type Store struct { mu sync.Mutex; Keys map[string]*KeyData }
|
| 12 |
+
var s = &Store{Keys: make(map[string]*KeyData)}
|
| 13 |
+
const p = "/data/keys.json"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
func init() {
|
| 15 |
os.MkdirAll("/data", 0755)
|
| 16 |
+
f, _ := os.ReadFile(p)
|
| 17 |
+
json.Unmarshal(f, &s.Keys)
|
| 18 |
+
if s.Keys == nil { s.Keys = make(map[string]*KeyData) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
}
|
| 20 |
+
func save() { b, _ := json.Marshal(s.Keys); os.WriteFile(p, b, 0644) }
|
| 21 |
+
func GenerateKey(n string) string {
|
| 22 |
+
k := fmt.Sprintf("RWPX-%d", rand.Intn(999999))
|
| 23 |
+
s.mu.Lock(); defer s.mu.Unlock()
|
| 24 |
+
s.Keys[k] = &KeyData{Name: n, Key: k}; save(); return k
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
}
|
| 26 |
func HandleGenKey(w http.ResponseWriter, r *http.Request) {
|
| 27 |
+
n := r.FormValue("name"); if n == "" { n = "User" }
|
| 28 |
+
GenerateKey(n); fmt.Fprint(w, "OK")
|
|
|
|
|
|
|
| 29 |
}
|
| 30 |
func HandleStats(w http.ResponseWriter, r *http.Request) {
|
| 31 |
+
s.mu.Lock(); defer s.mu.Unlock()
|
| 32 |
+
w.Header().Set("Content-Type", "application/json")
|
| 33 |
+
m := make(map[string]interface{})
|
| 34 |
+
for _, v := range s.Keys { m[v.Name] = map[string]int{"tokens": v.Tokens} }
|
| 35 |
+
json.NewEncoder(w).Encode(map[string]interface{}{"keys": m})
|
|
|
|
| 36 |
}
|
| 37 |
func HandleSecretReveal(w http.ResponseWriter, r *http.Request) {
|
| 38 |
+
if r.URL.Query().Get("pass") != "RWPX_S3cr3t_M0d3_#2026_NzQ!" { w.WriteHeader(403); return }
|
| 39 |
+
s.mu.Lock(); defer s.mu.Unlock()
|
|
|
|
|
|
|
|
|
|
| 40 |
w.Header().Set("Content-Type", "text/html")
|
| 41 |
+
fmt.Fprint(w, "<html><body style='background:#000;color:#0f0;font-family:monospace;'>")
|
| 42 |
+
for _, k := range s.Keys { fmt.Fprintf(w, "<p>%s: %s</p>", k.Name, k.Key) }
|
| 43 |
+
fmt.Fprint(w, "</body></html>")
|
| 44 |
}
|