Feat: add password for player
This commit is contained in:
@ -8,8 +8,12 @@
|
||||
<input type="hidden" name="room_id" value={{.}}>
|
||||
</div>
|
||||
<div id="login_notice">this name looks available</div>
|
||||
<label For="password" class="block text-sm font-medium leading-6 text-white-900">password</label>
|
||||
<div>
|
||||
<input id="password" name="password" type="password" class="block w-full rounded-md border-0 bg-white py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 text-center"/>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign in</button>
|
||||
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign in</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -2,12 +2,16 @@
|
||||
<div id="logindiv">
|
||||
<form class="space-y-6" hx-post="/login" hx-target="#ancestor">
|
||||
<div>
|
||||
<label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username</label>
|
||||
<label For="username" class="block text-sm font-medium leading-6 text-white-900">tell us your username (signup|login)</label>
|
||||
<div class="mt-2">
|
||||
<input id="username" name="username" hx-target="#login_notice" hx-swap="outerHTML" hx-post="/check/name" hx-trigger="input changed delay:400ms" autocomplete="username" required class="block w-full rounded-md border-0 bg-white py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 text-center"/>
|
||||
</div>
|
||||
<div id="login_notice">this name looks available</div>
|
||||
</div>
|
||||
<div>
|
||||
<label For="password" class="block text-sm font-medium leading-6 text-white-900">password</label>
|
||||
<input id="password" name="password" type="password" class="block w-full rounded-md border-0 bg-white py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 text-center"/>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign in</button>
|
||||
</div>
|
||||
|
@ -1,9 +1,6 @@
|
||||
{{define "roomlist"}}
|
||||
<div id="roomlist" hx-get="/" hx-trigger="sse:roomlistupdate" hx-target="#ancestor">
|
||||
{{range .}}
|
||||
<p>
|
||||
{{.ID}}
|
||||
</p>
|
||||
<div hx-get="/room-join?id={{.ID}}" hx-target="#ancestor" class="room-item mb-3 p-4 border rounded-lg hover:bg-gray-50 transition-colors">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="room-info">
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"gralias/broker"
|
||||
"gralias/models"
|
||||
"gralias/repos"
|
||||
"log/slog"
|
||||
"time"
|
||||
@ -61,7 +63,6 @@ func (cm *CronManager) CleanupRooms() {
|
||||
cm.log.Error("failed to get players for room", "room_id", room.ID, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(players) == 0 {
|
||||
cm.log.Info("deleting empty room", "room_id", room.ID)
|
||||
if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil {
|
||||
@ -72,7 +73,6 @@ func (cm *CronManager) CleanupRooms() {
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
creatorInRoom := false
|
||||
for _, player := range players {
|
||||
if player.Username == room.CreatorName {
|
||||
@ -80,7 +80,6 @@ func (cm *CronManager) CleanupRooms() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
isInactive := false
|
||||
// If the creator is in the room and the room is more than one hour old, check for inactivity
|
||||
if creatorInRoom && time.Since(room.CreatedAt) > time.Hour {
|
||||
@ -104,7 +103,6 @@ func (cm *CronManager) CleanupRooms() {
|
||||
reason = "inactive"
|
||||
}
|
||||
cm.log.Info("deleting room", "room_id", room.ID, "reason", reason)
|
||||
|
||||
for _, player := range players {
|
||||
if player.IsBot {
|
||||
if err := cm.repo.PlayerDelete(ctx, room.ID); err != nil {
|
||||
@ -116,14 +114,12 @@ func (cm *CronManager) CleanupRooms() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil {
|
||||
cm.log.Error("failed to delete room", "room_id", room.ID, "reason", reason, "err", err)
|
||||
}
|
||||
if err := cm.repo.SettingsDeleteByRoomID(ctx, room.ID); err != nil {
|
||||
cm.log.Error("failed to delete settings for room", "room_id", room.ID, "reason", reason, "err", err)
|
||||
}
|
||||
|
||||
// Move to the next room
|
||||
continue
|
||||
}
|
||||
@ -131,6 +127,10 @@ func (cm *CronManager) CleanupRooms() {
|
||||
if err := tx.Commit(); err != nil {
|
||||
cm.log.Error("failed to commit transaction", "err", err)
|
||||
}
|
||||
broker.Notifier.Notifier <- broker.NotificationEvent{
|
||||
EventName: models.NotifyRoomListUpdate,
|
||||
Payload: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *CronManager) CleanupActions() {
|
||||
|
@ -37,7 +37,6 @@ func HandleNameCheck(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
cleanName := utils.RemoveSpacesFromStr(username)
|
||||
// allNames := getAllNames()
|
||||
allNames, err := repo.PlayerListNames(r.Context())
|
||||
if err != nil {
|
||||
abortWithError(w, err.Error())
|
||||
@ -74,10 +73,12 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
abortWithError(w, msg)
|
||||
return
|
||||
}
|
||||
password := r.PostFormValue("password")
|
||||
var makeplayer bool
|
||||
roomID := r.PostFormValue("room_id")
|
||||
// make sure username does not exists
|
||||
cleanName := utils.RemoveSpacesFromStr(username)
|
||||
clearPass := utils.RemoveSpacesFromStr(password)
|
||||
// login user
|
||||
cookie, err := makeCookie(cleanName, r.RemoteAddr)
|
||||
if err != nil {
|
||||
@ -85,15 +86,19 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
// check if that user was already in db
|
||||
// userstate, err := loadState(cleanName)
|
||||
userstate, err := repo.PlayerGetByName(r.Context(), cleanName)
|
||||
if err != nil || userstate == nil {
|
||||
log.Debug("making new player", "error", err, "state", userstate)
|
||||
userstate = models.InitPlayer(cleanName)
|
||||
makeplayer = true
|
||||
}
|
||||
if userstate.Password != clearPass {
|
||||
log.Error("wrong password", "username", cleanName, "password", clearPass)
|
||||
abortWithError(w, "wrong password")
|
||||
return
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
fi := &models.FullInfo{
|
||||
State: userstate,
|
||||
}
|
||||
@ -106,20 +111,12 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
// room.PlayerList = append(room.PlayerList, fi.State.Username)
|
||||
// fi.Room = room
|
||||
fi.List = nil
|
||||
fi.State.RoomID = &room.ID
|
||||
if err := repo.PlayerSetRoomID(r.Context(), room.ID, fi.State.Username); err != nil {
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
// repo.RoomUpdate()
|
||||
// save full info instead
|
||||
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||
// abortWithError(w, err.Error())
|
||||
// return
|
||||
// }
|
||||
} else {
|
||||
log.Debug("no room_id in login")
|
||||
// fi.List = listRooms(false)
|
||||
@ -129,19 +126,15 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
// save state to cache
|
||||
// if err := saveState(cleanName, userstate); err != nil {
|
||||
if makeplayer {
|
||||
userstate.Password = clearPass
|
||||
if err := repo.PlayerAdd(r.Context(), userstate); err != nil {
|
||||
// if err := saveFullInfo(r.Context(), fi); err != nil {
|
||||
log.Error("failed to save state", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil {
|
||||
// log.Error("failed to execute base template", "error", err)
|
||||
// }
|
||||
http.Redirect(w, r, "/", 302)
|
||||
}
|
||||
|
||||
|
@ -94,19 +94,16 @@ func HandleExit(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
notify(models.NotifyRoomListUpdate, "")
|
||||
}
|
||||
// scary to update the whole room
|
||||
fiToSave := &models.FullInfo{
|
||||
Room: exitedRoom,
|
||||
}
|
||||
if err := repo.PlayerExitRoom(r.Context(), fi.State.Username); err != nil {
|
||||
log.Error("failed to exit room", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
if err := saveFullInfo(r.Context(), fiToSave); err != nil {
|
||||
if err := repo.RoomUpdate(r.Context(), exitedRoom); err != nil {
|
||||
log.Error("failed to update room", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
// fi.List = listRooms(false)
|
||||
fi.List, err = repo.RoomList(r.Context())
|
||||
if err != nil {
|
||||
abortWithError(w, err.Error())
|
||||
|
@ -21,6 +21,7 @@ CREATE TABLE players (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
room_id TEXT, -- nullable
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL DEFAULT '',
|
||||
team TEXT NOT NULL DEFAULT '', -- 'red' or 'blue'
|
||||
role TEXT NOT NULL DEFAULT '', -- 'guesser' or 'mime'
|
||||
is_bot BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
@ -106,6 +106,7 @@ type Player struct {
|
||||
ID uint32 `json:"id" db:"id"`
|
||||
RoomID *string `json:"room_id" db:"room_id"`
|
||||
Username string `json:"username" db:"username"`
|
||||
Password string `json:"-" db:"password"`
|
||||
Team UserTeam `json:"team" db:"team"`
|
||||
Role UserRole `json:"role" db:"role"`
|
||||
IsBot bool `json:"is_bot" db:"is_bot"`
|
||||
@ -153,7 +154,6 @@ type PlayerStats struct {
|
||||
PlayedAsGuesser int `db:"played_as_guesser"`
|
||||
}
|
||||
|
||||
|
||||
type Room struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
@ -465,7 +465,6 @@ type FullInfo struct {
|
||||
}
|
||||
|
||||
func (f *FullInfo) ExitRoom() *Room {
|
||||
// f.Room.PlayerList = utils.RemoveFromSlice(f.State.Username, f.Room.PlayerList)
|
||||
f.Room.RedTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.RedTeam.Guessers)
|
||||
f.Room.BlueTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.BlueTeam.Guessers)
|
||||
if f.Room.RedTeam.Mime == f.State.Username {
|
||||
@ -474,7 +473,7 @@ func (f *FullInfo) ExitRoom() *Room {
|
||||
if f.Room.BlueTeam.Mime == f.State.Username {
|
||||
f.Room.BlueTeam.Mime = ""
|
||||
}
|
||||
// f.State.ExitRoom()
|
||||
f.State.RoomID = nil
|
||||
resp := f.Room
|
||||
f.Room = nil
|
||||
return resp
|
||||
|
@ -32,7 +32,7 @@ func (p *RepoProvider) PlayerListNames(ctx context.Context) ([]string, error) {
|
||||
|
||||
func (p *RepoProvider) PlayerGetByName(ctx context.Context, username string) (*models.Player, error) {
|
||||
var player models.Player
|
||||
err := sqlx.GetContext(ctx, p.DB, &player, "SELECT id, room_id, username, team, role, is_bot FROM players WHERE username = ?", username)
|
||||
err := sqlx.GetContext(ctx, p.DB, &player, "SELECT id, room_id, username, team, role, is_bot, password FROM players WHERE username = ?", username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -44,8 +44,8 @@ func (p *RepoProvider) PlayerGetByName(ctx context.Context, username string) (*m
|
||||
|
||||
func (p *RepoProvider) PlayerAdd(ctx context.Context, player *models.Player) error {
|
||||
db := getDB(ctx, p.DB)
|
||||
_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)",
|
||||
player.RoomID, player.Username, player.Team, player.Role, player.IsBot)
|
||||
_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot, password) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
player.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.Password)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stretchr/testify/assert"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func setupPlayersTestDB(t *testing.T) (*sqlx.DB, func()) {
|
||||
@ -19,6 +19,7 @@ func setupPlayersTestDB(t *testing.T) (*sqlx.DB, func()) {
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
room_id TEXT,
|
||||
username TEXT,
|
||||
password TEXT NOT NULL DEFAULT '',
|
||||
team TEXT,
|
||||
role TEXT,
|
||||
is_bot BOOLEAN
|
||||
@ -106,3 +107,4 @@ func TestPlayersRepo_DeletePlayer(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, count)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user