Auth fixes
This commit is contained in:
parent
de07026042
commit
7978dd131a
8 changed files with 52 additions and 13 deletions
|
@ -8,15 +8,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterUserHandler(c echo.Context) error {
|
func RegisterUserHandler(c echo.Context) error {
|
||||||
|
name := c.FormValue("name")
|
||||||
email := c.FormValue("email")
|
email := c.FormValue("email")
|
||||||
password := c.FormValue("password")
|
password := c.FormValue("password")
|
||||||
|
|
||||||
|
// Check if the email already exists
|
||||||
|
existingUser, err := lib.GetUserByEmail(lib.GetDBPool(), email)
|
||||||
|
if err == nil && existingUser != nil {
|
||||||
|
// User with the given email already exists
|
||||||
|
errorMessage := `<div id="error-message" style="color: red;">An account with this email already exists!</div>`
|
||||||
|
return c.HTML(http.StatusBadRequest, errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with the existing registration logic
|
||||||
hashedPassword, err := lib.HashPassword(password)
|
hashedPassword, err := lib.HashPassword(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Failed to hash password")
|
return c.JSON(http.StatusInternalServerError, "Failed to hash password")
|
||||||
}
|
}
|
||||||
|
|
||||||
user := lib.User{Email: email, Password: hashedPassword}
|
user := lib.User{Name: name, Email: email, Password: hashedPassword}
|
||||||
if err := lib.SaveUser(lib.GetDBPool(), &user); err != nil {
|
if err := lib.SaveUser(lib.GetDBPool(), &user); err != nil {
|
||||||
return c.JSON(http.StatusInternalServerError, "Failed to save user")
|
return c.JSON(http.StatusInternalServerError, "Failed to save user")
|
||||||
}
|
}
|
||||||
|
@ -30,6 +40,7 @@ func RegisterUserHandler(c echo.Context) error {
|
||||||
lib.SetSessionCookie(c.Response().Writer, "session", lib.SessionData{
|
lib.SetSessionCookie(c.Response().Writer, "session", lib.SessionData{
|
||||||
SessionID: sessionID,
|
SessionID: sessionID,
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
|
Name: user.Name,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Roles: []string{"user"},
|
Roles: []string{"user"},
|
||||||
})
|
})
|
||||||
|
|
16
lib/auth.go
16
lib/auth.go
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string
|
ID string
|
||||||
|
Name string
|
||||||
Email string
|
Email string
|
||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
@ -43,6 +44,21 @@ func GetUserByEmail(dbPool *pgxpool.Pool, email string) (*User, error) {
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserByID fetches a user by ID from the database.
|
||||||
|
func GetUserByID(dbPool *pgxpool.Pool, id string) (*User, error) {
|
||||||
|
if dbPool == nil {
|
||||||
|
return nil, errors.New("database connection pool is not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
var user User
|
||||||
|
// Ensure the ID is being scanned as a string.
|
||||||
|
err := dbPool.QueryRow(context.Background(), "SELECT id::text, email, password FROM users WHERE id = $1", id).Scan(&user.ID, &user.Email, &user.Password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &user, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SaveUser saves a new user to the database.
|
// SaveUser saves a new user to the database.
|
||||||
func SaveUser(dbPool *pgxpool.Pool, user *User) error {
|
func SaveUser(dbPool *pgxpool.Pool, user *User) error {
|
||||||
if dbPool == nil {
|
if dbPool == nil {
|
||||||
|
|
|
@ -26,6 +26,7 @@ func InitializeSchema(dbPool *pgxpool.Pool) error {
|
||||||
const schemaSQL = `
|
const schemaSQL = `
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
email VARCHAR(255) UNIQUE NOT NULL,
|
email VARCHAR(255) UNIQUE NOT NULL,
|
||||||
password VARCHAR(255) NOT NULL
|
password VARCHAR(255) NOT NULL
|
||||||
);`
|
);`
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
type SessionData struct {
|
type SessionData struct {
|
||||||
SessionID string `json:"sessionID"`
|
SessionID string `json:"sessionID"`
|
||||||
UserID string `json:"userId"`
|
UserID string `json:"userId"`
|
||||||
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
|
@ -154,12 +155,21 @@ func ClearSessionCookie(w http.ResponseWriter, name string) {
|
||||||
|
|
||||||
// Checks if the user is signed in by checking the session cookie
|
// Checks if the user is signed in by checking the session cookie
|
||||||
func IsSignedIn(c echo.Context) bool {
|
func IsSignedIn(c echo.Context) bool {
|
||||||
_, err := GetSessionCookie(c.Request(), "session")
|
sessionData, err := GetSessionCookie(c.Request(), "session")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Log the error for debugging purposes
|
|
||||||
log.Printf("Error retrieving session cookie: %v", err)
|
log.Printf("Error retrieving session cookie: %v", err)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return err == nil
|
|
||||||
|
// Validate the session data by checking if the user exists in the database
|
||||||
|
user, err := GetUserByID(GetDBPool(), sessionData.UserID)
|
||||||
|
if err != nil || user == nil {
|
||||||
|
log.Printf("Session refers to a non-existent user: %v", err)
|
||||||
|
ClearSessionCookie(c.Response().Writer, "session")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRandomBytes returns securely generated random bytes.
|
// GenerateRandomBytes returns securely generated random bytes.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
type DashboardProps struct {
|
type DashboardProps struct {
|
||||||
IsLoggedIn bool
|
IsLoggedIn bool
|
||||||
Email string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dashboard(c echo.Context) error {
|
func Dashboard(c echo.Context) error {
|
||||||
|
@ -19,7 +19,7 @@ func Dashboard(c echo.Context) error {
|
||||||
|
|
||||||
props := DashboardProps{
|
props := DashboardProps{
|
||||||
IsLoggedIn: lib.IsSignedIn(c),
|
IsLoggedIn: lib.IsSignedIn(c),
|
||||||
Email: currentSession.Email,
|
Name: currentSession.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify the partials used by this page
|
// Specify the partials used by this page
|
||||||
|
|
|
@ -13,7 +13,7 @@ Pollo // Dashboard
|
||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<div class="flex flex-col items-center justify-center gap-8">
|
<div class="flex flex-col items-center justify-center gap-8">
|
||||||
<h1 class="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-4xl font-bold">
|
<h1 class="flex flex-row flex-wrap text-center justify-center items-center gap-1 text-4xl font-bold">
|
||||||
Hi, {{.Email}}!
|
Hi, {{.Name}}!
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<label htmlFor="new-room-modal" class="btn btn-primary">
|
<label htmlFor="new-room-modal" class="btn btn-primary">
|
||||||
|
|
|
@ -11,19 +11,21 @@ Pollo // Register
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<div id="auth-form">
|
<div id="auth-form" hx-ext="response-targets">
|
||||||
<h2 class="text-4xl">Register</h2>
|
<h2 class="text-4xl">Register</h2>
|
||||||
<br>
|
<br>
|
||||||
<form class="flex flex-col gap-2" hx-post="/api/register" hx-swap="none">
|
<form class="flex flex-col gap-2" hx-post="/api/register" hx-target-4*="#error-message">
|
||||||
|
<input class="input input-bordered input-primary w-full max-w-xs" type="text" name="name" placeholder="Name" required>
|
||||||
<input class="input input-bordered input-primary w-full max-w-xs" type="email" name="email" placeholder="Email" required>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="email" name="email" placeholder="Email" required>
|
||||||
<input class="input input-bordered input-primary w-full max-w-xs" type="password" name="password" placeholder="Password" required>
|
<input class="input input-bordered input-primary w-full max-w-xs" type="password" name="password" placeholder="Password" required>
|
||||||
<button class="btn btn-primary" type="submit">Register</button>
|
<button class="btn btn-primary" type="submit">Sign In</button>
|
||||||
</form>
|
</form>
|
||||||
<p>Already have an account? <a href="/signin">Sign In</a></p>
|
<div id="error-message"style="color: red;"></div>
|
||||||
|
<p>Already have an account? <a href="/signin">Register</a></p>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "foot"}}
|
{{define "foot"}}
|
||||||
<script src="/public/js/htmx.base.js"></script>
|
<script src="/public/js/htmx.base.js"></script>
|
||||||
<script src="/public/js/htmx.sse.js"></script>
|
<script src="/public/js/htmx.targets.js"></script>
|
||||||
{{end}}
|
{{end}}
|
|
@ -26,6 +26,5 @@ Pollo // Sign In
|
||||||
|
|
||||||
{{define "foot"}}
|
{{define "foot"}}
|
||||||
<script src="/public/js/htmx.base.js"></script>
|
<script src="/public/js/htmx.base.js"></script>
|
||||||
<script src="/public/js/htmx.sse.js"></script>
|
|
||||||
<script src="/public/js/htmx.targets.js"></script>
|
<script src="/public/js/htmx.targets.js"></script>
|
||||||
{{end}}
|
{{end}}
|
Loading…
Add table
Reference in a new issue