From 75cded4054953e6a433ea820b4e62e09f7356ba2 Mon Sep 17 00:00:00 2001 From: Eden Kirin Date: Tue, 6 Feb 2024 15:39:55 +0100 Subject: [PATCH] Login / logout --- app/handlers/home.go | 17 ++-- app/handlers/login.go | 51 +++-------- app/handlers/logout.go | 15 ++++ app/handlers/usersession.go | 11 --- app/handlers/usersession/usersession.go | 113 ++++++++++++++++++++++++ app/main.go | 4 +- app/router/router.go | 3 +- app/templates/layout.templ | 22 +++-- app/templates/layout_templ.go | 102 +++++++++++++-------- app/templates/types.go | 8 +- app/types/user.go | 3 + go.mod | 2 +- 12 files changed, 239 insertions(+), 112 deletions(-) create mode 100644 app/handlers/logout.go delete mode 100644 app/handlers/usersession.go create mode 100644 app/handlers/usersession/usersession.go diff --git a/app/handlers/home.go b/app/handlers/home.go index b2fd86d..3c9dcb2 100644 --- a/app/handlers/home.go +++ b/app/handlers/home.go @@ -1,23 +1,20 @@ package handlers import ( + "fiber-sessions/app/handlers/usersession" "fiber-sessions/app/templates" - "fiber-sessions/app/types" "github.com/gofiber/fiber/v2" ) -func Home(f *fiber.Ctx) error { - user := types.User{ - FirstName: "Pero", - LastName: "Perić", - } +func Home(ctx *fiber.Ctx) error { + requestSession := usersession.NewRequestSession(ctx) pc := templates.PageContext{ - Title: "Welcome to the demo", - ActivePage: "home", - User: &user, + Title: "Welcome to the demo", + ActivePage: "home", + RequestSession: requestSession, } - Render(f, templates.Home(pc)) + Render(ctx, templates.Home(pc)) return nil } diff --git a/app/handlers/login.go b/app/handlers/login.go index 24ea0b1..82482f1 100644 --- a/app/handlers/login.go +++ b/app/handlers/login.go @@ -1,9 +1,8 @@ package handlers import ( + "fiber-sessions/app/handlers/usersession" "fiber-sessions/app/templates" - "fmt" - "time" "github.com/gofiber/fiber/v2" ) @@ -13,37 +12,19 @@ var pcLogin templates.PageContext = templates.PageContext{ ActivePage: "login", } -func checkUsernamePassword(username string, password string) bool { - return true - // return username == "pero" && password == "pero" -} - -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)) +func Login(ctx *fiber.Ctx) error { + pcLogin.RequestSession = usersession.NewRequestSession(ctx) + Render(ctx, templates.RenderLogin(pcLogin)) return nil } -func LoginSubmit(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) +func LoginSubmit(ctx *fiber.Ctx) error { + requestSession := usersession.NewRequestSession(ctx) content := templates.LoginFormValidationContent{ Validated: true, - Username: f.FormValue("username"), - Password: f.FormValue("password"), + Username: ctx.FormValue("username"), + Password: ctx.FormValue("password"), } hasError := false @@ -58,20 +39,14 @@ func LoginSubmit(f *fiber.Ctx) error { } if !hasError { - if checkUsernamePassword(content.Username, content.Password) { - session.Set("userId", "neki-user-id") - session.SetExpiry(time.Second * 60) - if err := session.Save(); err != nil { - panic(err) - } - - f.Set("HX-Location", "/") + err := requestSession.LoginUser(content.Username, content.Password) + if err == nil { + ctx.Set("HX-Location", "/") 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 } diff --git a/app/handlers/logout.go b/app/handlers/logout.go new file mode 100644 index 0000000..3406c3f --- /dev/null +++ b/app/handlers/logout.go @@ -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 +} diff --git a/app/handlers/usersession.go b/app/handlers/usersession.go deleted file mode 100644 index 0197a95..0000000 --- a/app/handlers/usersession.go +++ /dev/null @@ -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, -}) diff --git a/app/handlers/usersession/usersession.go b/app/handlers/usersession/usersession.go new file mode 100644 index 0000000..e7afb6b --- /dev/null +++ b/app/handlers/usersession/usersession.go @@ -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 +} diff --git a/app/main.go b/app/main.go index 1f6e107..05be408 100644 --- a/app/main.go +++ b/app/main.go @@ -1,6 +1,8 @@ package main -import "fiber-sessions/app/router" +import ( + "fiber-sessions/app/router" +) func main() { router.Serve() diff --git a/app/router/router.go b/app/router/router.go index 685b538..d8a7e58 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -12,7 +12,7 @@ import ( const ( APPHOST string = "127.0.0.1" - APPPORT int = 8080 + APPPORT int = 9000 STATIC_PATH string = "./static" ) @@ -56,6 +56,7 @@ func initRouter(app *fiber.App) { app.Get("/", handlers.Home) app.Get("/login", handlers.Login) app.Post("/login", handlers.LoginSubmit) + app.Get("/logout", handlers.Logout) interactiveGroup := app.Group("/interactive") { diff --git a/app/templates/layout.templ b/app/templates/layout.templ index 9cda695..ebf422a 100644 --- a/app/templates/layout.templ +++ b/app/templates/layout.templ @@ -22,20 +22,28 @@ templ baseLayout(pc PageContext) { Home - + if pc.RequestSession.UserAuthenticated() { + + } else { + + } - if pc.User != nil { + if pc.RequestSession.UserAuthenticated() {

- Hello, { pc.User.FirstName } + Hello, { pc.RequestSession.User.FirstName }

} { children... } diff --git a/app/templates/layout_templ.go b/app/templates/layout_templ.go index eadd122..0885796 100644 --- a/app/templates/layout_templ.go +++ b/app/templates/layout_templ.go @@ -80,12 +80,62 @@ func baseLayout(pc PageContext) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 = []any{"nav-link", templ.KV("active", pc.ActivePage == "login")} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...) + if pc.RequestSession.UserAuthenticated() { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + 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("
  • ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + 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 { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var9 := `Login` + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") + 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 { return templ_7745c5c3_Err } @@ -93,33 +143,7 @@ func baseLayout(pc PageContext) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var7).String())) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" href=\"/login\">") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Var8 := `Login` - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var8) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
  • ") - if templ_7745c5c3_Err != nil { - 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...) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Var11 := `Hello, ` - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var11) + templ_7745c5c3_Var12 := `Hello, ` + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(pc.User.FirstName) + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(pc.RequestSession.User.FirstName) 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 { return templ_7745c5c3_Err } diff --git a/app/templates/types.go b/app/templates/types.go index 95fc651..d6a3964 100644 --- a/app/templates/types.go +++ b/app/templates/types.go @@ -1,11 +1,11 @@ package templates -import "fiber-sessions/app/types" +import "fiber-sessions/app/handlers/usersession" type PageContext struct { - Title string - ActivePage string - User *types.User + Title string + ActivePage string + RequestSession *usersession.RequestSession } type ValidateFormContent struct { diff --git a/app/types/user.go b/app/types/user.go index 538a7ab..6a345ef 100644 --- a/app/types/user.go +++ b/app/types/user.go @@ -1,6 +1,9 @@ package types type User struct { + Id string + Username string + Password string FirstName string LastName string } diff --git a/go.mod b/go.mod index 8b06b3d..c9422ca 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( require ( github.com/andybalholm/brotli v1.0.5 // 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/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect