diff --git a/Enums/WsEventType/WsMessageFrom.go b/Enums/WsEventType/WsMessageFrom.go new file mode 100644 index 0000000..ac7c5ed --- /dev/null +++ b/Enums/WsEventType/WsMessageFrom.go @@ -0,0 +1,11 @@ +package WsEventType + +type WsEventType uint8 + +const ( + Authentication WsEventType = iota + DirectMessage + ConnectionCreated + ConnectionDeleted + ConnectionElevated +) diff --git a/Enums/WsMessageFrom/WsMessageFrom.go b/Enums/WsMessageFrom/WsMessageFrom.go deleted file mode 100644 index 8db0175..0000000 --- a/Enums/WsMessageFrom/WsMessageFrom.go +++ /dev/null @@ -1,9 +0,0 @@ -package WsMessageFrom - -type WsMessageToUserFrom uint8 - -const ( - Server WsMessageToUserFrom = iota - DirectMessage - Group -) diff --git a/go-socket b/go-socket index a5479d0..11959d7 100755 Binary files a/go-socket and b/go-socket differ diff --git a/httpConnectionAndDm.go b/httpConnectionAndDm.go index c2ce932..a368a96 100644 --- a/httpConnectionAndDm.go +++ b/httpConnectionAndDm.go @@ -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,29 +294,53 @@ func HttpHandleUserElevateConnection(response http.ResponseWriter, request *http return } - if conn.RecipientId != user.Id { - http.Error(response, "invalid connectionid", http.StatusBadRequest) - return - } - - switch conn.State { - case ConnectionState.Stranger: - conn.State = ConnectionState.Friend - break - case ConnectionState.GroupFellow: - conn.State = ConnectionState.Stranger - break - default: - http.Error(response, "cannot elevate further", http.StatusBadRequest) - return - } - - err = DbConnectionUpdateState(ctx, conn) - if err != nil { - http.Error(response, "internal server error", http.StatusInternalServerError) - 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 + break + case ConnectionState.GroupFellow: + conn.State = ConnectionState.Stranger + break + default: + http.Error(response, "cannot elevate further", http.StatusBadRequest) + return + } + + err = DbConnectionUpdateState(ctx, conn) + if err != nil { + http.Error(response, "internal server error", http.StatusInternalServerError) + return + } + 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) { diff --git a/httpGroup.go b/httpGroup.go index 46ea877..816263b 100644 --- a/httpGroup.go +++ b/httpGroup.go @@ -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 diff --git a/httpUser.go b/httpUser.go index 3a6296c..2f059e5 100644 --- a/httpUser.go +++ b/httpUser.go @@ -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 } diff --git a/machine-client/index.html b/machine-client/index.html index 0b62d7e..d62ffba 100644 --- a/machine-client/index.html +++ b/machine-client/index.html @@ -73,7 +73,6 @@ - @@ -81,6 +80,7 @@ + @@ -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: [ diff --git a/structs.go b/structs.go index 184eb56..f6aad1c 100644 --- a/structs.go +++ b/structs.go @@ -5,6 +5,7 @@ import ( "time" "go-socket/Enums/ConnectionState" + "go-socket/Enums/WsEventType" "github.com/coder/websocket" "github.com/google/uuid" @@ -24,15 +25,16 @@ type User struct { } type Connection struct { - Mu sync.RWMutex `json:"-"` - Id uuid.UUID `json:"id"` - CreatedAt time.Time `json:"createdAt"` - MessagesBuff [MaxDirectMsgCache]*Message `json:"-"` - NextBuffIdx uint32 `json:"-"` - HaveOverflowed bool `json:"-"` - RequestorId uint32 `json:"requestorId"` - RecipientId uint32 `json:"recipientId"` - State ConnectionState.ConnectionState `json:"state"` + Mu sync.RWMutex `json:"-"` + Id uuid.UUID `json:"id"` + CreatedAt time.Time `json:"createdAt"` + MessagesBuff [MaxDirectMsgCache]*Message `json:"-"` + NextBuffIdx uint32 `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"` } func (conn *Connection) AddMessageToBuff(message *Message) { @@ -62,12 +64,17 @@ 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"` - CreatedAt time.Time `json:"createdAt"` - Sender uint32 `json:"sender"` - Receiver uuid.UUID `json:"receiver"` + Id uuid.UUID `json:"id"` + Content string `json:"content"` + CreatedAt time.Time `json:"createdAt"` + Sender uint32 `json:"sender"` + Receiver uuid.UUID `json:"receiver"` } type Group struct { @@ -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"` +} diff --git a/wsServer.go b/wsServer.go index 62460ba..494aa69 100644 --- a/wsServer.go +++ b/wsServer.go @@ -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 }