Login / logout

This commit is contained in:
Eden Kirin
2024-02-06 15:39:55 +01:00
parent 8ecfeb71e6
commit 75cded4054
12 changed files with 239 additions and 112 deletions

View File

@ -1,23 +1,20 @@
package handlers package handlers
import ( import (
"fiber-sessions/app/handlers/usersession"
"fiber-sessions/app/templates" "fiber-sessions/app/templates"
"fiber-sessions/app/types"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func Home(f *fiber.Ctx) error { func Home(ctx *fiber.Ctx) error {
user := types.User{ requestSession := usersession.NewRequestSession(ctx)
FirstName: "Pero",
LastName: "Perić",
}
pc := templates.PageContext{ pc := templates.PageContext{
Title: "Welcome to the demo", Title: "Welcome to the demo",
ActivePage: "home", ActivePage: "home",
User: &user, RequestSession: requestSession,
} }
Render(f, templates.Home(pc)) Render(ctx, templates.Home(pc))
return nil return nil
} }

View File

@ -1,9 +1,8 @@
package handlers package handlers
import ( import (
"fiber-sessions/app/handlers/usersession"
"fiber-sessions/app/templates" "fiber-sessions/app/templates"
"fmt"
"time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
@ -13,37 +12,19 @@ var pcLogin templates.PageContext = templates.PageContext{
ActivePage: "login", ActivePage: "login",
} }
func checkUsernamePassword(username string, password string) bool { func Login(ctx *fiber.Ctx) error {
return true pcLogin.RequestSession = usersession.NewRequestSession(ctx)
// return username == "pero" && password == "pero" Render(ctx, templates.RenderLogin(pcLogin))
}
func Login(f *fiber.Ctx) error {
session, err := sessionStore.Get(f)
if err != nil {
panic("Error gettings sessionStore: " + err.Error())
}
userId := session.Get("userId")
fmt.Printf("userId: %+v\n", userId)
Render(f, templates.RenderLogin(pcLogin))
return nil return nil
} }
func LoginSubmit(f *fiber.Ctx) error { func LoginSubmit(ctx *fiber.Ctx) error {
session, err := sessionStore.Get(f) requestSession := usersession.NewRequestSession(ctx)
if err != nil {
panic("Error gettings sessionStore: " + err.Error())
}
userId := session.Get("userId")
fmt.Printf("userId: %+v\n", userId)
content := templates.LoginFormValidationContent{ content := templates.LoginFormValidationContent{
Validated: true, Validated: true,
Username: f.FormValue("username"), Username: ctx.FormValue("username"),
Password: f.FormValue("password"), Password: ctx.FormValue("password"),
} }
hasError := false hasError := false
@ -58,20 +39,14 @@ func LoginSubmit(f *fiber.Ctx) error {
} }
if !hasError { if !hasError {
if checkUsernamePassword(content.Username, content.Password) { err := requestSession.LoginUser(content.Username, content.Password)
session.Set("userId", "neki-user-id") if err == nil {
session.SetExpiry(time.Second * 60) ctx.Set("HX-Location", "/")
if err := session.Save(); err != nil {
panic(err)
}
f.Set("HX-Location", "/")
return nil return nil
} else { }
content.LoginError = "Invalid username or password" content.LoginError = "Invalid username or password"
} }
}
Render(f, templates.LoginFormContent(content)) Render(ctx, templates.LoginFormContent(content))
return nil return nil
} }

15
app/handlers/logout.go Normal file
View File

@ -0,0 +1,15 @@
package handlers
import (
"fiber-sessions/app/handlers/usersession"
"github.com/gofiber/fiber/v2"
)
func Logout(ctx *fiber.Ctx) error {
requestSession := usersession.NewRequestSession(ctx)
requestSession.Logout()
ctx.Redirect("/")
return nil
}

View File

@ -1,11 +0,0 @@
package handlers
import (
"github.com/gofiber/fiber/v2/middleware/session"
"github.com/gofiber/storage/memory/v2"
)
var sessionStorage = memory.New()
var sessionStore = session.New(session.Config{
Storage: sessionStorage,
})

View File

@ -0,0 +1,113 @@
package usersession
import (
"errors"
"fiber-sessions/app/types"
"fmt"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/session"
"github.com/gofiber/storage/memory/v2"
)
var sessionStorage = memory.New()
var sessionStore = session.New(session.Config{
Storage: sessionStorage,
})
const SESSION_EXPIRES = time.Minute * 30
var dbUsers map[string]types.User = map[string]types.User{
"pero-uuid": {
Id: "pero-uuid",
Username: "pero",
Password: "pero",
FirstName: "Pero",
LastName: "Perić",
},
"mirko-uuid": {
Id: "mirko-uuid",
Username: "mirko",
Password: "mirko",
FirstName: "Mirko",
LastName: "Mirković",
},
}
type RequestSession struct {
ctx *fiber.Ctx
session *session.Session
User *types.User
}
func NewRequestSession(ctx *fiber.Ctx) *RequestSession {
session, err := sessionStore.Get(ctx)
if err != nil {
panic(err)
}
var user *types.User = nil
userId := session.Get("userId")
fmt.Printf("userId: %+v\n", userId)
if userId != nil {
user = getUserById(userId.(string))
}
return &RequestSession{
ctx: ctx,
session: session,
User: user,
}
}
func getUserById(id string) *types.User {
user, ok := dbUsers[id]
if ok {
return &user
}
return nil
}
func getUser(username string, password string) *types.User {
for _, user := range dbUsers {
if user.Username == username {
if user.Password == password {
return &user
}
break
}
}
return nil
}
func (r *RequestSession) LoginUser(username string, password string) error {
user := getUser(username, password)
if user == nil {
return errors.New("invalid username or password")
}
r.User = user
r.session.Set("userId", r.User.Id)
r.session.SetExpiry(SESSION_EXPIRES)
if err := r.session.Save(); err != nil {
panic(err)
}
return nil
}
func (r *RequestSession) UserAuthenticated() bool {
return r.User != nil
}
func (r *RequestSession) Logout() error {
if !r.UserAuthenticated() {
return errors.New("user not authenticated")
}
r.session.Destroy()
r.User = nil
return nil
}

View File

@ -1,6 +1,8 @@
package main package main
import "fiber-sessions/app/router" import (
"fiber-sessions/app/router"
)
func main() { func main() {
router.Serve() router.Serve()

View File

@ -12,7 +12,7 @@ import (
const ( const (
APPHOST string = "127.0.0.1" APPHOST string = "127.0.0.1"
APPPORT int = 8080 APPPORT int = 9000
STATIC_PATH string = "./static" STATIC_PATH string = "./static"
) )
@ -56,6 +56,7 @@ func initRouter(app *fiber.App) {
app.Get("/", handlers.Home) app.Get("/", handlers.Home)
app.Get("/login", handlers.Login) app.Get("/login", handlers.Login)
app.Post("/login", handlers.LoginSubmit) app.Post("/login", handlers.LoginSubmit)
app.Get("/logout", handlers.Logout)
interactiveGroup := app.Group("/interactive") interactiveGroup := app.Group("/interactive")
{ {

View File

@ -22,20 +22,28 @@ templ baseLayout(pc PageContext) {
Home Home
</a> </a>
</li> </li>
if pc.RequestSession.UserAuthenticated() {
<li class="nav-item">
<a class="nav-link" href="/logout">
Logout
</a>
</li>
} else {
<li class="nav-item"> <li class="nav-item">
<a class={ "nav-link", templ.KV("active", pc.ActivePage == "login") } href="/login"> <a class={ "nav-link", templ.KV("active", pc.ActivePage == "login") } href="/login">
Login Login
</a> </a>
</li> </li>
}
<li class="nav-item"> <li class="nav-item">
<a class={ "nav-link", templ.KV("active", pc.ActivePage == "interactive") } href="/interactive"> <a class={ "nav-link", templ.KV("active", pc.ActivePage == "interactive") } href="/interactive">
Interactive Interactive
</a> </a>
</li> </li>
</ul> </ul>
if pc.User != nil { if pc.RequestSession.UserAuthenticated() {
<p class="alert alert-warning"> <p class="alert alert-warning">
Hello, { pc.User.FirstName } Hello, { pc.RequestSession.User.FirstName }
</p> </p>
} }
{ children... } { children... }

View File

@ -80,12 +80,31 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li class=\"nav-item\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var7 = []any{"nav-link", templ.KV("active", pc.ActivePage == "login")} if pc.RequestSession.UserAuthenticated() {
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"nav-item\"><a class=\"nav-link\" href=\"/logout\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var7 := `Logout`
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var7)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"nav-item\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 = []any{"nav-link", templ.KV("active", pc.ActivePage == "login")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -93,7 +112,7 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var7).String())) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var8).String()))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -101,17 +120,22 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Var8 := `Login` templ_7745c5c3_Var9 := `Login`
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><li class=\"nav-item\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var9 = []any{"nav-link", templ.KV("active", pc.ActivePage == "interactive")} }
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"nav-item\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 = []any{"nav-link", templ.KV("active", pc.ActivePage == "interactive")}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -119,7 +143,7 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var9).String())) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var10).String()))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -127,8 +151,8 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Var10 := `Interactive` templ_7745c5c3_Var11 := `Interactive`
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var10) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -136,22 +160,22 @@ func baseLayout(pc PageContext) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if pc.User != nil { if pc.RequestSession.UserAuthenticated() {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"alert alert-warning\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"alert alert-warning\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Var11 := `Hello, ` templ_7745c5c3_Var12 := `Hello, `
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var12 string var templ_7745c5c3_Var13 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(pc.User.FirstName) templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(pc.RequestSession.User.FirstName)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templates/layout.templ`, Line: 37, Col: 32} return templ.Error{Err: templ_7745c5c3_Err, FileName: `app/templates/layout.templ`, Line: 45, Col: 47}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -1,11 +1,11 @@
package templates package templates
import "fiber-sessions/app/types" import "fiber-sessions/app/handlers/usersession"
type PageContext struct { type PageContext struct {
Title string Title string
ActivePage string ActivePage string
User *types.User RequestSession *usersession.RequestSession
} }
type ValidateFormContent struct { type ValidateFormContent struct {

View File

@ -1,6 +1,9 @@
package types package types
type User struct { type User struct {
Id string
Username string
Password string
FirstName string FirstName string
LastName string LastName string
} }

2
go.mod
View File

@ -10,7 +10,7 @@ require (
require ( require (
github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/brotli v1.0.5 // indirect
github.com/gofiber/storage/memory/v2 v2.0.0 // indirect github.com/gofiber/storage/memory/v2 v2.0.0 // indirect
github.com/google/uuid v1.5.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect github.com/klauspost/compress v1.17.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect