summaryrefslogtreecommitdiff
path: root/internal/server
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2025-01-10 20:13:31 +0200
committerKyren223 <Kyren223@proton.me>2025-01-10 20:13:31 +0200
commit2285afec9944f06b03baa345435e647161d2a438 (patch)
tree21444a7191f68ca40289195574ef3f28cf2da4fd /internal/server
parent3f2236077adcf2450733fb658bb59ac440d14682 (diff)
Implemented message propagation for real-time live chat
Diffstat (limited to 'internal/server')
-rw-r--r--internal/server/api/api.go123
1 files changed, 83 insertions, 40 deletions
diff --git a/internal/server/api/api.go b/internal/server/api/api.go
index 0cd75d5..ef04347 100644
--- a/internal/server/api/api.go
+++ b/internal/server/api/api.go
@@ -12,6 +12,7 @@ import (
"github.com/kyren223/eko/internal/data"
"github.com/kyren223/eko/internal/packet"
"github.com/kyren223/eko/internal/server/session"
+ "github.com/kyren223/eko/pkg/assert"
"github.com/kyren223/eko/pkg/snowflake"
)
@@ -25,64 +26,106 @@ func SendMessage(ctx context.Context, sess *session.Session, request *packet.Sen
return &packet.Error{Error: "either receiver id or frequency id must exist"}
}
+ if len(request.Content) > packet.MaxMessageBytes {
+ return &packet.Error{Error: fmt.Sprintf(
+ "message conent must not exceed %v bytes",
+ packet.MaxMessageBytes,
+ )}
+ }
+
content := strings.TrimSpace(request.Content)
if content == "" {
return &packet.Error{Error: "message content must not be blank"}
}
queries := data.New(db)
- message, err := queries.CreateMessage(ctx, data.CreateMessageParams{
- ID: sess.Manager().Node().Generate(),
- SenderID: sess.ID(),
- Content: content,
- FrequencyID: request.FrequencyID,
- ReceiverID: request.ReceiverID,
- })
- if err != nil {
- log.Println(sess.Addr(), "database error:", err, "in SendMessage")
- return &ErrInternalError
+
+ if request.FrequencyID != nil {
+ frequency, err := queries.GetFrequencyById(ctx, *request.FrequencyID)
+ if err == sql.ErrNoRows {
+ return &packet.Error{Error: "frequency doesn't exist"}
+ }
+ if err != nil {
+ log.Println("database error 0:", err)
+ return &ErrInternalError
+ }
+
+ isAdmin, err := IsNetworkAdmin(ctx, queries, sess.ID(), frequency.NetworkID)
+ if err != nil {
+ log.Println("database error 1:", err)
+ return &ErrInternalError
+ }
+
+ if frequency.Perms != packet.PermReadWrite && !isAdmin {
+ return &ErrPermissionDenied
+ }
+
+ message, err := queries.CreateMessage(ctx, data.CreateMessageParams{
+ ID: sess.Manager().Node().Generate(),
+ SenderID: sess.ID(),
+ Content: content,
+ FrequencyID: request.FrequencyID,
+ ReceiverID: request.ReceiverID,
+ })
+ if err != nil {
+ log.Println(sess.Addr(), "database error:", err, "in SendMessage")
+ return &ErrInternalError
+ }
+
+ return NetworkPropagate(ctx, sess, frequency.NetworkID, &packet.MessagesInfo{
+ Messages: []data.Message{message},
+ RemovedMessages: nil,
+ })
}
- return &packet.MessagesInfo{
- Messages: []data.Message{message},
- RemovedMessages: nil,
+ if request.ReceiverID != nil {
+ return &packet.Error{Error: "receiver messages not supported yet!"}
}
+
+ assert.Never("already checked in the first line for the case where both are nil")
+ return nil
}
func RequestMessages(ctx context.Context, sess *session.Session, request *packet.RequestMessages) packet.Payload {
queries := data.New(db)
- var messages []data.Message
- var err error
if request.FrequencyID != nil && request.ReceiverID == nil {
- messages, err = queries.GetFrequencyMessages(ctx, request.FrequencyID)
- } else if request.ReceiverID != nil && request.FrequencyID == nil {
- messages, err = queries.GetDirectMessages(ctx, data.GetDirectMessagesParams{
- User1: sess.ID(),
- User2: request.ReceiverID,
- })
- } else {
- return &packet.Error{Error: "either receiver id or frequency id must be specified"}
- }
+ frequency, err := queries.GetFrequencyById(ctx, *request.FrequencyID)
+ if err == sql.ErrNoRows {
+ return &packet.Error{Error: "frequency doesn't exist"}
+ }
+ if err != nil {
+ log.Println("database error 0:", err)
+ return &ErrInternalError
+ }
- if err != nil {
- log.Println("database error when retrieving messages:", err)
- return &packet.Error{Error: "internal server error"}
- }
+ isAdmin, err := IsNetworkAdmin(ctx, queries, sess.ID(), frequency.NetworkID)
+ if err != nil {
+ log.Println("database error 1:", err)
+ return &ErrInternalError
+ }
- // TODO:
- // FIXME: If an attacker knows the frequency ID of a private frequency
- // Such in a case where they used to have access to it but no longer do
- // Then it's possible to view all messages including current ones
- // Add a check to make sure the user is inside the network of this
- // Frequency, and even if it is, if the frequency is "no access" then
- // an admin-check needs to happen, and if he's not an admin it needs to be
- // denied
+ if frequency.Perms == packet.PermNoAccess && !isAdmin {
+ return &ErrPermissionDenied
+ }
- return &packet.MessagesInfo{
- Messages: messages,
- RemovedMessages: nil,
+ messages, err := queries.GetFrequencyMessages(ctx, request.FrequencyID)
+ if err != nil {
+ log.Println("database error 0:", err)
+ return &ErrInternalError
+ }
+
+ return &packet.MessagesInfo{
+ Messages: messages,
+ RemovedMessages: nil,
+ }
}
+
+ if request.ReceiverID != nil && request.FrequencyID == nil {
+ return &packet.Error{Error: "receiver message requests are not implemented yet!"}
+ }
+
+ return &packet.Error{Error: "either receiver id or frequency id must be specified"}
}
func CreateOrGetUser(ctx context.Context, node *snowflake.Node, pubKey ed25519.PublicKey) (data.User, error) {
@@ -257,7 +300,7 @@ func CreateFrequency(ctx context.Context, sess *session.Session, request *packet
if len(request.Name) > packet.MaxFrequencyName {
return &packet.Error{Error: fmt.Sprintf(
- "exceeded allowed frequency name length in bytes: %v",
+ "exceeded allowed frequency name length, max %v bytes",
packet.MaxFrequencyName,
)}
}