feat: create-room handler, with middleware

This commit is contained in:
efim 2023-11-04 05:52:20 +00:00
parent 850b6c693b
commit f8eb11c53e
4 changed files with 108 additions and 48 deletions

View File

@ -10,14 +10,14 @@ import (
) )
type Person struct { type Person struct {
PersonId int64 PersonId int
Name string Name string
PasswordHash string PasswordHash string
} }
type Room struct { type Room struct {
Name string // will be unique ID Name string // will be unique ID
AdminIds []int64 AdminIds []int
PasswordHash string PasswordHash string
Paricipants []Person Paricipants []Person
// TODO hands, for each type of hand? // TODO hands, for each type of hand?

View File

@ -1,29 +1,82 @@
package routes package routes
import ( import (
"context"
"embed" "embed"
"fmt" "fmt"
"html/template" "html/template"
"log" "log"
"math/rand"
"net/http" "net/http"
"strconv"
"sunshine.industries/some-automoderation/rooms" "sunshine.industries/some-automoderation/rooms"
"sunshine.industries/some-automoderation/sessions" "sunshine.industries/some-automoderation/sessions"
) )
func registerLoginRoutes( const authCookieName = "auth"
templateFs *embed.FS, const loginPath = "/login"
sessionSM sessions.SessionManagement, type contextKey string
roomsM rooms.RoomManager,
) { // checks sessionId from cookie
// login page // when non-zero session found - pass to next http.Hander
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { // when no session available - render same as login page and redirect to /
func authedPageMiddleware(
sessionsM sessions.SessionManagement, next http.Handler,
) http.Handler {
returnNoAccess := func(w http.ResponseWriter, r *http.Request) {
log.Printf("auth middle > restricting access to %s", r.URL.Path)
w.Header().Add("HX-Replace-Url", loginPath)
renderLoginPage(w)
}
rerturnSuccess := func(w http.ResponseWriter, r *http.Request, session sessions.SessionData) {
ctx := context.WithValue(r.Context(), contextKey("session"), session)
log.Printf("auth middle > allowing access to %s for %+v", r.URL.Path, session)
next.ServeHTTP(w, r.WithContext(ctx))
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sessionCookie, err := r.Cookie(authCookieName)
if err != nil {
returnNoAccess(w, r)
return
}
// TODO log here, why i get 'error readin 0'
sessionId, err := strconv.Atoi(sessionCookie.Value)
if err != nil {
returnNoAccess(w, r)
return
}
session := sessionsM.Get(sessionId)
if session == (sessions.SessionData{}) {
returnNoAccess(w, r)
return
} else {
rerturnSuccess(w, r, session)
return
}
})
}
func renderLoginPage(w http.ResponseWriter) {
var templFile = "templates/login.gohtml" var templFile = "templates/login.gohtml"
tmpl := template.Must(template.ParseFS(templateFs, templFile)) tmpl := template.Must(template.ParseFS(templateFs, templFile))
err := tmpl.Execute(w, nil) err := tmpl.Execute(w, nil)
if err != nil { if err != nil {
log.Printf("my error in executing template, huh\n %s", err) log.Printf("my error in executing template, huh\n %s", err)
} }
}
// function to register all http routes for servicing auth pages and logic
func registerLoginRoutes(
templateFs *embed.FS,
sessionSM sessions.SessionManagement,
roomsM rooms.RoomManager,
) {
// login page
http.HandleFunc(loginPath, func(w http.ResponseWriter, r *http.Request) {
renderLoginPage(w)
}) })
// when the room exists - attempt to join // when the room exists - attempt to join
@ -49,7 +102,7 @@ func registerLoginRoutes(
roomId := "room-name-actually" // would be taken from rooms interface from redis roomId := "room-name-actually" // would be taken from rooms interface from redis
// would be either taken from room info on correct person pass or created // would be either taken from room info on correct person pass or created
personId := 111 personId := 111
id, err := sessionSM.Save(roomId, int64(personId)) id, err := sessionSM.Save(roomId, personId)
if err != nil { if err != nil {
log.Printf("/login/submit > error saving session %s", err) log.Printf("/login/submit > error saving session %s", err)
} }
@ -75,33 +128,37 @@ func registerLoginRoutes(
_, exists, _ := roomsM.Get(roomName) _, exists, _ := roomsM.Get(roomName)
if exists { if exists {
// TODO return anouther error notice // TODO return anouther error notice
log.Printf("error, room name occupied", roomName) log.Printf("error, room name occupied %s", roomName)
return return
} }
person := rooms.Person{
PersonId: rand.Int(),
Name: r.PostFormValue("personalName"),
PasswordHash: r.PostFormValue("personalPassword"), // TODO hash the password, not to store
}
newRoom := rooms.Room{ newRoom := rooms.Room{
Name: roomName, Name: roomName,
PasswordHash: r.PostFormValue("roomPassword"), // TODO hash the password, not to store PasswordHash: r.PostFormValue("roomPassword"), // TODO hash the password, not to store
AdminIds: []int64{1}, AdminIds: []int{person.PersonId},
Paricipants: []rooms.Person{ Paricipants: []rooms.Person{person},
{
PersonId: 1,
Name: r.PostFormValue("personalName"),
PasswordHash: r.PostFormValue("personalPassword"),
},
},
} }
err = roomsM.Save(newRoom) err = roomsM.Save(newRoom)
http.SetCookie(w, &http.Cookie{
Name: "auth",
Value: "session-id",
Secure: true,
HttpOnly: true,
Path: "/",
})
if err != nil { if err != nil {
log.Printf("what am i to do? error saving room %s", err) log.Printf("what am i to do? error saving room %s", err)
// todo return error notice somehow // todo return error notice somehow
} }
newSessionId, err := sessionSM.Save(newRoom.Name, person.PersonId)
if err != nil {
log.Printf("what am i to do? error saving session %s", err)
// todo return error notice somehow
}
http.SetCookie(w, &http.Cookie{
Name: authCookieName,
Value: fmt.Sprint(newSessionId),
Secure: true,
HttpOnly: true,
Path: "/",
})
var templFile = "templates/index.gohtml" var templFile = "templates/index.gohtml"
tmpl := template.Must(template.ParseFS(templateFs, templFile)) tmpl := template.Must(template.ParseFS(templateFs, templFile))
w.Header().Add("HX-Retarget", "body") w.Header().Add("HX-Retarget", "body")

View File

@ -21,14 +21,16 @@ func RegisterRoutes(sessions sessions.SessionManagement, rooms rooms.RoomManager
registerLoginRoutes(&templateFs, sessions, rooms) registerLoginRoutes(&templateFs, sessions, rooms)
// main page template // main page template
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Handle("/", authedPageMiddleware(
sessions,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var templFile = "templates/index.gohtml" var templFile = "templates/index.gohtml"
tmpl := template.Must(template.ParseFS(templateFs, templFile)) tmpl := template.Must(template.ParseFS(templateFs, templFile))
err := tmpl.Execute(w, nil) err := tmpl.Execute(w, nil)
if err != nil { if err != nil {
log.Printf("my error in executing template, huh\n %s", err) log.Printf("my error in executing template, huh\n %s", err)
} }
}) })))
// static resources route // static resources route
http.Handle("/static/", http.Handle("/static/",

View File

@ -10,21 +10,21 @@ import (
) )
type SessionData struct { type SessionData struct {
SessionId int64 `redis:"session_id"` SessionId int `redis:"session_id"`
RoomId string `redis:"room_id"` RoomId string `redis:"room_id"`
PersonId int64 `redis:"person_id"` PersonId int `redis:"person_id"`
} }
type SessionManagement interface { type SessionManagement interface {
Get(sessionId int64) SessionData Get(sessionId int) SessionData
Save(roomId string, personId int64) (int64, error) Save(roomName string, personId int) (int, error)
} }
var ctx = context.Background() var ctx = context.Background()
const sessionPrefix = "session" const sessionPrefix = "session"
func sessionIdToKey(sessionId int64) string { func sessionIdToKey(sessionId int) string {
return fmt.Sprintf("%s:%d", sessionPrefix, sessionId) return fmt.Sprintf("%s:%d", sessionPrefix, sessionId)
} }
@ -32,21 +32,22 @@ type RedisSM struct {
Rdb *redis.Client Rdb *redis.Client
} }
func (redisSM RedisSM) Get(sessionId int64) SessionData { func (redisSM RedisSM) Get(sessionId int) SessionData {
var foundSession SessionData var foundSession SessionData
err := redisSM.Rdb.HGetAll(ctx, sessionIdToKey(sessionId)).Scan(foundSession) redisKey := sessionIdToKey(sessionId)
err := redisSM.Rdb.HGetAll(ctx, redisKey).Scan(&foundSession)
if err != nil { if err != nil {
log.Printf("> error reading %d", sessionId) log.Printf("> error reading %s : %s", redisKey, err)
return SessionData{} return SessionData{}
} }
log.Printf("> successfully found %d %+v", sessionId, foundSession) log.Printf("> successfully found %d %+v", sessionId, foundSession)
return foundSession return foundSession
} }
func (redisSM RedisSM) Save(roomId string, personId int64) (int64, error) { func (redisSM RedisSM) Save(roomName string, personId int) (int, error) {
randId := rand.Int63() randId := rand.Int()
newSession := SessionData{ newSession := SessionData{
SessionId: randId, SessionId: randId,
RoomId: roomId, RoomId: roomName,
PersonId: personId, PersonId: personId,
} }
err := redisSM.Rdb.HSet(ctx, sessionIdToKey(randId), newSession).Err() err := redisSM.Rdb.HSet(ctx, sessionIdToKey(randId), newSession).Err()
@ -59,11 +60,11 @@ func (redisSM RedisSM) Save(roomId string, personId int64) (int64, error) {
type DummySM struct{} type DummySM struct{}
func (d DummySM) Get(sessionId int64) SessionData { func (d DummySM) Get(sessionId int) SessionData {
log.Printf("get dummy session by %d", sessionId) log.Printf("get dummy session by %d", sessionId)
return SessionData{} return SessionData{}
} }
func (d DummySM) Save(roomId string, personId int64) (int64, error) { func (d DummySM) Save(roomName string, personId int) (int, error) {
log.Printf("save dummy session with %d %d", roomId, personId) log.Printf("save dummy session with %s %d", roomName, personId)
return 1, nil return 1, nil
} }