better castle

This commit is contained in:
metacryst
2025-09-22 13:05:06 -05:00
parent 04f4155a19
commit a58632d983
10 changed files with 3293 additions and 114 deletions

67
server/db/db.go Normal file
View File

@@ -0,0 +1,67 @@
package db
import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"github.com/alexedwards/argon2id"
)
var DB map[string]interface{}
type GetService struct{}
var Get = GetService{}
func (g GetService) User(id string) (map[string]interface{}, error) {
raw, ok := DB[id]
if !ok {
return nil, errors.New("user not found")
}
userData, ok := raw.(map[string]interface{})
log.Println(userData)
if !ok {
return nil, errors.New("user data is not in expected format")
}
return userData, nil
}
func InitDB() error {
file, err := os.Open("../db/users.json")
if err != nil {
fmt.Println("Error opening file:", err)
return errors.New("Failed to read db")
}
defer file.Close()
var data interface{}
err = json.NewDecoder(file).Decode(&data)
if err != nil {
fmt.Println("Error decoding JSON:", err)
return errors.New("Failed to decode db")
}
result, ok := data.(map[string]interface{})
if !ok {
fmt.Println("Data is not a JSON object (map)")
return errors.New("Db is in the wrong format")
}
DB = result
// Use default recommended parameters
hash, err := argon2id.CreateHash("hunter2", argon2id.DefaultParams)
if err != nil {
log.Fatal(err)
}
fmt.Println("Argon2 Hash:")
fmt.Println(hash)
return nil
}

View File

@@ -1,8 +1,8 @@
module hyperia
go 1.23.0
go 1.24.0
toolchain go1.24.2
toolchain go1.24.5
require (
github.com/alexedwards/argon2id v1.0.0
@@ -23,6 +23,11 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/yuin/goldmark v1.7.13 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/tools v0.36.1-0.20250903222949-a5c0eb837c9f // indirect
golang.org/x/tools/cmd/godoc v0.1.0-deprecated // indirect
golang.org/x/tools/godoc v0.1.0-deprecated // indirect
)

View File

@@ -46,12 +46,16 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -88,6 +92,12 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.36.1-0.20250903222949-a5c0eb837c9f h1:jDEaVlf+r7N8Re8Es5pGylGkfnqcx9dfUCsd1T+biTs=
golang.org/x/tools v0.36.1-0.20250903222949-a5c0eb837c9f/go.mod h1:n+8pplxVZfXnmHBxWsfPnQRJ5vWroQDk+U2MFpjwtFY=
golang.org/x/tools/cmd/godoc v0.1.0-deprecated h1:sEGTwp9aZNTHsdf/2BGaRqE4ZLndRVH17rbQ2OVun9Q=
golang.org/x/tools/cmd/godoc v0.1.0-deprecated/go.mod h1:J6VY4iFch6TIm456U3fnw1EJZaIqcYlhHu6GpHQ9HJk=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=

View File

@@ -2,23 +2,24 @@ package handlers
import (
"encoding/json"
// "errors"
"errors"
"log"
"net/http"
// "strings"
"hyperia/db"
"github.com/rs/zerolog/log"
// "github.com/alexedwards/argon2id"
"github.com/alexedwards/argon2id"
)
type loginRequest struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
}
type user struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func HandleLogin(w http.ResponseWriter, r *http.Request) {
@@ -33,75 +34,38 @@ func HandleLogin(w http.ResponseWriter, r *http.Request) {
return
}
// user, err := getUserByCredentials(creds.Name, creds.Password)
// if err != nil {
// http.Error(w, "Unauthorized: "+err.Error(), http.StatusUnauthorized)
// return
// }
user, err := getUserByCredentials(creds)
if err != nil {
http.Error(w, "Unauthorized: "+ err.Error(), http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "application/json")
http.Error(w, "Not implemented", http.StatusMethodNotAllowed)
// json.NewEncoder(w).Encode(user)
http.Error(w, "Not implemented", http.StatusMethodNotAllowed)
json.NewEncoder(w).Encode(user)
}
// func getUserByCredentials(name string, password string) (*user, error) {
// var id int
// var dbName, dbHash string
func getUserByCredentials(loginCreds loginRequest) (map[string]interface{}, error) {
// name = strings.TrimSpace(strings.ToLower(name))
// err := DB.QueryRow("SELECT id, name, password FROM users WHERE LOWER(name) = LOWER($1)", name).Scan(&id, &dbName, &dbHash)
// if err != nil {
// return nil, errors.New("user not found")
// }
// match, err := argon2id.ComparePasswordAndHash(password, dbHash)
// if err != nil || !match {
// return nil, errors.New("invalid password")
// }
// return &user{
// ID: id,
// Name: dbName,
// }, nil
// }
func HandleApplicantLogin(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Only POST allowed", http.StatusMethodNotAllowed)
return
}
var creds loginRequest
if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
// exists, err := EmailExists(creds.Name)
// if err != nil {
// log.Err(err).Msg("error checking email")
// http.Error(w, "Internal server error", http.StatusInternalServerError)
// return
// }
// if !exists {
// http.Error(w, "Email does not exist.", http.StatusConflict)
// return
// }
token, err := generateVerificationToken(creds.Name)
// email := strings.TrimSpace(strings.ToLower(loginCreds.Email))
user, err := db.Get.User("1")
// err := DB.QueryRow("SELECT id, name, password FROM users WHERE LOWER(name) = LOWER($1)", name).Scan(&id, &dbName, &dbHash)
if err != nil {
log.Err(err).Msg("error generating verification token")
http.Error(w, "Error, please try again later.", http.StatusInternalServerError)
return
return nil, errors.New("user not found")
}
err = sendWelcomeEmail(creds.Name, token)
if err != nil {
log.Err(err).Msg("error sending welcome email")
http.Error(w, "Failed to send email", http.StatusInternalServerError)
return
dbPassword, ok := user["password"].(string)
if !ok {
return nil, errors.New("password format is invalid")
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}
log.Println("pass: ", loginCreds, loginCreds.Password, dbPassword)
match, err := argon2id.ComparePasswordAndHash(loginCreds.Password, dbPassword)
if err != nil || !match {
return nil, errors.New("invalid password")
}
return user, nil
}

View File

@@ -5,6 +5,7 @@ import (
"net/http"
"path/filepath"
"hyperia/config"
"hyperia/db"
"hyperia/handlers"
"hyperia/logger"
"runtime/debug"
@@ -16,15 +17,14 @@ import (
func main() {
config.SetConfiguration()
logger.ConfigureLogger()
// err := handlers.InitDB()
// if err != nil {
// log.Fatal().Msgf("failed to connect to database: %v", err)
// } else {
// log.Info().Msg("successfully connected to PostgreSQL")
// }
err := db.InitDB()
if err != nil {
log.Fatal().Msgf("failed to connect to database: %v", err)
} else {
log.Info().Msg("successfully connected to PostgreSQL")
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
defer func() {
@@ -55,7 +55,7 @@ func main() {
})
log.Info().Msgf("Server starting on http://localhost: %s", config.PORT)
err := http.ListenAndServe(":"+config.PORT, nil)
err = http.ListenAndServe(":"+config.PORT, nil)
if err != nil {
log.Fatal().Msgf("failed to start server: %v", err)
}
@@ -67,10 +67,6 @@ func handlePublic(w http.ResponseWriter, r *http.Request) {
handlers.HandleLogin(w, r)
return
}
if r.URL.Path == "/api/applicantlogin" {
handlers.HandleApplicantLogin(w, r)
return
}
if r.URL.Path == "/api/join" {
handlers.HandleJoin(w, r)
return