better castle
This commit is contained in:
67
server/db/db.go
Normal file
67
server/db/db.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user