Feat: add password for player
This commit is contained in:
		| @@ -8,6 +8,10 @@ | ||||
|         <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> | ||||
|     </div> | ||||
|   | ||||
| @@ -2,11 +2,15 @@ | ||||
|     <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> | ||||
|   | ||||
| @@ -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
	 Grail Finder
					Grail Finder