feat: logout route and button

This commit is contained in:
efim 2023-11-14 04:18:25 +00:00
parent 1297fcf35d
commit 83e81ec011
9 changed files with 130 additions and 22 deletions

View File

@ -117,6 +117,16 @@ gestureIteration:
r.CurrentSpeaker = nextSpeakerId r.CurrentSpeaker = nextSpeakerId
} }
func (r *Room) PersonToStandUpFromTable(p PersonId) {
r.ReleaseHand(p)
if slices.Contains(r.Paricipants, p) {
updated := slices.DeleteFunc(r.Paricipants, func(sittingPerson PersonId) bool {
return sittingPerson == p
})
r.Paricipants = updated
}
}
// find place to start - separate function // find place to start - separate function
// current speaker level, searched gesture level, room marks // current speaker level, searched gesture level, room marks
// if search level >= current speaker start from speaker // if search level >= current speaker start from speaker

View File

@ -4,7 +4,12 @@ type baseData struct {
Title string Title string
} }
type headerData struct {
Title string
}
type pageData struct { type pageData struct {
Base baseData Base baseData
Content interface {} Content any
Header headerData
} }

View File

@ -27,18 +27,21 @@ func indexPageRoute(
type MainData struct { type MainData struct {
SessionStringToken string SessionStringToken string
SomeString string SomeString string
SessionToken sessions.SessionData SessionToken sessions.SessionData
} }
data := pageData { data := pageData{
Base: baseData{ Base: baseData{
Title: "hello base template title", Title: "hello base template title",
}, },
Header: headerData{
Title: session.RoomId,
},
Content: MainData{ Content: MainData{
fmt.Sprintf("%+v", session), fmt.Sprintf("%+v", session),
"hello!", "hello!",
session, session,
}, },
} }
tmpl := template.Must(template.ParseFS(templateFs, templFile, baseFile)) tmpl := template.Must(template.ParseFS(templateFs, templFile, baseFile))
err := tmpl.ExecuteTemplate(w, "full-page", data) err := tmpl.ExecuteTemplate(w, "full-page", data)

View File

@ -7,7 +7,9 @@ import (
"html/template" "html/template"
"log" "log"
"net/http" "net/http"
"slices"
"strconv" "strconv"
"time"
"sunshine.industries/some-automoderation/rooms" "sunshine.industries/some-automoderation/rooms"
"sunshine.industries/some-automoderation/sessions" "sunshine.industries/some-automoderation/sessions"
@ -30,6 +32,8 @@ func registerLoginRoutes(
http.HandleFunc("/login/join", joinRoomHandler(templateFs, sessionSM, roomsM)) http.HandleFunc("/login/join", joinRoomHandler(templateFs, sessionSM, roomsM))
http.HandleFunc("/login/create", createRoomHandler(templateFs, sessionSM, roomsM)) http.HandleFunc("/login/create", createRoomHandler(templateFs, sessionSM, roomsM))
http.HandleFunc("/login/room-name-check", checkRoomName(templateFs, roomsM)) http.HandleFunc("/login/room-name-check", checkRoomName(templateFs, roomsM))
http.Handle("/logout", authedPageMiddleware(sessionSM,
http.HandlerFunc(logoutRoute(sessionSM, roomsM))))
} }
const authCookieName = "auth" const authCookieName = "auth"
@ -89,7 +93,7 @@ func renderLoginPage(w http.ResponseWriter) {
baseFile := "templates/base.gohtml" baseFile := "templates/base.gohtml"
templFile := "templates/login.gohtml" templFile := "templates/login.gohtml"
tmpl := template.Must(template.ParseFS(templateFs, templFile, baseFile)) tmpl := template.Must(template.ParseFS(templateFs, templFile, baseFile))
data := pageData { data := pageData{
Base: baseData{ Base: baseData{
Title: "login", Title: "login",
}, },
@ -138,7 +142,7 @@ func createRoomHandler(templateFs *embed.FS,
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.Id) newSessionId, err := sessionSM.Save(r.Context(), newRoom.Name, person.Id)
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
@ -261,7 +265,10 @@ func joinRoomHandler(templateFs *embed.FS,
err = roomsM.Update(r.Context(), room.Name, func(fromRoom rooms.Room) (toRoom rooms.Room) { err = roomsM.Update(r.Context(), room.Name, func(fromRoom rooms.Room) (toRoom rooms.Room) {
toRoom = fromRoom toRoom = fromRoom
toRoom.Paricipants = append(toRoom.Paricipants, person.Id) if !slices.Contains(toRoom.Paricipants, person.Id) {
// consequtive login from additional devices
toRoom.Paricipants = append(toRoom.Paricipants, person.Id)
}
return toRoom return toRoom
}) })
if err != nil { if err != nil {
@ -272,7 +279,7 @@ func joinRoomHandler(templateFs *embed.FS,
return // error sitting a new person return // error sitting a new person
} }
newSessionId, err := sessionSM.Save(room.Name, person.Id) newSessionId, err := sessionSM.Save(r.Context(), room.Name, person.Id)
if err != nil { if err != nil {
log.Printf("/login/submit > error saving session %s", err) log.Printf("/login/submit > error saving session %s", err)
} }
@ -291,3 +298,41 @@ func joinRoomHandler(templateFs *embed.FS,
w.Header().Add("HX-Redirect", "/") w.Header().Add("HX-Redirect", "/")
} }
} }
func logoutRoute(sessionSM sessions.SessionManagement,
roomsM rooms.RoomManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, found := getContextSession(r.Context())
if !found {
log.Printf("/logout session not found, it's ok.")
// though this is under middleware for now, should be impossible
// TODO return error i guess
w.Header().Add("HX-Redirect", "/")
return
}
http.SetCookie(w, &http.Cookie{
Name: authCookieName,
Expires: time.Now().Add(-time.Hour),
Value: "",
Secure: true,
HttpOnly: true,
Path: "/",
})
err := sessionSM.Remove(r.Context(), session.SessionId)
if err != nil {
log.Printf("/logout error deleting session: %s", err)
}
err = roomsM.Update(r.Context(), session.RoomId, func(fromRoom rooms.Room) (toRoom rooms.Room) {
toRoom = fromRoom
toRoom.PersonToStandUpFromTable(session.PersonId)
return toRoom
})
if err != nil {
log.Printf("/logout error removing person from table: %s", err)
}
log.Printf("/logout deleting session %+v", session)
w.Header().Add("HX-Redirect", "/")
}
}

View File

@ -207,15 +207,15 @@ func roomPageRoute(
for gesture := rooms.ChangeTopic; gesture <= rooms.Meta; gesture++ { for gesture := rooms.ChangeTopic; gesture <= rooms.Meta; gesture++ {
gesturesData = append(gesturesData, GestureData{ gesturesData = append(gesturesData, GestureData{
Name: gesture.String(), Name: gesture.String(),
Url: fmt.Sprintf("%s%d", raiseHandPath, gesture), Url: fmt.Sprintf("%s%d", raiseHandPath, gesture),
}) })
} }
contentData := struct { contentData := struct {
Room rooms.Room Room rooms.Room
Gestures []GestureData Gestures []GestureData
}{ }{
Room: room, Room: room,
Gestures: gesturesData, Gestures: gesturesData,
} }
data := pageData{ data := pageData{
@ -223,6 +223,9 @@ func roomPageRoute(
Title: "room-lala-from-base", Title: "room-lala-from-base",
}, },
Content: contentData, Content: contentData,
Header: headerData{
Title: room.Name,
},
} }
err = tmpl.ExecuteTemplate(w, "full-page", data) err = tmpl.ExecuteTemplate(w, "full-page", data)

View File

@ -550,6 +550,10 @@ video {
display: grid; display: grid;
} }
.h-14 {
height: 3.5rem;
}
.h-full { .h-full {
height: 100%; height: 100%;
} }
@ -562,6 +566,10 @@ video {
width: 100%; width: 100%;
} }
.flex-none {
flex: none;
}
.grid-cols-2 { .grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
} }
@ -641,10 +649,25 @@ video {
background-color: rgb(255 255 255 / var(--tw-bg-opacity)); background-color: rgb(255 255 255 / var(--tw-bg-opacity));
} }
.bg-yellow-200 {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
.p-4 { .p-4 {
padding: 1rem; padding: 1rem;
} }
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.text-xl { .text-xl {
font-size: 1.25rem; font-size: 1.25rem;
line-height: 1.75rem; line-height: 1.75rem;

View File

@ -22,7 +22,16 @@
<link rel="apple-touch-icon" href="/apple-touch-icon.png" /> <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- Place favicon.ico in the root directory --> <!-- Place favicon.ico in the root directory -->
</head> </head>
<body> <body
class="flex flex-col"
>
<nav class="bg-yellow-200 flex-none h-14">
{{if .Header.Title}} Room name: "{{.Header.Title}}"{{end}}
<button
class="bg-white border-2 rounded py-1 px-2"
hx-get="/logout"
>Logout</button>
</nav>
<!--[if lt IE 8]> <!--[if lt IE 8]>
<p class="browserupgrade"> <p class="browserupgrade">
You are using an <strong>outdated</strong> browser. Please You are using an <strong>outdated</strong> browser. Please

View File

@ -46,7 +46,6 @@
{{ end }} {{ end }}
</div> </div>
<div id="controls" class="bg-green-300"> <div id="controls" class="bg-green-300">
<p>Room name is "{{ .Room.Name }}"</p>
{{ range .Gestures }} {{ range .Gestures }}
<button <button
hx-get="{{ .Url }}" hx-get="{{ .Url }}"

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"math/rand" "math/rand"
"time"
"sunshine.industries/some-automoderation/rooms" "sunshine.industries/some-automoderation/rooms"
@ -19,11 +20,10 @@ type SessionData struct {
type SessionManagement interface { type SessionManagement interface {
Get(sessionId int) SessionData Get(sessionId int) SessionData
Save(roomName string, personId rooms.PersonId) (int, error) Save(ctx context.Context, roomName string, personId rooms.PersonId) (int, error)
Remove(ctx context.Context, sessionId int) error
} }
var ctx = context.Background()
const sessionPrefix = "session" const sessionPrefix = "session"
func sessionIdToKey(sessionId int) string { func sessionIdToKey(sessionId int) string {
@ -37,7 +37,7 @@ type RedisSM struct {
func (redisSM RedisSM) Get(sessionId int) SessionData { func (redisSM RedisSM) Get(sessionId int) SessionData {
var foundSession SessionData var foundSession SessionData
redisKey := sessionIdToKey(sessionId) redisKey := sessionIdToKey(sessionId)
err := redisSM.Rdb.HGetAll(ctx, redisKey).Scan(&foundSession) err := redisSM.Rdb.HGetAll(context.TODO(), 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{}
@ -45,7 +45,7 @@ func (redisSM RedisSM) Get(sessionId int) 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(roomName string, personId rooms.PersonId) (int, error) { func (redisSM RedisSM) Save(ctx context.Context, roomName string, personId rooms.PersonId) (int, error) {
randId := rand.Int() randId := rand.Int()
newSession := SessionData{ newSession := SessionData{
SessionId: randId, SessionId: randId,
@ -53,6 +53,8 @@ func (redisSM RedisSM) Save(roomName string, personId rooms.PersonId) (int, erro
PersonId: personId, PersonId: personId,
} }
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)
if err != nil { if err != nil {
log.Printf("> error! saving session %+v %s", newSession, err) log.Printf("> error! saving session %+v %s", newSession, err)
return 0, fmt.Errorf("error saving new session: %+v with %s", newSession, err) return 0, fmt.Errorf("error saving new session: %+v with %s", newSession, err)
@ -60,13 +62,22 @@ func (redisSM RedisSM) Save(roomName string, personId rooms.PersonId) (int, erro
return randId, nil return randId, nil
} }
func (redisSM RedisSM) Remove(ctx context.Context, sessionId int) error {
err := redisSM.Rdb.Del(ctx, sessionIdToKey(sessionId)).Err()
return err
}
type DummySM struct{} type DummySM struct{}
func (d DummySM) Get(sessionId int) 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(roomName string, personId rooms.PersonId) (int, error) { func (d DummySM) Save(ctx context.Context, roomName string, personId rooms.PersonId) (int, error) {
log.Printf("save dummy session with %s %d", roomName, personId) log.Printf("save dummy session with %s %d", roomName, personId)
return 1, nil return 1, nil
} }
func (d DummySM) Remove(ctx context.Context, sessionId int) error {
log.Printf("deleting session %d", sessionId)
return nil
}