diff --git a/rooms/rooms_manager.go b/rooms/rooms_manager.go index fb428a1..7292feb 100644 --- a/rooms/rooms_manager.go +++ b/rooms/rooms_manager.go @@ -10,14 +10,14 @@ import ( ) type Person struct { - PersonId int64 + PersonId int Name string PasswordHash string } type Room struct { Name string // will be unique ID - AdminIds []int64 + AdminIds []int PasswordHash string Paricipants []Person // TODO hands, for each type of hand? diff --git a/routes/login_page.go b/routes/login_page.go index c6ff7f1..2b56150 100644 --- a/routes/login_page.go +++ b/routes/login_page.go @@ -1,29 +1,82 @@ package routes import ( + "context" "embed" "fmt" "html/template" "log" + "math/rand" "net/http" + "strconv" "sunshine.industries/some-automoderation/rooms" "sunshine.industries/some-automoderation/sessions" ) +const authCookieName = "auth" +const loginPath = "/login" +type contextKey string + +// checks sessionId from cookie +// when non-zero session found - pass to next http.Hander +// 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" + tmpl := template.Must(template.ParseFS(templateFs, templFile)) + err := tmpl.Execute(w, nil) + if err != nil { + 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("/login", func(w http.ResponseWriter, r *http.Request) { - var templFile = "templates/login.gohtml" - tmpl := template.Must(template.ParseFS(templateFs, templFile)) - err := tmpl.Execute(w, nil) - if err != nil { - log.Printf("my error in executing template, huh\n %s", err) - } + http.HandleFunc(loginPath, func(w http.ResponseWriter, r *http.Request) { + renderLoginPage(w) }) // 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 // would be either taken from room info on correct person pass or created personId := 111 - id, err := sessionSM.Save(roomId, int64(personId)) + id, err := sessionSM.Save(roomId, personId) if err != nil { log.Printf("/login/submit > error saving session %s", err) } @@ -75,33 +128,37 @@ func registerLoginRoutes( _, exists, _ := roomsM.Get(roomName) if exists { // TODO return anouther error notice - log.Printf("error, room name occupied", roomName) + log.Printf("error, room name occupied %s", roomName) 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{ Name: roomName, PasswordHash: r.PostFormValue("roomPassword"), // TODO hash the password, not to store - AdminIds: []int64{1}, - Paricipants: []rooms.Person{ - { - PersonId: 1, - Name: r.PostFormValue("personalName"), - PasswordHash: r.PostFormValue("personalPassword"), - }, - }, + AdminIds: []int{person.PersonId}, + Paricipants: []rooms.Person{person}, } err = roomsM.Save(newRoom) - http.SetCookie(w, &http.Cookie{ - Name: "auth", - Value: "session-id", - Secure: true, - HttpOnly: true, - Path: "/", - }) if err != nil { log.Printf("what am i to do? error saving room %s", err) // 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" tmpl := template.Must(template.ParseFS(templateFs, templFile)) w.Header().Add("HX-Retarget", "body") diff --git a/routes/routes.go b/routes/routes.go index cd96508..7f7385d 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -21,14 +21,16 @@ func RegisterRoutes(sessions sessions.SessionManagement, rooms rooms.RoomManager registerLoginRoutes(&templateFs, sessions, rooms) // main page template - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - var templFile = "templates/index.gohtml" - tmpl := template.Must(template.ParseFS(templateFs, templFile)) - err := tmpl.Execute(w, nil) - if err != nil { - log.Printf("my error in executing template, huh\n %s", err) - } - }) + http.Handle("/", authedPageMiddleware( + sessions, + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var templFile = "templates/index.gohtml" + tmpl := template.Must(template.ParseFS(templateFs, templFile)) + err := tmpl.Execute(w, nil) + if err != nil { + log.Printf("my error in executing template, huh\n %s", err) + } + }))) // static resources route http.Handle("/static/", diff --git a/sessions/sessions_manager.go b/sessions/sessions_manager.go index e908bd4..93704f0 100644 --- a/sessions/sessions_manager.go +++ b/sessions/sessions_manager.go @@ -10,21 +10,21 @@ import ( ) type SessionData struct { - SessionId int64 `redis:"session_id"` + SessionId int `redis:"session_id"` RoomId string `redis:"room_id"` - PersonId int64 `redis:"person_id"` + PersonId int `redis:"person_id"` } type SessionManagement interface { - Get(sessionId int64) SessionData - Save(roomId string, personId int64) (int64, error) + Get(sessionId int) SessionData + Save(roomName string, personId int) (int, error) } var ctx = context.Background() const sessionPrefix = "session" -func sessionIdToKey(sessionId int64) string { +func sessionIdToKey(sessionId int) string { return fmt.Sprintf("%s:%d", sessionPrefix, sessionId) } @@ -32,21 +32,22 @@ type RedisSM struct { Rdb *redis.Client } -func (redisSM RedisSM) Get(sessionId int64) SessionData { +func (redisSM RedisSM) Get(sessionId int) 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 { - log.Printf("> error reading %d", sessionId) + log.Printf("> error reading %s : %s", redisKey, err) return SessionData{} } log.Printf("> successfully found %d %+v", sessionId, foundSession) return foundSession } -func (redisSM RedisSM) Save(roomId string, personId int64) (int64, error) { - randId := rand.Int63() +func (redisSM RedisSM) Save(roomName string, personId int) (int, error) { + randId := rand.Int() newSession := SessionData{ SessionId: randId, - RoomId: roomId, + RoomId: roomName, PersonId: personId, } 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{} -func (d DummySM) Get(sessionId int64) SessionData { +func (d DummySM) Get(sessionId int) SessionData { log.Printf("get dummy session by %d", sessionId) return SessionData{} } -func (d DummySM) Save(roomId string, personId int64) (int64, error) { - log.Printf("save dummy session with %d %d", roomId, personId) +func (d DummySM) Save(roomName string, personId int) (int, error) { + log.Printf("save dummy session with %s %d", roomName, personId) return 1, nil }