rework ws responses to user, send events to user via ws
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package WsEventType
|
||||
|
||||
type WsEventType uint8
|
||||
|
||||
const (
|
||||
Authentication WsEventType = iota
|
||||
DirectMessage
|
||||
ConnectionCreated
|
||||
ConnectionDeleted
|
||||
ConnectionElevated
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
package WsMessageFrom
|
||||
|
||||
type WsMessageToUserFrom uint8
|
||||
|
||||
const (
|
||||
Server WsMessageToUserFrom = iota
|
||||
DirectMessage
|
||||
Group
|
||||
)
|
||||
+43
-6
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"go-socket/Enums/ConnectionState"
|
||||
"go-socket/Enums/WsEventType"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -64,7 +65,10 @@ func HttpHandleDm(response http.ResponseWriter, request *http.Request) {
|
||||
Receiver: conn.Id,
|
||||
}
|
||||
|
||||
WsMessageSendToUser(target, message)
|
||||
WsSendMessageCloseIfTimeout(target, WsEventMessage{
|
||||
Type: WsEventType.DirectMessage,
|
||||
Event: message,
|
||||
})
|
||||
|
||||
err = DbMessageSave(ctx, message)
|
||||
if err != nil {
|
||||
@@ -201,6 +205,11 @@ func HttpHandleUserNewConnection(response http.ResponseWriter, request *http.Req
|
||||
}
|
||||
CacheAddConnection(requestor, recipient, connection)
|
||||
|
||||
WsSendMessageCloseIfTimeout(recipient, WsEventMessage{
|
||||
Type: WsEventType.ConnectionCreated,
|
||||
Event: connection,
|
||||
})
|
||||
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
return
|
||||
}
|
||||
@@ -256,6 +265,10 @@ func HttpHandleUserDeleteConnection(response http.ResponseWriter, request *http.
|
||||
}
|
||||
|
||||
CacheDeleteConnection(user, user2, connectionId)
|
||||
WsSendMessageCloseIfTimeout(user2, WsEventMessage{
|
||||
Type: WsEventType.ConnectionDeleted,
|
||||
Event: connectionId,
|
||||
})
|
||||
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
@@ -281,11 +294,10 @@ func HttpHandleUserElevateConnection(response http.ResponseWriter, request *http
|
||||
return
|
||||
}
|
||||
|
||||
if conn.RecipientId != user.Id {
|
||||
http.Error(response, "invalid connectionid", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
|
||||
// TODO change to != "" after user id via uuid
|
||||
if conn.UserWantingToElevate != 0 && conn.UserWantingToElevate != user.Id {
|
||||
switch conn.State {
|
||||
case ConnectionState.Stranger:
|
||||
conn.State = ConnectionState.Friend
|
||||
@@ -303,7 +315,32 @@ func HttpHandleUserElevateConnection(response http.ResponseWriter, request *http
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write([]byte("elevated"))
|
||||
|
||||
var user2 *User
|
||||
if conn.RequestorId == user.Id {
|
||||
user2, err = GetUserById(ctx, conn.RecipientId)
|
||||
} else {
|
||||
user2, err = GetUserById(ctx, conn.RequestorId)
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
WsSendMessageCloseIfTimeout(user2, WsEventMessage{
|
||||
Type: WsEventType.ConnectionElevated,
|
||||
Event: ConnectionElevationData{
|
||||
Id: connectionId,
|
||||
NewState: conn.State,
|
||||
},
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
conn.UserWantingToElevate = user.Id
|
||||
response.Write([]byte("waiting for second user to elevate"))
|
||||
}
|
||||
|
||||
func HttpHandleUserGetConnections(response http.ResponseWriter, request *http.Request) {
|
||||
|
||||
+1
-1
@@ -338,7 +338,7 @@ func HttpHandleGroupMessage(response http.ResponseWriter, request *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
err = WsSendToGroup(group, user, content)
|
||||
err = WsSendToGroupAsUser(group, user, content)
|
||||
if err != nil {
|
||||
http.Error(response, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
|
||||
+2
-2
@@ -53,13 +53,13 @@ func HttpHandleUserNewToken(response http.ResponseWriter, request *http.Request)
|
||||
|
||||
token, err := TokenCreate(user.Id)
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error2", http.StatusInternalServerError)
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json, err := json2.Marshal(LoginReturn{Token: token, UserId: user.Id})
|
||||
if err != nil {
|
||||
http.Error(response, "internal server error3", http.StatusInternalServerError)
|
||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
<button onclick="showForm('mod-user-appearance')">POST /mod/user/appearence</button>
|
||||
<button onclick="showForm('mod-user-about')">POST /mod/user/about</button>
|
||||
<button onclick="showForm('accept-connection')">POST /mod/connection/accept</button>
|
||||
<button onclick="showForm('delete-connection')" class="warn">POST /mod/connection/delete</button>
|
||||
<button onclick="showForm('add-users')">POST /mod/group/addusers</button>
|
||||
<button onclick="showForm('remove-users')">POST /mod/group/removeusers</button>
|
||||
<button onclick="showForm('group-color')">POST /mod/group/color</button>
|
||||
@@ -81,6 +80,7 @@
|
||||
<button onclick="showForm('get-groups')">POST /get/groups</button>
|
||||
<button onclick="showForm('get-connections')">POST /get/connections</button>
|
||||
<button onclick="showForm('get-members')">POST /get/group/members</button>
|
||||
<button onclick="showForm('del-user')" class="warn">POST /del/user</button>
|
||||
<button onclick="showForm('del-group')" class="warn">POST /del/group</button>
|
||||
<button onclick="showForm('del-connection')" class="warn">POST /del/connection</button>
|
||||
<button onclick="showForm('get-connection-messages')">POST /get/connection/messages</button>
|
||||
@@ -164,14 +164,6 @@
|
||||
],
|
||||
submit: () => httpPost('/mod/connection/accept', { token:'ca-token', connectionid:'ca-connectionid' })
|
||||
},
|
||||
'delete-connection': {
|
||||
title: 'POST /mod/connection/delete — delete connection',
|
||||
fields: [
|
||||
{ id: 'cd-token', label: 'token', ph: '' },
|
||||
{ id: 'cd-connectionid', label: 'connectionid', ph: 'UUID' },
|
||||
],
|
||||
submit: () => httpPost('/mod/connection/delete', { token:'cd-token', connectionid:'cd-connectionid' })
|
||||
},
|
||||
'add-users': {
|
||||
title: 'POST /mod/group/addusers — add users (owner only)',
|
||||
fields: [
|
||||
@@ -230,6 +222,13 @@
|
||||
],
|
||||
submit: () => httpPost('/get/group/members', { token:'gm-token', group:'gm-group' })
|
||||
},
|
||||
'del-user': {
|
||||
title: 'POST /del/user — delete own account',
|
||||
fields: [
|
||||
{ id: 'du-token', label: 'token', ph: '' },
|
||||
],
|
||||
submit: () => httpPost('/del/user', { token:'du-token' })
|
||||
},
|
||||
'del-group': {
|
||||
title: 'POST /del/group — delete group (owner only)',
|
||||
fields: [
|
||||
|
||||
+18
-1
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"go-socket/Enums/ConnectionState"
|
||||
"go-socket/Enums/WsEventType"
|
||||
|
||||
"github.com/coder/websocket"
|
||||
"github.com/google/uuid"
|
||||
@@ -29,9 +30,10 @@ type Connection struct {
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
MessagesBuff [MaxDirectMsgCache]*Message `json:"-"`
|
||||
NextBuffIdx uint32 `json:"-"`
|
||||
HaveOverflowed bool `json:"-"`
|
||||
RequestorId uint32 `json:"requestorId"`
|
||||
RecipientId uint32 `json:"recipientId"`
|
||||
UserWantingToElevate uint32 `json:"userWantingToElevate"` // TODO add to database
|
||||
HaveOverflowed bool `json:"-"`
|
||||
State ConnectionState.ConnectionState `json:"state"`
|
||||
}
|
||||
|
||||
@@ -62,6 +64,11 @@ func (conn *Connection) GetSortedMessagesBuff() (*[MaxDirectMsgCache]*Message, u
|
||||
return sorted, MaxDirectMsgCache
|
||||
}
|
||||
|
||||
type ConnectionElevationData struct {
|
||||
Id uuid.UUID `json:"id"`
|
||||
NewState ConnectionState.ConnectionState `json:"newState"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Id uuid.UUID `json:"id"`
|
||||
Content string `json:"content"`
|
||||
@@ -85,3 +92,13 @@ type LoginReturn struct {
|
||||
Token string `json:"token"`
|
||||
UserId uint32 `json:"userId"`
|
||||
}
|
||||
|
||||
type WsEventMessage struct {
|
||||
Type WsEventType.WsEventType `json:"type"`
|
||||
Event any `json:"event"`
|
||||
}
|
||||
|
||||
type WsAuthMessage struct {
|
||||
Success bool `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
+36
-45
@@ -7,7 +7,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go-socket/Enums/WsMessageFrom"
|
||||
"go-socket/Enums/WsEventType"
|
||||
|
||||
"github.com/coder/websocket"
|
||||
"github.com/coder/websocket/wsjson"
|
||||
@@ -54,21 +54,7 @@ func ServeWsConnection(responseWriter http.ResponseWriter, request *http.Request
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessageStructCloseIfTimeout(user *User, message *Message) {
|
||||
if user.WsConn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err := wsjson.Write(ctx, user.WsConn, message)
|
||||
if err != nil {
|
||||
log.Printf("json write error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessageCloseIfTimeout(user *User, message *map[string]any) {
|
||||
func WsSendMessageCloseIfTimeout(user *User, message any) {
|
||||
if user.WsConn == nil {
|
||||
return
|
||||
}
|
||||
@@ -94,65 +80,64 @@ func sendToAllMessageCloseIfTimeout(message *map[string]any) {
|
||||
mu.RUnlock()
|
||||
|
||||
for _, user := range users {
|
||||
sendMessageCloseIfTimeout(user, message)
|
||||
WsSendMessageCloseIfTimeout(user, message)
|
||||
}
|
||||
}
|
||||
|
||||
func WsMessageSendToUser(to *User, message *Message) {
|
||||
sendMessageStructCloseIfTimeout(to, message)
|
||||
}
|
||||
|
||||
func WsSendToGroup(group *Group, sender *User, message string) error {
|
||||
func WsSendToGroupAsUser(group *Group, sender *User, message string) error {
|
||||
for groupUserId := range group.Users {
|
||||
groupUser, err := CacheGetUserById(groupUserId)
|
||||
if err != nil || groupUser.Id == sender.Id {
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO update on groups rework
|
||||
var msg = map[string]any{
|
||||
"type": WsMessageFrom.Group,
|
||||
// "type": WsEventType.Group,
|
||||
"from": group.Id,
|
||||
"sender": sender.Id,
|
||||
"content": message,
|
||||
}
|
||||
sendMessageCloseIfTimeout(groupUser, &msg)
|
||||
WsSendMessageCloseIfTimeout(groupUser, &msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAuthenticatedMessage(user *User, userMessage *map[string]any) bool {
|
||||
sendMessageCloseIfTimeout(user, userMessage)
|
||||
WsSendMessageCloseIfTimeout(user, userMessage)
|
||||
return true
|
||||
}
|
||||
|
||||
func handleUnauthenticatedMessage(ctx context.Context, user *User, userMessage *map[string]any) bool {
|
||||
token, ok := (*userMessage)["token"].(string)
|
||||
response := WsEventMessage{Type: WsEventType.Authentication}
|
||||
|
||||
if !ok {
|
||||
var msg = map[string]any{
|
||||
"type": WsMessageFrom.Server,
|
||||
"error": "no token in message",
|
||||
response.Event = WsAuthMessage{
|
||||
Success: false,
|
||||
Error: "no token in message",
|
||||
}
|
||||
sendMessageCloseIfTimeout(user, &msg)
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return false
|
||||
}
|
||||
|
||||
userId, err := TokenValidateGetId(token)
|
||||
if err != nil {
|
||||
var msg = map[string]any{
|
||||
"type": WsMessageFrom.Server,
|
||||
"error": "invalid token",
|
||||
response.Event = WsAuthMessage{
|
||||
Success: false,
|
||||
Error: "invalid token",
|
||||
}
|
||||
sendMessageCloseIfTimeout(user, &msg)
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return false
|
||||
}
|
||||
|
||||
userFromCache, err := CacheGetUserById(userId)
|
||||
if err != nil {
|
||||
var msg = map[string]any{
|
||||
"type": WsMessageFrom.Server,
|
||||
"error": "user not found",
|
||||
response.Event = WsAuthMessage{
|
||||
Success: false,
|
||||
Error: "user not found",
|
||||
}
|
||||
sendMessageCloseIfTimeout(user, &msg)
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -166,25 +151,31 @@ func handleUnauthenticatedMessage(ctx context.Context, user *User, userMessage *
|
||||
|
||||
err = DbGroupGetById(ctx, dbGroup)
|
||||
if err != nil {
|
||||
var msg = map[string]any{
|
||||
"type": "server",
|
||||
"error": "invalid user data",
|
||||
response.Event = WsAuthMessage{
|
||||
Success: false,
|
||||
Error: "invalid user data",
|
||||
}
|
||||
sendMessageCloseIfTimeout(user, &msg)
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return false
|
||||
}
|
||||
err = DbGroupGetMembers(ctx, dbGroup)
|
||||
if err != nil {
|
||||
var msg = map[string]any{
|
||||
"type": "server",
|
||||
"error": "invalid user data",
|
||||
response.Event = WsAuthMessage{
|
||||
Success: false,
|
||||
Error: "invalid user data",
|
||||
}
|
||||
sendMessageCloseIfTimeout(user, &msg)
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return false
|
||||
}
|
||||
CacheSaveGroup(dbGroup)
|
||||
}
|
||||
}
|
||||
|
||||
response.Event = WsAuthMessage{
|
||||
Success: true,
|
||||
Error: "",
|
||||
}
|
||||
WsSendMessageCloseIfTimeout(user, response)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user