Compare commits
4 Commits
de8a661952
...
5cab5d88d9
Author | SHA1 | Date |
---|---|---|
|
5cab5d88d9 | |
|
a502ee72a0 | |
|
cc33c3f742 | |
|
e0bd77fe3b |
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
@ -50,13 +51,14 @@ func (r *Room) UnmarshalBinary(data []byte) error {
|
||||||
// let's check whether it will be possible to save nested structs
|
// let's check whether it will be possible to save nested structs
|
||||||
|
|
||||||
type RoomManager interface {
|
type RoomManager interface {
|
||||||
Get(roomName string) (Room, bool, error)
|
Get(ctx context.Context, roomName string) (Room, bool, error)
|
||||||
Save(room Room) error
|
Save(ctx context.Context, room Room) error
|
||||||
Update(ctx context.Context, roomName string, f func(fromRoom Room) (toRoom Room)) error
|
Update(ctx context.Context, roomName string, f func(fromRoom Room) (toRoom Room)) error
|
||||||
Subscribe(ctx context.Context, roomName string) <-chan Room
|
Subscribe(ctx context.Context, roomName string) <-chan Room
|
||||||
}
|
}
|
||||||
|
|
||||||
const roomRedisPrefix = "room"
|
const roomRedisPrefix = "room"
|
||||||
|
const roomTtl = 24 * time.Hour
|
||||||
|
|
||||||
func roomNameToRedisId(roomName string) string {
|
func roomNameToRedisId(roomName string) string {
|
||||||
return fmt.Sprintf("%s:%s", roomRedisPrefix, roomName)
|
return fmt.Sprintf("%s:%s", roomRedisPrefix, roomName)
|
||||||
|
@ -66,9 +68,9 @@ type RedisRM struct {
|
||||||
Rdb *redis.Client
|
Rdb *redis.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (redisRM RedisRM) Get(roomName string) (Room, bool, error) {
|
func (redisRM RedisRM) Get(ctx context.Context, roomName string) (Room, bool, error) {
|
||||||
var readRoom Room
|
var readRoom Room
|
||||||
err := redisRM.Rdb.Get(context.TODO(), roomNameToRedisId(roomName)).Scan(&readRoom)
|
err := redisRM.Rdb.Get(ctx, roomNameToRedisId(roomName)).Scan(&readRoom)
|
||||||
if err == redis.Nil {
|
if err == redis.Nil {
|
||||||
return Room{}, false, nil
|
return Room{}, false, nil
|
||||||
}
|
}
|
||||||
|
@ -155,7 +157,7 @@ func (redisRM RedisRM) Update(ctx context.Context, roomName string, f func(fromR
|
||||||
|
|
||||||
_, err = tx.Pipelined(ctx, func(pipe redis.Pipeliner) error {
|
_, err = tx.Pipelined(ctx, func(pipe redis.Pipeliner) error {
|
||||||
log.Printf(">> about to Set %s to %v", roomName, room)
|
log.Printf(">> about to Set %s to %v", roomName, room)
|
||||||
pipe.Set(ctx, roomKey, &room, 0)
|
pipe.Set(ctx, roomKey, &room, roomTtl)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -177,7 +179,7 @@ func (redisRM RedisRM) Update(ctx context.Context, roomName string, f func(fromR
|
||||||
return errors.New("update reached maximum amount of retries")
|
return errors.New("update reached maximum amount of retries")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (redisRM RedisRM) Save(room Room) error {
|
func (redisRM RedisRM) Save(ctx context.Context, room Room) error {
|
||||||
err := redisRM.Rdb.Set(context.TODO(), roomNameToRedisId(room.Name), &room, 0).Err() // maybe even set expiration?
|
err := redisRM.Rdb.Set(ctx, roomNameToRedisId(room.Name), &room, roomTtl).Err()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ func indexPageRoute(
|
||||||
) http.HandlerFunc {
|
) http.HandlerFunc {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
session, err := getRequestSession(r, sessionSM)
|
session, err := getRequestSession(r, sessionSM)
|
||||||
|
log.Printf("/ the session i got is %+v", session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("/ session not found, means should render the login section %s", err)
|
log.Printf("/ session not found, means should render the login section %s", err)
|
||||||
// TODO return error i guess
|
// TODO return error i guess
|
||||||
|
@ -53,7 +54,7 @@ func indexPageRoute(
|
||||||
|
|
||||||
data := pageData{
|
data := pageData{
|
||||||
Base: baseData{
|
Base: baseData{
|
||||||
Title: "hello base template title",
|
Title: "Some Automoderation: simple automation",
|
||||||
},
|
},
|
||||||
Header: headerData{
|
Header: headerData{
|
||||||
Title: session.RoomId,
|
Title: session.RoomId,
|
||||||
|
|
|
@ -71,7 +71,7 @@ func getRequestSession(r *http.Request,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sessions.SessionData{}, ErrAuthCookieValueInvalid
|
return sessions.SessionData{}, ErrAuthCookieValueInvalid
|
||||||
}
|
}
|
||||||
session := sessionsM.Get(sessionId)
|
session := sessionsM.Get(r.Context(), sessionId)
|
||||||
if session == (sessions.SessionData{}) {
|
if session == (sessions.SessionData{}) {
|
||||||
return sessions.SessionData{}, ErrAuthSessionNotFound
|
return sessions.SessionData{}, ErrAuthSessionNotFound
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ func renderLoginPage(w http.ResponseWriter, roomName string, isRoomExisting bool
|
||||||
|
|
||||||
title := "Some Automoderation: Join room or create one"
|
title := "Some Automoderation: Join room or create one"
|
||||||
if roomName != "" {
|
if roomName != "" {
|
||||||
title = fmt.Sprintf("Some Automoderation: create or join '%s' room", roomName)
|
title = fmt.Sprintf("Some Automoderation: join room '%s'", roomName)
|
||||||
}
|
}
|
||||||
data := pageData{
|
data := pageData{
|
||||||
Base: baseData{
|
Base: baseData{
|
||||||
|
@ -146,7 +146,7 @@ func createRoomHandler(templateFs *embed.FS,
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
roomName := r.PostFormValue("roomName")
|
roomName := r.PostFormValue("roomName")
|
||||||
_, exists, _ := roomsM.Get(roomName)
|
_, exists, _ := roomsM.Get(r.Context(), roomName)
|
||||||
if exists {
|
if exists {
|
||||||
// TODO return anouther error notice
|
// TODO return anouther error notice
|
||||||
log.Printf("error, room name occupied %s", roomName)
|
log.Printf("error, room name occupied %s", roomName)
|
||||||
|
@ -171,12 +171,13 @@ func createRoomHandler(templateFs *embed.FS,
|
||||||
AllKnownPeople: map[rooms.PersonId]rooms.Person{
|
AllKnownPeople: map[rooms.PersonId]rooms.Person{
|
||||||
person.Id: person},
|
person.Id: person},
|
||||||
}
|
}
|
||||||
err = roomsM.Save(newRoom)
|
err = roomsM.Save(r.Context(), newRoom)
|
||||||
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
|
||||||
}
|
}
|
||||||
newSession, err := sessionSM.Save(r.Context(), newRoom.Name, person.Id)
|
newSession, err := sessionSM.Save(r.Context(), newRoom.Name, person.Id)
|
||||||
|
log.Printf("saving session %v", newSession)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("what am i to do? error saving session %s", err)
|
log.Printf("what am i to do? error saving session %s", err)
|
||||||
// todo return error notice somehow
|
// todo return error notice somehow
|
||||||
|
@ -187,6 +188,7 @@ func createRoomHandler(templateFs *embed.FS,
|
||||||
Secure: true,
|
Secure: true,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
Expires: time.Now().Add(newSession.ExpireIn),
|
||||||
})
|
})
|
||||||
w.Header().Add("HX-Redirect", fmt.Sprintf("/room/%s", newRoom.Name))
|
w.Header().Add("HX-Redirect", fmt.Sprintf("/room/%s", newRoom.Name))
|
||||||
}
|
}
|
||||||
|
@ -203,7 +205,7 @@ func checkRoomName(templateFs *embed.FS,
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
roomName := r.PostFormValue("roomName")
|
roomName := r.PostFormValue("roomName")
|
||||||
_, isFound, err := roomsM.Get(roomName)
|
_, isFound, err := roomsM.Get(r.Context(), roomName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("/login/room-name-check error finding room %s\n", err)
|
log.Printf("/login/room-name-check error finding room %s\n", err)
|
||||||
}
|
}
|
||||||
|
@ -229,7 +231,7 @@ func joinRoomHandler(templateFs *embed.FS,
|
||||||
personPass := r.PostFormValue("personalPassword")
|
personPass := r.PostFormValue("personalPassword")
|
||||||
|
|
||||||
// a) get room data
|
// a) get room data
|
||||||
room, _, err := roomsM.Get(roomName)
|
room, _, err := roomsM.Get(r.Context(), roomName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("/login/join error getting room %s", roomName)
|
log.Printf("/login/join error getting room %s", roomName)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -308,6 +310,7 @@ func joinRoomHandler(templateFs *embed.FS,
|
||||||
}
|
}
|
||||||
|
|
||||||
newSession, err := sessionSM.Save(r.Context(), room.Name, person.Id)
|
newSession, err := sessionSM.Save(r.Context(), room.Name, person.Id)
|
||||||
|
log.Printf("saving session %v", newSession)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("/login/submit > error saving session %s", err)
|
log.Printf("/login/submit > error saving session %s", err)
|
||||||
}
|
}
|
||||||
|
@ -317,6 +320,7 @@ func joinRoomHandler(templateFs *embed.FS,
|
||||||
Secure: true,
|
Secure: true,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
Expires: time.Now().Add(newSession.ExpireIn),
|
||||||
})
|
})
|
||||||
log.Printf("is is %+v. room things %s & %s, personal things %s and %s. \n found room %+v",
|
log.Printf("is is %+v. room things %s & %s, personal things %s and %s. \n found room %+v",
|
||||||
newSession, roomName, roomPass, personName, personPass, room,
|
newSession, roomName, roomPass, personName, personPass, room,
|
||||||
|
|
|
@ -223,7 +223,7 @@ func roomPageRoute(
|
||||||
|
|
||||||
// check session,
|
// check session,
|
||||||
session, err := getRequestSession(r, sessionSM)
|
session, err := getRequestSession(r, sessionSM)
|
||||||
room, found, err := roomsM.Get(roomName)
|
room, found, err := roomsM.Get(r.Context(), roomName)
|
||||||
if err != nil || session.RoomId != roomName {
|
if err != nil || session.RoomId != roomName {
|
||||||
log.Printf("not authed with session %+v | error %s, but for wrong room, trying to access %s", session, err, roomName)
|
log.Printf("not authed with session %+v | error %s, but for wrong room, trying to access %s", session, err, roomName)
|
||||||
renderLoginPage(w, roomName, found)
|
renderLoginPage(w, roomName, found)
|
||||||
|
@ -268,7 +268,7 @@ func roomPageRoute(
|
||||||
}
|
}
|
||||||
data := pageData{
|
data := pageData{
|
||||||
Base: baseData{
|
Base: baseData{
|
||||||
Title: "room-lala-from-base",
|
Title: fmt.Sprintf("Some Automoderation: discussion in '%s'", room.Name),
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
},
|
},
|
||||||
Content: contentData,
|
Content: contentData,
|
||||||
|
|
|
@ -16,15 +16,18 @@ type SessionData struct {
|
||||||
SessionId int `redis:"session_id"`
|
SessionId int `redis:"session_id"`
|
||||||
RoomId string `redis:"room_id"`
|
RoomId string `redis:"room_id"`
|
||||||
PersonId rooms.PersonId `redis:"person_id"`
|
PersonId rooms.PersonId `redis:"person_id"`
|
||||||
|
ExpireIn time.Duration `redis:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionManagement interface {
|
type SessionManagement interface {
|
||||||
Get(sessionId int) SessionData
|
Get(ctx context.Context, sessionId int) SessionData
|
||||||
Save(ctx context.Context, roomName string, personId rooms.PersonId) (SessionData, error)
|
Save(ctx context.Context, roomName string, personId rooms.PersonId) (SessionData, error)
|
||||||
Remove(ctx context.Context, sessionId int) error
|
Remove(ctx context.Context, sessionId int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionPrefix = "session"
|
const sessionPrefix = "session"
|
||||||
|
const SessionTtl = 3 * time.Hour
|
||||||
|
const SessionProlongationWindow = time.Hour
|
||||||
|
|
||||||
func sessionIdToKey(sessionId int) string {
|
func sessionIdToKey(sessionId int) string {
|
||||||
return fmt.Sprintf("%s:%d", sessionPrefix, sessionId)
|
return fmt.Sprintf("%s:%d", sessionPrefix, sessionId)
|
||||||
|
@ -34,15 +37,34 @@ type RedisSM struct {
|
||||||
Rdb *redis.Client
|
Rdb *redis.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (redisSM RedisSM) Get(sessionId int) SessionData {
|
func (redisSM RedisSM) Get(ctx context.Context, sessionId int) SessionData {
|
||||||
var foundSession SessionData
|
var foundSession SessionData
|
||||||
redisKey := sessionIdToKey(sessionId)
|
redisKey := sessionIdToKey(sessionId)
|
||||||
err := redisSM.Rdb.HGetAll(context.TODO(), redisKey).Scan(&foundSession)
|
err := redisSM.Rdb.HGetAll(ctx, redisKey).Scan(&foundSession)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("> error reading %s : %s", redisKey, err)
|
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)
|
||||||
|
ttl, err := redisSM.Rdb.TTL(ctx, redisKey).Result()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("> error getting ttl for session %+v", foundSession)
|
||||||
|
return foundSession
|
||||||
|
}
|
||||||
|
if ttl == -2 {
|
||||||
|
log.Printf("> ttl indicates session doesn't exist for session %+v", foundSession)
|
||||||
|
return SessionData{}
|
||||||
|
}
|
||||||
|
if ttl < SessionProlongationWindow {
|
||||||
|
err = redisSM.Rdb.Expire(ctx, redisKey, SessionTtl).Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("> error updating ttl for session %+v", foundSession)
|
||||||
|
return foundSession
|
||||||
|
} else {
|
||||||
|
ttl = SessionTtl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundSession.ExpireIn = ttl
|
||||||
return foundSession
|
return foundSession
|
||||||
}
|
}
|
||||||
func (redisSM RedisSM) Save(ctx context.Context, roomName string, personId rooms.PersonId) (SessionData, error) {
|
func (redisSM RedisSM) Save(ctx context.Context, roomName string, personId rooms.PersonId) (SessionData, error) {
|
||||||
|
@ -51,9 +73,10 @@ func (redisSM RedisSM) Save(ctx context.Context, roomName string, personId rooms
|
||||||
SessionId: randId,
|
SessionId: randId,
|
||||||
RoomId: roomName,
|
RoomId: roomName,
|
||||||
PersonId: personId,
|
PersonId: personId,
|
||||||
|
ExpireIn: SessionTtl,
|
||||||
}
|
}
|
||||||
err := redisSM.Rdb.HSet(ctx, sessionIdToKey(randId), newSession).Err()
|
err := redisSM.Rdb.HSet(ctx, sessionIdToKey(randId), newSession).Err()
|
||||||
redisSM.Rdb.Expire(ctx, sessionIdToKey(randId), 24 * time.Hour)
|
redisSM.Rdb.Expire(ctx, sessionIdToKey(randId), SessionTtl)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("> error! saving session %+v %s", newSession, err)
|
log.Printf("> error! saving session %+v %s", newSession, err)
|
||||||
|
@ -69,7 +92,7 @@ func (redisSM RedisSM) Remove(ctx context.Context, sessionId int) error {
|
||||||
|
|
||||||
type DummySM struct{}
|
type DummySM struct{}
|
||||||
|
|
||||||
func (d DummySM) Get(sessionId int) SessionData {
|
func (d DummySM) Get(ctx context.Context, sessionId int) SessionData {
|
||||||
log.Printf("get dummy session by %d", sessionId)
|
log.Printf("get dummy session by %d", sessionId)
|
||||||
return SessionData{}
|
return SessionData{}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue