Fix endpoint for getting lobby id from passphrase
Had to add several helpers (e.g. passphrase ones) to make the endpoint for getting lobby id work. Moved all handler functions into handler package. Added test for getting lobby from passphrase.
This commit is contained in:
parent
11d6e8c98a
commit
d7c4f28f3a
@ -1,25 +1,49 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"mchess_server/api"
|
"mchess_server/api"
|
||||||
|
"mchess_server/chess"
|
||||||
lobbies "mchess_server/lobby_registry"
|
lobbies "mchess_server/lobby_registry"
|
||||||
|
"mchess_server/usher"
|
||||||
"mchess_server/utils"
|
"mchess_server/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetLobbyFromPassphraseHandler(c *gin.Context) {
|
var mut sync.Mutex
|
||||||
reqPassphrase := api.Passphrase{}
|
|
||||||
|
|
||||||
err := c.ShouldBindJSON(&reqPassphrase)
|
func HostPrivateGameHandler(c *gin.Context) {
|
||||||
if err != nil || reqPassphrase.Value == nil || *reqPassphrase.Value == "" {
|
player := chess.NewPlayer(uuid.New())
|
||||||
c.IndentedJSON(http.StatusNotFound, reqPassphrase)
|
u := usher.GetUsher()
|
||||||
|
|
||||||
|
mut.Lock()
|
||||||
|
defer mut.Unlock()
|
||||||
|
lobby := u.CreateNewPrivateLobby(player)
|
||||||
|
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
||||||
|
|
||||||
|
passphrase := lobby.Passphrase.String()
|
||||||
|
info := api.PlayerInfo{
|
||||||
|
PlayerID: &player.Uuid,
|
||||||
|
LobbyID: &lobby.Uuid,
|
||||||
|
Passphrase: &passphrase,
|
||||||
|
}
|
||||||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||||||
|
c.IndentedJSON(http.StatusOK, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLobbyForPassphraseHandler(c *gin.Context) {
|
||||||
|
reqPassphrase := c.Param("phrase")
|
||||||
|
if reqPassphrase == "" {
|
||||||
|
c.IndentedJSON(http.StatusBadRequest, reqPassphrase)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase(
|
passPhraseWithSpaces := utils.ConvertToPassphraseWithSpaces(reqPassphrase)
|
||||||
utils.NewPassphraseFromString(*reqPassphrase.Value))
|
lobby := lobbies.GetLobbyRegistry().GetLobbyByPassphrase(passPhraseWithSpaces)
|
||||||
|
|
||||||
if lobby == nil {
|
if lobby == nil {
|
||||||
c.IndentedJSON(http.StatusNotFound, reqPassphrase)
|
c.IndentedJSON(http.StatusNotFound, reqPassphrase)
|
||||||
@ -32,3 +56,73 @@ func GetLobbyFromPassphraseHandler(c *gin.Context) {
|
|||||||
|
|
||||||
c.IndentedJSON(http.StatusOK, lobbyInfo)
|
c.IndentedJSON(http.StatusOK, lobbyInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegisterForRandomGame(c *gin.Context) {
|
||||||
|
player := chess.NewPlayer(uuid.New())
|
||||||
|
usher := usher.GetUsher()
|
||||||
|
|
||||||
|
mut.Lock()
|
||||||
|
defer mut.Unlock()
|
||||||
|
lobby := usher.WelcomeNewPlayer(player)
|
||||||
|
usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
||||||
|
|
||||||
|
info := api.PlayerInfo{
|
||||||
|
PlayerID: &player.Uuid,
|
||||||
|
LobbyID: &lobby.Uuid,
|
||||||
|
}
|
||||||
|
log.Println("responding with info ", info)
|
||||||
|
|
||||||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||||||
|
c.IndentedJSON(http.StatusOK, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func JoinPrivateGame(c *gin.Context) {
|
||||||
|
req := api.PlayerInfo{}
|
||||||
|
log.Println(c.Request.Body)
|
||||||
|
err := c.ShouldBindJSON(&req)
|
||||||
|
if err != nil || req.Passphrase == nil || *req.Passphrase == "" {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
u := usher.GetUsher()
|
||||||
|
|
||||||
|
if req.Passphrase != nil &&
|
||||||
|
*req.Passphrase != "" &&
|
||||||
|
req.PlayerID != nil &&
|
||||||
|
req.LobbyID != nil { //is reconnect
|
||||||
|
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
|
||||||
|
_, found := lobby.GetPlayerByUUID(*req.PlayerID)
|
||||||
|
if found {
|
||||||
|
c.IndentedJSON(
|
||||||
|
http.StatusOK,
|
||||||
|
api.PlayerInfo{
|
||||||
|
PlayerID: req.PlayerID,
|
||||||
|
LobbyID: req.LobbyID,
|
||||||
|
Passphrase: req.Passphrase,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player := chess.NewPlayer(uuid.New())
|
||||||
|
|
||||||
|
mut.Lock()
|
||||||
|
defer mut.Unlock()
|
||||||
|
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
|
||||||
|
if lobby != nil {
|
||||||
|
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
||||||
|
} else {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
info := api.PlayerInfo{
|
||||||
|
PlayerID: &player.Uuid,
|
||||||
|
LobbyID: &lobby.Uuid,
|
||||||
|
Passphrase: req.Passphrase,
|
||||||
|
}
|
||||||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||||||
|
c.IndentedJSON(http.StatusOK, info)
|
||||||
|
}
|
||||||
|
57
handler/handler_test.go
Normal file
57
handler/handler_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"mchess_server/api"
|
||||||
|
"mchess_server/utils"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_GetLobbyFromPassphraseHandler(t *testing.T) {
|
||||||
|
var passphraseURLParameter string
|
||||||
|
var hostedLobbyId uuid.UUID
|
||||||
|
|
||||||
|
t.Run("host a lobby", func(t *testing.T) {
|
||||||
|
r1 := httptest.NewRecorder()
|
||||||
|
ctx1, e1 := gin.CreateTestContext(r1)
|
||||||
|
e1.GET("/api/hostPrivate", HostPrivateGameHandler)
|
||||||
|
hostGameRequest, _ := http.NewRequest("GET", "/api/hostPrivate", nil)
|
||||||
|
ctx1.Request = hostGameRequest
|
||||||
|
|
||||||
|
e1.ServeHTTP(r1, hostGameRequest)
|
||||||
|
|
||||||
|
playerInfo := api.PlayerInfo{}
|
||||||
|
err := json.Unmarshal(r1.Body.Bytes(), &playerInfo)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
receivedPhrase := *playerInfo.Passphrase
|
||||||
|
hostedLobbyId = *playerInfo.LobbyID
|
||||||
|
|
||||||
|
passphrase := utils.NewPassphraseFromString(receivedPhrase)
|
||||||
|
passphraseURLParameter = passphrase.AsURLParam()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("see if the lobby can be fetched by using the passphrase", func(t *testing.T) {
|
||||||
|
r2 := httptest.NewRecorder()
|
||||||
|
ctx2, engine := gin.CreateTestContext(r2)
|
||||||
|
engine.GET("/api/getLobbyForPassphrase/:phrase", GetLobbyForPassphraseHandler)
|
||||||
|
|
||||||
|
url := "/api/getLobbyForPassphrase/" + passphraseURLParameter
|
||||||
|
getLobbyRequest, _ := http.NewRequest("GET", url, nil)
|
||||||
|
ctx2.Request = getLobbyRequest
|
||||||
|
|
||||||
|
engine.ServeHTTP(r2, getLobbyRequest)
|
||||||
|
|
||||||
|
lobbyInfo := api.LobbyInfo{}
|
||||||
|
err := json.Unmarshal(r2.Body.Bytes(), &lobbyInfo)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, hostedLobbyId, *lobbyInfo.ID)
|
||||||
|
})
|
||||||
|
}
|
104
main.go
104
main.go
@ -7,22 +7,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"mchess_server/api"
|
"mchess_server/api"
|
||||||
"mchess_server/chess"
|
"mchess_server/handler"
|
||||||
lobbies "mchess_server/lobby_registry"
|
lobbies "mchess_server/lobby_registry"
|
||||||
"mchess_server/usher"
|
|
||||||
"mchess_server/utils"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
|
||||||
"nhooyr.io/websocket"
|
"nhooyr.io/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cert_path = "/etc/letsencrypt/live/chess.sw-gross.de/"
|
var cert_path = "/etc/letsencrypt/live/chess.sw-gross.de/"
|
||||||
var cert_file = cert_path + "fullchain.pem"
|
var cert_file = cert_path + "fullchain.pem"
|
||||||
var key_file = cert_path + "privkey.pem"
|
var key_file = cert_path + "privkey.pem"
|
||||||
var mut sync.Mutex
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var debugMode bool
|
var debugMode bool
|
||||||
@ -35,10 +29,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
router.GET("/api/random", registerForRandomGame)
|
router.GET("/api/random", handler.RegisterForRandomGame)
|
||||||
router.GET("/api/hostPrivate", hostPrivateGame)
|
router.GET("/api/hostPrivate", handler.HostPrivateGameHandler)
|
||||||
router.POST("/api/joinPrivate", joinPrivateGame)
|
router.POST("/api/joinPrivate", handler.JoinPrivateGame)
|
||||||
router.GET("/api/ws", registerWebSocketConnection)
|
router.GET("/api/ws", registerWebSocketConnection)
|
||||||
|
router.GET("/api/getLobbyForPassphrase/:phrase", handler.GetLobbyForPassphraseHandler)
|
||||||
|
|
||||||
if debugMode {
|
if debugMode {
|
||||||
log.Println("Starting service WITHOUT TLS")
|
log.Println("Starting service WITHOUT TLS")
|
||||||
@ -51,95 +46,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerForRandomGame(c *gin.Context) {
|
|
||||||
player := chess.NewPlayer(uuid.New())
|
|
||||||
usher := usher.GetUsher()
|
|
||||||
|
|
||||||
mut.Lock()
|
|
||||||
defer mut.Unlock()
|
|
||||||
lobby := usher.WelcomeNewPlayer(player)
|
|
||||||
usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
|
||||||
|
|
||||||
info := api.PlayerInfo{
|
|
||||||
PlayerID: &player.Uuid,
|
|
||||||
LobbyID: &lobby.Uuid,
|
|
||||||
}
|
|
||||||
log.Println("responding with info ", info)
|
|
||||||
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
c.IndentedJSON(http.StatusOK, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hostPrivateGame(c *gin.Context) {
|
|
||||||
player := chess.NewPlayer(uuid.New())
|
|
||||||
u := usher.GetUsher()
|
|
||||||
|
|
||||||
mut.Lock()
|
|
||||||
defer mut.Unlock()
|
|
||||||
lobby := u.CreateNewPrivateLobby(player)
|
|
||||||
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
|
||||||
|
|
||||||
passphrase := lobby.Passphrase.String()
|
|
||||||
info := api.PlayerInfo{
|
|
||||||
PlayerID: &player.Uuid,
|
|
||||||
LobbyID: &lobby.Uuid,
|
|
||||||
Passphrase: &passphrase,
|
|
||||||
}
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
c.IndentedJSON(http.StatusOK, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func joinPrivateGame(c *gin.Context) {
|
|
||||||
req := api.PlayerInfo{}
|
|
||||||
log.Println(c.Request.Body)
|
|
||||||
err := c.ShouldBindJSON(&req)
|
|
||||||
if err != nil || req.Passphrase == nil || *req.Passphrase == "" {
|
|
||||||
c.IndentedJSON(http.StatusNotFound, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
u := usher.GetUsher()
|
|
||||||
|
|
||||||
if req.Passphrase != nil &&
|
|
||||||
*req.Passphrase != "" &&
|
|
||||||
req.PlayerID != nil &&
|
|
||||||
req.LobbyID != nil { //is reconnect
|
|
||||||
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
|
|
||||||
_, found := lobby.GetPlayerByUUID(*req.PlayerID)
|
|
||||||
if found {
|
|
||||||
c.IndentedJSON(
|
|
||||||
http.StatusOK,
|
|
||||||
api.PlayerInfo{
|
|
||||||
PlayerID: req.PlayerID,
|
|
||||||
LobbyID: req.LobbyID,
|
|
||||||
Passphrase: req.Passphrase,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
c.IndentedJSON(http.StatusNotFound, req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
player := chess.NewPlayer(uuid.New())
|
|
||||||
|
|
||||||
mut.Lock()
|
|
||||||
defer mut.Unlock()
|
|
||||||
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
|
|
||||||
if lobby != nil {
|
|
||||||
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
|
|
||||||
} else {
|
|
||||||
c.IndentedJSON(http.StatusNotFound, req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
info := api.PlayerInfo{
|
|
||||||
PlayerID: &player.Uuid,
|
|
||||||
LobbyID: &lobby.Uuid,
|
|
||||||
Passphrase: req.Passphrase,
|
|
||||||
}
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
c.IndentedJSON(http.StatusOK, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerWebSocketConnection(c *gin.Context) {
|
func registerWebSocketConnection(c *gin.Context) {
|
||||||
webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"chess.sw-gross.de", "localhost:*"}})
|
webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"chess.sw-gross.de", "localhost:*"}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28006,7 +28006,6 @@ var CleanWords = []string{
|
|||||||
"joystick",
|
"joystick",
|
||||||
"joysticks",
|
"joysticks",
|
||||||
"jpeg",
|
"jpeg",
|
||||||
"jpn",
|
|
||||||
"juan",
|
"juan",
|
||||||
"juana",
|
"juana",
|
||||||
"juanita",
|
"juanita",
|
||||||
|
@ -2,6 +2,7 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Passphrase string
|
type Passphrase string
|
||||||
@ -24,6 +25,33 @@ func NewPassphraseFromString(s string) Passphrase {
|
|||||||
return Passphrase(s)
|
return Passphrase(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Passphrase) AsURLParam() string {
|
||||||
|
var result string
|
||||||
|
phraseAsString := p.String()
|
||||||
|
|
||||||
|
segments := strings.Split(phraseAsString, " ")
|
||||||
|
|
||||||
|
for _, segment := range segments {
|
||||||
|
runes := []rune(segment)
|
||||||
|
runes[0] = unicode.ToUpper(runes[0])
|
||||||
|
result += string(runes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertToPassphraseWithSpaces(s string) Passphrase {
|
||||||
|
result := ""
|
||||||
|
for _, rune := range s {
|
||||||
|
if unicode.IsUpper(rune) {
|
||||||
|
result += " "
|
||||||
|
}
|
||||||
|
result += strings.ToLower(string(rune))
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewPassphraseFromString(strings.Trim(result, " "))
|
||||||
|
}
|
||||||
|
|
||||||
func (p Passphrase) String() string {
|
func (p Passphrase) String() string {
|
||||||
return string(p)
|
return string(p)
|
||||||
}
|
}
|
||||||
|
@ -19,3 +19,18 @@ func Test_onlyUniqueWords(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, numberOfCleanWords, len(wordsDistribution))
|
assert.Equal(t, numberOfCleanWords, len(wordsDistribution))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Passphrase_AsURLParam(t *testing.T) {
|
||||||
|
phrase := NewPassphraseFromString("this is a Test phrase")
|
||||||
|
|
||||||
|
asParams := phrase.AsURLParam()
|
||||||
|
|
||||||
|
assert.Equal(t, "ThisIsATestPhrase", asParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Passphrase_ConvertToPassphraseWithSpaces(t *testing.T) {
|
||||||
|
fromURL := "ThisIsATestPhraseWithManyWords"
|
||||||
|
phrase := ConvertToPassphraseWithSpaces(fromURL)
|
||||||
|
|
||||||
|
assert.Equal(t, NewPassphraseFromString("this is a test phrase with many words"), phrase)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user