Various styling changes

fix-voucher-compensation
maru 2024-04-08 18:15:09 -04:00
parent 80a2c637d2
commit 0edfeab3ca
No known key found for this signature in database
GPG Key ID: 37689350E9CD0F0D
7 changed files with 73 additions and 62 deletions

View File

@ -30,7 +30,7 @@ func getUsernameFromRequest(r *http.Request) (string, error) {
return username, nil return username, nil
} }
func getUuidFromRequest(r *http.Request) ([]byte, error) { func getUUIDFromRequest(r *http.Request) ([]byte, error) {
if r.Header.Get("Authorization") == "" { if r.Header.Get("Authorization") == "" {
return nil, fmt.Errorf("missing token") return nil, fmt.Errorf("missing token")
} }
@ -44,7 +44,7 @@ func getUuidFromRequest(r *http.Request) ([]byte, error) {
return nil, fmt.Errorf("invalid token length: got %d, expected 32", len(token)) return nil, fmt.Errorf("invalid token length: got %d, expected 32", len(token))
} }
uuid, err := db.FetchUuidFromToken(token) uuid, err := db.FetchUUIDFromToken(token)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to validate token: %s", err) return nil, fmt.Errorf("failed to validate token: %s", err)
} }

View File

@ -18,10 +18,12 @@ import (
) )
const ( const (
argonTime = 1 UUIDSize = 16
argonMemory = 256 * 1024 ArgonTime = 1
argonThreads = 4 ArgonMemory = 256 * 1024
argonKeyLength = 32 ArgonThreads = 4
ArgonKeySize = 32
ArgonSaltSize = 16
) )
var isValidUsername = regexp.MustCompile(`^\w{1,16}$`).MatchString var isValidUsername = regexp.MustCompile(`^\w{1,16}$`).MatchString
@ -39,14 +41,14 @@ func (s *Server) handleAccountInfo(w http.ResponseWriter, r *http.Request) {
return return
} }
uuid, err := getUuidFromRequest(r) // lazy uuid, err := getUUIDFromRequest(r) // lazy
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return
} }
var latestSaveTime time.Time var latestSave time.Time
latestSaveId := -1 latestSaveID := -1
for id := range sessionSlotCount { for id := range sessionSlotCount {
fileName := "session" fileName := "session"
if id != 0 { if id != 0 {
@ -58,13 +60,13 @@ func (s *Server) handleAccountInfo(w http.ResponseWriter, r *http.Request) {
continue continue
} }
if stat.ModTime().After(latestSaveTime) { if stat.ModTime().After(latestSave) {
latestSaveTime = stat.ModTime() latestSave = stat.ModTime()
latestSaveId = id latestSaveID = id
} }
} }
response, err := json.Marshal(AccountInfoResponse{Username: username, LastSessionSlot: latestSaveId}) response, err := json.Marshal(AccountInfoResponse{Username: username, LastSessionSlot: latestSaveID})
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to marshal response json: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to marshal response json: %s", err), http.StatusInternalServerError)
return return
@ -94,21 +96,21 @@ func (s *Server) handleAccountRegister(w http.ResponseWriter, r *http.Request) {
return return
} }
uuid := make([]byte, 16) uuid := make([]byte, UUIDSize)
_, err = rand.Read(uuid) _, err = rand.Read(uuid)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to generate uuid: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to generate uuid: %s", err), http.StatusInternalServerError)
return return
} }
salt := make([]byte, 16) salt := make([]byte, ArgonSaltSize)
_, err = rand.Read(salt) _, err = rand.Read(salt)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to generate salt: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to generate salt: %s", err), http.StatusInternalServerError)
return return
} }
err = db.AddAccountRecord(uuid, request.Username, argon2.IDKey([]byte(request.Password), salt, argonTime, argonMemory, argonThreads, argonKeyLength), salt) err = db.AddAccountRecord(uuid, request.Username, argon2.IDKey([]byte(request.Password), salt, ArgonTime, ArgonMemory, ArgonThreads, ArgonKeySize), salt)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to add account record: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to add account record: %s", err), http.StatusInternalServerError)
return return
@ -150,7 +152,7 @@ func (s *Server) handleAccountLogin(w http.ResponseWriter, r *http.Request) {
return return
} }
if !bytes.Equal(key, argon2.IDKey([]byte(request.Password), salt, argonTime, argonMemory, argonThreads, argonKeyLength)) { if !bytes.Equal(key, argon2.IDKey([]byte(request.Password), salt, ArgonTime, ArgonMemory, ArgonThreads, ArgonKeySize)) {
httpError(w, r, "password doesn't match", http.StatusBadRequest) httpError(w, r, "password doesn't match", http.StatusBadRequest)
return return
} }

View File

@ -26,26 +26,33 @@ var (
) )
func ScheduleDailyRunRefresh() { func ScheduleDailyRunRefresh() {
dailyRunScheduler.Every(1).Day().At("00:00").Do(InitDailyRun) dailyRunScheduler.Every(1).Day().At("00:00").Do(func() error {
err := InitDailyRun()
if err != nil {
log.Fatal(err)
}
return nil
}())
dailyRunScheduler.StartAsync() dailyRunScheduler.StartAsync()
} }
func InitDailyRun() { func InitDailyRun() error {
secret, err := os.ReadFile("secret.key") secret, err := os.ReadFile("secret.key")
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
log.Fatalf("failed to read daily seed secret: %s", err) return fmt.Errorf("failed to read daily seed secret: %s", err)
} }
newSecret := make([]byte, 32) newSecret := make([]byte, 32)
_, err := rand.Read(newSecret) _, err := rand.Read(newSecret)
if err != nil { if err != nil {
log.Fatalf("failed to generate daily seed secret: %s", err) return fmt.Errorf("failed to generate daily seed secret: %s", err)
} }
err = os.WriteFile("secret.key", newSecret, 0400) err = os.WriteFile("secret.key", newSecret, 0400)
if err != nil { if err != nil {
log.Fatalf("failed to write daily seed secret: %s", err) return fmt.Errorf("failed to write daily seed secret: %s", err)
} }
secret = newSecret secret = newSecret
@ -61,6 +68,8 @@ func InitDailyRun() {
} }
log.Printf("Daily Run Seed: %s", dailyRunSeed) log.Printf("Daily Run Seed: %s", dailyRunSeed)
return nil
} }
func deriveDailyRunSeed(seedTime time.Time) []byte { func deriveDailyRunSeed(seedTime time.Time) []byte {
@ -79,7 +88,7 @@ func (s *Server) handleSeed(w http.ResponseWriter) {
// /daily/rankings - fetch daily rankings // /daily/rankings - fetch daily rankings
func (s *Server) handleRankings(w http.ResponseWriter, r *http.Request) { func (s *Server) handleRankings(w http.ResponseWriter, r *http.Request) {
uuid, err := getUuidFromRequest(r) uuid, err := getUUIDFromRequest(r)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return

View File

@ -40,12 +40,12 @@ func readSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
return system, nil return system, nil
} }
func readSessionSaveData(uuid []byte, slotId int) (defs.SessionSaveData, error) { func readSessionSaveData(uuid []byte, slotID int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData var session defs.SessionSaveData
fileName := "session" fileName := "session"
if slotId != 0 { if slotID != 0 {
fileName += strconv.Itoa(slotId) fileName += strconv.Itoa(slotID)
} }
save, err := os.ReadFile(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName)) save, err := os.ReadFile(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))

View File

@ -20,7 +20,7 @@ const sessionSlotCount = 3
// /savedata/get - get save data // /savedata/get - get save data
func (s *Server) handleSavedataGet(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSavedataGet(w http.ResponseWriter, r *http.Request) {
uuid, err := getUuidFromRequest(r) uuid, err := getUUIDFromRequest(r)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return
@ -42,18 +42,18 @@ func (s *Server) handleSavedataGet(w http.ResponseWriter, r *http.Request) {
w.Write(saveJson) w.Write(saveJson)
case "1": // Session case "1": // Session
slotId, err := strconv.Atoi(r.URL.Query().Get("slot")) slotID, err := strconv.Atoi(r.URL.Query().Get("slot"))
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest)
return return
} }
if slotId < 0 || slotId >= sessionSlotCount { if slotID < 0 || slotID >= sessionSlotCount {
httpError(w, r, fmt.Sprintf("slot id %d out of range", slotId), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("slot id %d out of range", slotID), http.StatusBadRequest)
return return
} }
session, err := readSessionSaveData(uuid, slotId) session, err := readSessionSaveData(uuid, slotID)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusInternalServerError) httpError(w, r, err.Error(), http.StatusInternalServerError)
return return
@ -74,7 +74,7 @@ func (s *Server) handleSavedataGet(w http.ResponseWriter, r *http.Request) {
// /savedata/update - update save data // /savedata/update - update save data
func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
uuid, err := getUuidFromRequest(r) uuid, err := getUUIDFromRequest(r)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return
@ -85,7 +85,7 @@ func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
log.Print("failed to update account last activity") log.Print("failed to update account last activity")
} }
hexUuid := hex.EncodeToString(uuid) hexUUID := hex.EncodeToString(uuid)
switch r.URL.Query().Get("datatype") { switch r.URL.Query().Get("datatype") {
case "0": // System case "0": // System
@ -96,7 +96,7 @@ func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
return return
} }
if system.TrainerId == 0 && system.SecretId == 0 { if system.TrainerID == 0 && system.SecretID == 0 {
httpError(w, r, "invalid system data", http.StatusInternalServerError) httpError(w, r, "invalid system data", http.StatusInternalServerError)
return return
} }
@ -122,32 +122,32 @@ func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
compressed := zstdWriter.EncodeAll(gobBuffer.Bytes(), nil) compressed := zstdWriter.EncodeAll(gobBuffer.Bytes(), nil)
err = os.MkdirAll("userdata/"+hexUuid, 0755) err = os.MkdirAll("userdata/"+hexUUID, 0755)
if err != nil && !os.IsExist(err) { if err != nil && !os.IsExist(err) {
httpError(w, r, fmt.Sprintf("failed to create userdata folder: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to create userdata folder: %s", err), http.StatusInternalServerError)
return return
} }
err = os.WriteFile("userdata/"+hexUuid+"/system.pzs", compressed, 0644) err = os.WriteFile("userdata/"+hexUUID+"/system.pzs", compressed, 0644)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to write save file: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to write save file: %s", err), http.StatusInternalServerError)
return return
} }
case "1": // Session case "1": // Session
slotId, err := strconv.Atoi(r.URL.Query().Get("slot")) slotID, err := strconv.Atoi(r.URL.Query().Get("slot"))
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest)
return return
} }
if slotId < 0 || slotId >= sessionSlotCount { if slotID < 0 || slotID >= sessionSlotCount {
httpError(w, r, fmt.Sprintf("slot id %d out of range", slotId), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("slot id %d out of range", slotID), http.StatusBadRequest)
return return
} }
fileName := "session" fileName := "session"
if slotId != 0 { if slotID != 0 {
fileName += strconv.Itoa(slotId) fileName += strconv.Itoa(slotID)
} }
var session defs.SessionSaveData var session defs.SessionSaveData
@ -172,13 +172,13 @@ func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
compressed := zstdWriter.EncodeAll(gobBuffer.Bytes(), nil) compressed := zstdWriter.EncodeAll(gobBuffer.Bytes(), nil)
err = os.MkdirAll("userdata/"+hexUuid, 0755) err = os.MkdirAll("userdata/"+hexUUID, 0755)
if err != nil && !os.IsExist(err) { if err != nil && !os.IsExist(err) {
httpError(w, r, fmt.Sprintf("failed to create userdata folder: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to create userdata folder: %s", err), http.StatusInternalServerError)
return return
} }
err = os.WriteFile(fmt.Sprintf("userdata/%s/%s.pzs", hexUuid, fileName), compressed, 0644) err = os.WriteFile(fmt.Sprintf("userdata/%s/%s.pzs", hexUUID, fileName), compressed, 0644)
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to write save file: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to write save file: %s", err), http.StatusInternalServerError)
return return
@ -193,7 +193,7 @@ func (s *Server) handleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
// /savedata/delete - delete save data // /savedata/delete - delete save data
func (s *Server) handleSavedataDelete(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSavedataDelete(w http.ResponseWriter, r *http.Request) {
uuid, err := getUuidFromRequest(r) uuid, err := getUUIDFromRequest(r)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return
@ -204,33 +204,33 @@ func (s *Server) handleSavedataDelete(w http.ResponseWriter, r *http.Request) {
log.Print("failed to update account last activity") log.Print("failed to update account last activity")
} }
hexUuid := hex.EncodeToString(uuid) hexUUID := hex.EncodeToString(uuid)
switch r.URL.Query().Get("datatype") { switch r.URL.Query().Get("datatype") {
case "0": // System case "0": // System
err := os.Remove("userdata/" + hexUuid + "/system.pzs") err := os.Remove("userdata/" + hexUUID + "/system.pzs")
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
httpError(w, r, fmt.Sprintf("failed to delete save file: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to delete save file: %s", err), http.StatusInternalServerError)
return return
} }
case "1": // Session case "1": // Session
slotId, err := strconv.Atoi(r.URL.Query().Get("slot")) slotID, err := strconv.Atoi(r.URL.Query().Get("slot"))
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest)
return return
} }
if slotId < 0 || slotId >= sessionSlotCount { if slotID < 0 || slotID >= sessionSlotCount {
httpError(w, r, fmt.Sprintf("slot id %d out of range", slotId), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("slot id %d out of range", slotID), http.StatusBadRequest)
return return
} }
fileName := "session" fileName := "session"
if slotId != 0 { if slotID != 0 {
fileName += strconv.Itoa(slotId) fileName += strconv.Itoa(slotID)
} }
err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", hexUuid, fileName)) err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", hexUUID, fileName))
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
httpError(w, r, fmt.Sprintf("failed to delete save file: %s", err), http.StatusInternalServerError) httpError(w, r, fmt.Sprintf("failed to delete save file: %s", err), http.StatusInternalServerError)
return return
@ -249,7 +249,7 @@ type SavedataClearResponse struct {
// /savedata/clear - mark session save data as cleared and delete // /savedata/clear - mark session save data as cleared and delete
func (s *Server) handleSavedataClear(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSavedataClear(w http.ResponseWriter, r *http.Request) {
uuid, err := getUuidFromRequest(r) uuid, err := getUUIDFromRequest(r)
if err != nil { if err != nil {
httpError(w, r, err.Error(), http.StatusBadRequest) httpError(w, r, err.Error(), http.StatusBadRequest)
return return
@ -260,14 +260,14 @@ func (s *Server) handleSavedataClear(w http.ResponseWriter, r *http.Request) {
log.Print("failed to update account last activity") log.Print("failed to update account last activity")
} }
slotId, err := strconv.Atoi(r.URL.Query().Get("slot")) slotID, err := strconv.Atoi(r.URL.Query().Get("slot"))
if err != nil { if err != nil {
httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("failed to convert slot id: %s", err), http.StatusBadRequest)
return return
} }
if slotId < 0 || slotId >= sessionSlotCount { if slotID < 0 || slotID >= sessionSlotCount {
httpError(w, r, fmt.Sprintf("slot id %d out of range", slotId), http.StatusBadRequest) httpError(w, r, fmt.Sprintf("slot id %d out of range", slotID), http.StatusBadRequest)
return return
} }
@ -306,8 +306,8 @@ func (s *Server) handleSavedataClear(w http.ResponseWriter, r *http.Request) {
} }
fileName := "session" fileName := "session"
if slotId != 0 { if slotID != 0 {
fileName += strconv.Itoa(slotId) fileName += strconv.Itoa(slotID)
} }
err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName)) err = os.Remove(fmt.Sprintf("userdata/%s/%s.pzs", hex.EncodeToString(uuid), fileName))

