Feat: add password for player
This commit is contained in:
		| @@ -8,8 +8,12 @@ | |||||||
|         <input type="hidden" name="room_id" value={{.}}> |         <input type="hidden" name="room_id" value={{.}}> | ||||||
|       </div> |       </div> | ||||||
|   <div id="login_notice">this name looks available</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> |     <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> |     </div> | ||||||
|   </form> |   </form> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -2,12 +2,16 @@ | |||||||
|     <div id="logindiv"> |     <div id="logindiv"> | ||||||
|         <form class="space-y-6" hx-post="/login" hx-target="#ancestor"> |         <form class="space-y-6" hx-post="/login" hx-target="#ancestor"> | ||||||
|           <div> |           <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"> |             <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"/> |               <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> | ||||||
| 	<div id="login_notice">this name looks available</div> | 	<div id="login_notice">this name looks available</div> | ||||||
|           </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> |           <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> |           </div> | ||||||
|   | |||||||
| @@ -1,9 +1,6 @@ | |||||||
| {{define "roomlist"}} | {{define "roomlist"}} | ||||||
| <div id="roomlist" hx-get="/" hx-trigger="sse:roomlistupdate" hx-target="#ancestor"> | <div id="roomlist" hx-get="/" hx-trigger="sse:roomlistupdate" hx-target="#ancestor"> | ||||||
| {{range .}} | {{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 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="flex justify-between items-center"> | ||||||
|         <div class="room-info"> |         <div class="room-info"> | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"database/sql" | 	"database/sql" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"gralias/broker" | ||||||
|  | 	"gralias/models" | ||||||
| 	"gralias/repos" | 	"gralias/repos" | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"time" | 	"time" | ||||||
| @@ -61,7 +63,6 @@ func (cm *CronManager) CleanupRooms() { | |||||||
| 			cm.log.Error("failed to get players for room", "room_id", room.ID, "err", err) | 			cm.log.Error("failed to get players for room", "room_id", room.ID, "err", err) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if len(players) == 0 { | 		if len(players) == 0 { | ||||||
| 			cm.log.Info("deleting empty room", "room_id", room.ID) | 			cm.log.Info("deleting empty room", "room_id", room.ID) | ||||||
| 			if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil { | 			if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil { | ||||||
| @@ -72,7 +73,6 @@ func (cm *CronManager) CleanupRooms() { | |||||||
| 			} | 			} | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		creatorInRoom := false | 		creatorInRoom := false | ||||||
| 		for _, player := range players { | 		for _, player := range players { | ||||||
| 			if player.Username == room.CreatorName { | 			if player.Username == room.CreatorName { | ||||||
| @@ -80,7 +80,6 @@ func (cm *CronManager) CleanupRooms() { | |||||||
| 				break | 				break | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		isInactive := false | 		isInactive := false | ||||||
| 		// If the creator is in the room and the room is more than one hour old, check for inactivity | 		// 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 { | 		if creatorInRoom && time.Since(room.CreatedAt) > time.Hour { | ||||||
| @@ -104,7 +103,6 @@ func (cm *CronManager) CleanupRooms() { | |||||||
| 				reason = "inactive" | 				reason = "inactive" | ||||||
| 			} | 			} | ||||||
| 			cm.log.Info("deleting room", "room_id", room.ID, "reason", reason) | 			cm.log.Info("deleting room", "room_id", room.ID, "reason", reason) | ||||||
|  |  | ||||||
| 			for _, player := range players { | 			for _, player := range players { | ||||||
| 				if player.IsBot { | 				if player.IsBot { | ||||||
| 					if err := cm.repo.PlayerDelete(ctx, room.ID); err != nil { | 					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 { | 			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) | 				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 { | 			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) | 				cm.log.Error("failed to delete settings for room", "room_id", room.ID, "reason", reason, "err", err) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// Move to the next room | 			// Move to the next room | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| @@ -131,6 +127,10 @@ func (cm *CronManager) CleanupRooms() { | |||||||
| 	if err := tx.Commit(); err != nil { | 	if err := tx.Commit(); err != nil { | ||||||
| 		cm.log.Error("failed to commit transaction", "err", err) | 		cm.log.Error("failed to commit transaction", "err", err) | ||||||
| 	} | 	} | ||||||
|  | 	broker.Notifier.Notifier <- broker.NotificationEvent{ | ||||||
|  | 		EventName: models.NotifyRoomListUpdate, | ||||||
|  | 		Payload:   "", | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cm *CronManager) CleanupActions() { | func (cm *CronManager) CleanupActions() { | ||||||
|   | |||||||
| @@ -37,7 +37,6 @@ func HandleNameCheck(w http.ResponseWriter, r *http.Request) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	cleanName := utils.RemoveSpacesFromStr(username) | 	cleanName := utils.RemoveSpacesFromStr(username) | ||||||
| 	// allNames := getAllNames() |  | ||||||
| 	allNames, err := repo.PlayerListNames(r.Context()) | 	allNames, err := repo.PlayerListNames(r.Context()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| @@ -74,10 +73,12 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, msg) | 		abortWithError(w, msg) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 	password := r.PostFormValue("password") | ||||||
| 	var makeplayer bool | 	var makeplayer bool | ||||||
| 	roomID := r.PostFormValue("room_id") | 	roomID := r.PostFormValue("room_id") | ||||||
| 	// make sure username does not exists | 	// make sure username does not exists | ||||||
| 	cleanName := utils.RemoveSpacesFromStr(username) | 	cleanName := utils.RemoveSpacesFromStr(username) | ||||||
|  | 	clearPass := utils.RemoveSpacesFromStr(password) | ||||||
| 	// login user | 	// login user | ||||||
| 	cookie, err := makeCookie(cleanName, r.RemoteAddr) | 	cookie, err := makeCookie(cleanName, r.RemoteAddr) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -85,15 +86,19 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	http.SetCookie(w, cookie) |  | ||||||
| 	// check if that user was already in db | 	// check if that user was already in db | ||||||
| 	// userstate, err := loadState(cleanName) |  | ||||||
| 	userstate, err := repo.PlayerGetByName(r.Context(), cleanName) | 	userstate, err := repo.PlayerGetByName(r.Context(), cleanName) | ||||||
| 	if err != nil || userstate == nil { | 	if err != nil || userstate == nil { | ||||||
| 		log.Debug("making new player", "error", err, "state", userstate) | 		log.Debug("making new player", "error", err, "state", userstate) | ||||||
| 		userstate = models.InitPlayer(cleanName) | 		userstate = models.InitPlayer(cleanName) | ||||||
| 		makeplayer = true | 		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{ | 	fi := &models.FullInfo{ | ||||||
| 		State: userstate, | 		State: userstate, | ||||||
| 	} | 	} | ||||||
| @@ -106,20 +111,12 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 			abortWithError(w, err.Error()) | 			abortWithError(w, err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		// room.PlayerList = append(room.PlayerList, fi.State.Username) |  | ||||||
| 		// fi.Room = room |  | ||||||
| 		fi.List = nil | 		fi.List = nil | ||||||
| 		fi.State.RoomID = &room.ID | 		fi.State.RoomID = &room.ID | ||||||
| 		if err := repo.PlayerSetRoomID(r.Context(), room.ID, fi.State.Username); err != nil { | 		if err := repo.PlayerSetRoomID(r.Context(), room.ID, fi.State.Username); err != nil { | ||||||
| 			abortWithError(w, err.Error()) | 			abortWithError(w, err.Error()) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		// repo.RoomUpdate() |  | ||||||
| 		// save full info instead |  | ||||||
| 		// if err := saveFullInfo(r.Context(), fi); err != nil { |  | ||||||
| 		// 	abortWithError(w, err.Error()) |  | ||||||
| 		// 	return |  | ||||||
| 		// } |  | ||||||
| 	} else { | 	} else { | ||||||
| 		log.Debug("no room_id in login") | 		log.Debug("no room_id in login") | ||||||
| 		// fi.List = listRooms(false) | 		// fi.List = listRooms(false) | ||||||
| @@ -129,19 +126,15 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		// save state to cache | 		// save state to cache | ||||||
| 		// if err := saveState(cleanName, userstate); err != nil { |  | ||||||
| 		if makeplayer { | 		if makeplayer { | ||||||
|  | 			userstate.Password = clearPass | ||||||
| 			if err := repo.PlayerAdd(r.Context(), userstate); err != nil { | 			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) | 				log.Error("failed to save state", "error", err) | ||||||
| 				abortWithError(w, err.Error()) | 				abortWithError(w, err.Error()) | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// if err := tmpl.ExecuteTemplate(w, "base", fi); err != nil { |  | ||||||
| 	// 	log.Error("failed to execute base template", "error", err) |  | ||||||
| 	// } |  | ||||||
| 	http.Redirect(w, r, "/", 302) | 	http.Redirect(w, r, "/", 302) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -94,19 +94,16 @@ func HandleExit(w http.ResponseWriter, r *http.Request) { | |||||||
| 		} | 		} | ||||||
| 		notify(models.NotifyRoomListUpdate, "") | 		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 { | 	if err := repo.PlayerExitRoom(r.Context(), fi.State.Username); err != nil { | ||||||
|  | 		log.Error("failed to exit room", "error", err) | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		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()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// fi.List = listRooms(false) |  | ||||||
| 	fi.List, err = repo.RoomList(r.Context()) | 	fi.List, err = repo.RoomList(r.Context()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ CREATE TABLE players ( | |||||||
|     id INTEGER PRIMARY KEY AUTOINCREMENT, |     id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
|     room_id TEXT, -- nullable |     room_id TEXT, -- nullable | ||||||
|     username TEXT NOT NULL UNIQUE, |     username TEXT NOT NULL UNIQUE, | ||||||
|  |     password TEXT NOT NULL DEFAULT '', | ||||||
|     team TEXT NOT NULL DEFAULT '', -- 'red' or 'blue' |     team TEXT NOT NULL DEFAULT '', -- 'red' or 'blue' | ||||||
|     role TEXT NOT NULL DEFAULT '', -- 'guesser' or 'mime' |     role TEXT NOT NULL DEFAULT '', -- 'guesser' or 'mime' | ||||||
|     is_bot BOOLEAN NOT NULL DEFAULT FALSE, |     is_bot BOOLEAN NOT NULL DEFAULT FALSE, | ||||||
|   | |||||||
| @@ -106,6 +106,7 @@ type Player struct { | |||||||
| 	ID       uint32   `json:"id" db:"id"` | 	ID       uint32   `json:"id" db:"id"` | ||||||
| 	RoomID   *string  `json:"room_id" db:"room_id"` | 	RoomID   *string  `json:"room_id" db:"room_id"` | ||||||
| 	Username string   `json:"username" db:"username"` | 	Username string   `json:"username" db:"username"` | ||||||
|  | 	Password string   `json:"-" db:"password"` | ||||||
| 	Team     UserTeam `json:"team" db:"team"` | 	Team     UserTeam `json:"team" db:"team"` | ||||||
| 	Role     UserRole `json:"role" db:"role"` | 	Role     UserRole `json:"role" db:"role"` | ||||||
| 	IsBot    bool     `json:"is_bot" db:"is_bot"` | 	IsBot    bool     `json:"is_bot" db:"is_bot"` | ||||||
| @@ -153,7 +154,6 @@ type PlayerStats struct { | |||||||
| 	PlayedAsGuesser     int     `db:"played_as_guesser"` | 	PlayedAsGuesser     int     `db:"played_as_guesser"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| type Room struct { | type Room struct { | ||||||
| 	ID             string    `json:"id" db:"id"` | 	ID             string    `json:"id" db:"id"` | ||||||
| 	CreatedAt      time.Time `json:"created_at" db:"created_at"` | 	CreatedAt      time.Time `json:"created_at" db:"created_at"` | ||||||
| @@ -465,7 +465,6 @@ type FullInfo struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (f *FullInfo) ExitRoom() *Room { | 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.RedTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.RedTeam.Guessers) | ||||||
| 	f.Room.BlueTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.BlueTeam.Guessers) | 	f.Room.BlueTeam.Guessers = utils.RemoveFromSlice(f.State.Username, f.Room.BlueTeam.Guessers) | ||||||
| 	if f.Room.RedTeam.Mime == f.State.Username { | 	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 { | 	if f.Room.BlueTeam.Mime == f.State.Username { | ||||||
| 		f.Room.BlueTeam.Mime = "" | 		f.Room.BlueTeam.Mime = "" | ||||||
| 	} | 	} | ||||||
| 	// f.State.ExitRoom() | 	f.State.RoomID = nil | ||||||
| 	resp := f.Room | 	resp := f.Room | ||||||
| 	f.Room = nil | 	f.Room = nil | ||||||
| 	return resp | 	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) { | func (p *RepoProvider) PlayerGetByName(ctx context.Context, username string) (*models.Player, error) { | ||||||
| 	var player models.Player | 	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 { | 	if err != nil { | ||||||
| 		return nil, err | 		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 { | func (p *RepoProvider) PlayerAdd(ctx context.Context, player *models.Player) error { | ||||||
| 	db := getDB(ctx, p.DB) | 	db := getDB(ctx, p.DB) | ||||||
| 	_, err := db.ExecContext(ctx, "INSERT INTO players (room_id, username, team, role, is_bot) VALUES (?, ?, ?, ?, ?)", | 	_, 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.RoomID, player.Username, player.Team, player.Role, player.IsBot, player.Password) | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/jmoiron/sqlx" | 	"github.com/jmoiron/sqlx" | ||||||
| 	"github.com/stretchr/testify/assert" |  | ||||||
| 	_ "github.com/mattn/go-sqlite3" | 	_ "github.com/mattn/go-sqlite3" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func setupPlayersTestDB(t *testing.T) (*sqlx.DB, func()) { | 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, | 		id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
| 		room_id TEXT, | 		room_id TEXT, | ||||||
| 		username TEXT, | 		username TEXT, | ||||||
|  | 		password TEXT NOT NULL DEFAULT '', | ||||||
| 		team TEXT, | 		team TEXT, | ||||||
| 		role TEXT, | 		role TEXT, | ||||||
| 		is_bot BOOLEAN | 		is_bot BOOLEAN | ||||||
| @@ -105,4 +106,5 @@ func TestPlayersRepo_DeletePlayer(t *testing.T) { | |||||||
| 	err = db.Get(&count, "SELECT COUNT(*) FROM players WHERE room_id = ? AND username = ?", player.RoomID, player.Username) | 	err = db.Get(&count, "SELECT COUNT(*) FROM players WHERE room_id = ? AND username = ?", player.RoomID, player.Username) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 0, count) | 	assert.Equal(t, 0, count) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder