Repository navigation
Secured Rooms
There will be rooms which you wish to be protected or where only authorized users are welcomed this section will give you example how to do it.
Mesh Global room is where clients default join . Its also the place from where client will join a particular room either directly as implemented below or indirectly from UI like wordsbattle .
Client via websocket can check if the token is correct or whatever roles you need a client has to have to join a room successfully . You can push the client roles directly into header as given in the 2nd code snippet app.Handle .
The below function will help you to get ClientAuthMetadata later on . Either through events of mesh-global room for direct room join below sample or triggered message in mesh-global to join a particular room like here you can get the client who want to join what is the authmetadata and verify if it can join .
type Updates struct {
Slug string
Roles []string
Message chan []string
}
// HandleRoomData implements simplysocket.RoomData.
func (r *Updates) HandleRoomData(room simplysocket.Room, server simplysocket.MeshServer) {
roomname := room.GetRoomSlugInfo()
r.Slug = roomname
log.Println("Handeling data Server for ", roomname, server.GetGameName())
r.PushETLUpdateMessages(room, server)
r.HandleRoomEvents(room, server)
for {
select {
case message, ok := <-room.ConsumeRoomMessage():
if !ok {
log.Println("Channel closed. Exiting HandleRoomData for", roomname)
}
if message.Target == roomname {
switch message.Action {
case "send-message":
message.IsTargetClient = false
room.BroadcastMessage(message)
}
}
case <-room.RoomStopped():
log.Println("Room is stopped so stop the handler")
return
}
}
}
func (r *Updates) HandleRoomEvents(room simplysocket.Room, server simplysocket.MeshServer) {
go func() {
for {
select {
case clientevent := <-room.EventTriggers():
if room.GetRoomSlugInfo() == "mesh-global" && clientevent[0] == "client-joined-room" {
canJoinRoom := matchStringLists([]string{"loggedIn", "notify"}, server.GetClientAuthMetadata(clientevent[2]))
if clientevent[1] == r.Slug {
message := &simplysocket.Message{
Action: "client-count",
Target: room.GetRoomSlugInfo(),
MessageBody: map[string]interface{}{
"message": strconv.Itoa(len(server.GetClientsInRoom()[r.Slug])),
},
Sender: "etl",
IsTargetClient: false,
}
room.BroadcastMessage(message)
}
if !canJoinRoom {
message := &simplysocket.Message{
Action: "updates-message",
Target: clientevent[2],
MessageBody: map[string]interface{}{
"message": []string{"API key is not correct so cannot notify", "fail"},
},
Sender: "etl",
IsTargetClient: true,
}
log.Println("NOT AUTHENTICATED")
room.BroadcastMessage(message)
} else {
server.JoinClientRoom("room-updates", clientevent[2], &Updates{
Message: r.Message,
Roles: []string{"loggedIn", "notify"},
Slug: "room-updates",
})
message := &simplysocket.Message{
Action: "updates-message",
Target: clientevent[2],
MessageBody: map[string]interface{}{
"message": []string{"Authenticated can notify", "info"},
},
Sender: "etl",
IsTargetClient: true,
}
log.Println("AUTHENTICATED")
room.BroadcastMessage(message)
}
}
case <-room.RoomStopped():
log.Println("Room is stopped so stop the handler events")
return
}
}
}()
}
client side :-
You need to add header Role which takes comma seperated strings and later you can use it for room security . This is what server.GetAuthMetadata will return list of strings.
app.Handle("GET", "/etl-data", func(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
key := r.URL.Query().Get("token")
if strings.Compare(key, apiKey) != 0 {
log.Println("is not authenticated", apiKey, key)
simplysocket.ServeWs(ms, w, r)
return nil
} else {
//must have Role , seperated
log.Println("is authenticated")
r.Header.Set("Role", "loggedIn,notify")
simplysocket.ServeWs(ms, w, r)
return nil
}
})
mesh-global is a global room which is provided where all the clients and rooms are present .
You can use server.GetClientAuthMetadata(clientslug string) where you can get the clientslug from events in mesh-global room .
The Room Data which is your custom struct will hold the Roles you want and can be matched .
This way you can match the authmetadata which you send through client side and then match it based on your custom room data .