View File

@ -120,7 +120,7 @@ func FetchAccountKeySaltFromUsername(username string) ([]byte, []byte, error) {
return key, salt, nil return key, salt, nil
} }
func FetchUuidFromToken(token []byte) ([]byte, error) { func FetchUUIDFromToken(token []byte) ([]byte, error) {
var uuid []byte var uuid []byte
err := handle.QueryRow("SELECT uuid FROM sessions WHERE token = ? AND expire > UTC_TIMESTAMP()", token).Scan(&uuid) err := handle.QueryRow("SELECT uuid FROM sessions WHERE token = ? AND expire > UTC_TIMESTAMP()", token).Scan(&uuid)
if err != nil { if err != nil {

View File

@ -1,8 +1,8 @@
package defs package defs
type SystemSaveData struct { type SystemSaveData struct {
TrainerId int `json:"trainerId"` TrainerID int `json:"trainerId"`
SecretId int `json:"secretId"` SecretID int `json:"secretId"`
Gender int `json:"gender"` Gender int `json:"gender"`
DexData DexData `json:"dexData"` DexData DexData `json:"dexData"`
StarterMoveData StarterMoveData `json:"starterMoveData"` StarterMoveData StarterMoveData `json:"starterMoveData"`
@ -44,7 +44,7 @@ type VoucherUnlocks map[string]int
type VoucherCounts map[string]int type VoucherCounts map[string]int
type EggData struct { type EggData struct {
Id int `json:"id"` ID int `json:"id"`
GachaType GachaType `json:"gachaType"` GachaType GachaType `json:"gachaType"`
HatchWaves int `json:"hatchWaves"` HatchWaves int `json:"hatchWaves"`
Timestamp int `json:"timestamp"` Timestamp int `json:"timestamp"`