code refactor, implementing sockets

This commit is contained in:
slawk0
2025-02-11 16:34:59 +01:00
parent bbae0e8fbb
commit 248966d63f
18 changed files with 595 additions and 122 deletions

View File

@@ -5,7 +5,7 @@ import (
"errors"
"github.com/google/uuid"
_ "github.com/lib/pq"
"relay-server/helpers"
"relay-server/utils"
)
func CheckUserExists(db *sql.DB, username string) (bool, error) {
@@ -14,7 +14,7 @@ func CheckUserExists(db *sql.DB, username string) (bool, error) {
var count int
err := db.QueryRow(query, username).Scan(&count)
if err != nil {
return false, helpers.NewError(helpers.ErrInternal, "Failed to check user existence", err)
return false, utils.NewError(utils.ErrInternal, "Failed to check user existence", err)
}
return count > 0, nil
@@ -30,7 +30,7 @@ func InsertUser(db *sql.DB, username string, passwordHash string) (string, error
var userID string
err := db.QueryRow(query, username, passwordHash).Scan(&userID)
if err != nil {
return "", helpers.NewError(helpers.ErrInternal, "Failed to create user", err)
return "", utils.NewError(utils.ErrInternal, "Failed to create user", err)
}
return userID, nil
@@ -46,9 +46,9 @@ func GetPasswordHash(db *sql.DB, username string) (string, error) {
err := db.QueryRow(query, username).Scan(&passwordHash)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", helpers.NewError(helpers.ErrNotFound, "User not found", nil)
return "", utils.NewError(utils.ErrNotFound, "User not found", nil)
}
return "", helpers.NewError(helpers.ErrInternal, "Failed to get user credentials", err)
return "", utils.NewError(utils.ErrInternal, "Failed to get user credentials", err)
}
return passwordHash, nil
@@ -64,9 +64,9 @@ func GetUserID(db *sql.DB, username string) (uuid.UUID, error) {
err := db.QueryRow(query, username).Scan(&userID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return uuid.Nil, helpers.NewError(helpers.ErrNotFound, "User not found", nil)
return uuid.Nil, utils.NewError(utils.ErrNotFound, "User not found", nil)
}
return uuid.Nil, helpers.NewError(helpers.ErrInternal, "Failed to get user ID", err)
return uuid.Nil, utils.NewError(utils.ErrInternal, "Failed to get user ID", err)
}
return userID, nil
}

View File

@@ -5,8 +5,8 @@ import (
"errors"
"fmt"
"github.com/google/uuid"
"relay-server/helpers"
"relay-server/model"
"relay-server/utils"
"strings"
)
@@ -18,9 +18,9 @@ func DeleteContact(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) error
).Scan(&conversationType)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return helpers.NewError(helpers.ErrNotFound, "no contacts found for this id", fmt.Errorf("no conversation found with id: %s", conversationID))
return utils.NewError(utils.ErrNotFound, "no contacts found for this id", fmt.Errorf("no conversation found with id: %s", conversationID))
}
return helpers.NewError(helpers.ErrInternal, "Failed to check conversation", err)
return utils.NewError(utils.ErrInternal, "Failed to check conversation", err)
}
if conversationType == "group" {
@@ -30,15 +30,15 @@ func DeleteContact(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) error
conversationID, userID,
)
if err != nil {
return helpers.NewError(helpers.ErrInternal, "Failed to delete contact", err)
return utils.NewError(utils.ErrInternal, "Failed to delete contact", err)
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to verify contact deletion: %w", err))
return utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to verify contact deletion: %w", err))
}
if rowsAffected == 0 {
return helpers.NewError(helpers.ErrNotFound, fmt.Sprintf("no matching contact found with conversation id: %s, user id: %s", conversationID, userID), nil)
return utils.NewError(utils.ErrNotFound, fmt.Sprintf("no matching contact found with conversation id: %s, user id: %s", conversationID, userID), nil)
}
// Delete from Memberships
@@ -47,15 +47,15 @@ func DeleteContact(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) error
conversationID, userID,
)
if err != nil {
return helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to delete membership: %w", err))
return utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to delete membership: %w", err))
}
rowsAffected, err = res.RowsAffected()
if err != nil {
return helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to verify membership deletion: %w", err))
return utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to verify membership deletion: %w", err))
}
if rowsAffected == 0 {
return helpers.NewError(helpers.ErrNotFound, "No membership found", err)
return utils.NewError(utils.ErrNotFound, "No membership found", err)
}
} else {
res, err := db.Exec(
@@ -63,15 +63,15 @@ func DeleteContact(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) error
userID, conversationID,
)
if err != nil {
return helpers.NewError(helpers.ErrInternal, "Failed to delete contact", err)
return utils.NewError(utils.ErrInternal, "Failed to delete contact", err)
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to verify contact deletion: %w", err))
return utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to verify contact deletion: %w", err))
}
if rowsAffected == 0 {
return helpers.NewError(helpers.ErrNotFound, fmt.Sprintf("no matching contact found with user id: %s, conversation id: %s", userID, conversationID), nil)
return utils.NewError(utils.ErrNotFound, fmt.Sprintf("no matching contact found with user id: %s, conversation id: %s", userID, conversationID), nil)
}
}
@@ -94,7 +94,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
`, userID).Scan(&conversationID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation: %w", err))
}
if conversationID == uuid.Nil {
@@ -104,7 +104,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
RETURNING conversation_id;
`).Scan(&conversationID)
if err != nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err))
}
_, err = db.Exec(`
@@ -113,7 +113,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
ON CONFLICT (conversation_id, user_id) DO NOTHING;
`, conversationID, userID)
if err != nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create membership: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to create membership: %w", err))
}
}
} else {
@@ -128,7 +128,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
`, userID, contactID).Scan(&conversationID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation %w", err))
}
if conversationID == uuid.Nil {
@@ -138,7 +138,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
RETURNING conversation_id;
`).Scan(&conversationID)
if err != nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err))
}
_, err = db.Exec(`
@@ -147,7 +147,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse
ON CONFLICT (conversation_id, user_id) DO NOTHING;
`, conversationID, userID, contactID)
if err != nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create memberships: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to create memberships: %w", err))
}
}
}
@@ -186,9 +186,9 @@ func InsertContactByID(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) (
`, userID, conversationID).Scan(&contact.ID, &contact.ConversationID, &contact.UserID)
if err == nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInvalidInput, "Contact already exists", nil)
return &model.Contact{}, utils.NewError(utils.ErrInvalidInput, "Contact already exists", nil)
} else if !errors.Is(err, sql.ErrNoRows) {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check contact existence: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to check contact existence: %w", err))
}
// Insert new contact
@@ -199,7 +199,7 @@ func InsertContactByID(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) (
`, userID, conversationID).Scan(&contact.ID, &contact.ConversationID, &contact.UserID)
if err != nil {
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to create contact", err)
return &model.Contact{}, utils.NewError(utils.ErrInternal, "Failed to create contact", err)
}
return &contact, nil
@@ -230,7 +230,7 @@ func GetLatestMessage(db *sql.DB, conversationId uuid.UUID) (*model.Contact, err
if errors.Is(err, sql.ErrNoRows) {
return &model.Contact{}, nil
}
return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to get latest message", fmt.Errorf("failed to get latest message: %w", err))
return &model.Contact{}, utils.NewError(utils.ErrInternal, "Failed to get latest message", fmt.Errorf("failed to get latest message: %w", err))
}
return &latestMessage, nil
@@ -287,7 +287,7 @@ func GetContacts(db *sql.DB, userID uuid.UUID) ([]*model.Contact, error) {
rows, err := db.Query(contactsQuery, userID)
if err != nil {
return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to get contacts", fmt.Errorf("failed to get contacts: %w", err))
return []*model.Contact{}, utils.NewError(utils.ErrInternal, "Failed to get contacts", fmt.Errorf("failed to get contacts: %w", err))
}
defer rows.Close()
@@ -296,7 +296,7 @@ func GetContacts(db *sql.DB, userID uuid.UUID) ([]*model.Contact, error) {
contact := &model.Contact{}
err := rows.Scan(&contact.ID, &contact.UserID, &contact.Username, &contact.LastActive, &contact.ConversationID, &contact.Type, &contact.LastReadMessageID)
if err != nil {
return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact: %w", err))
return []*model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact: %w", err))
}
latestMessage, err := GetLatestMessage(db, contact.ConversationID)
@@ -313,7 +313,7 @@ func GetContacts(db *sql.DB, userID uuid.UUID) ([]*model.Contact, error) {
}
if err = rows.Err(); err != nil {
return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process contacts: %w", err))
return []*model.Contact{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to process contacts: %w", err))
}
return contacts, nil
@@ -329,7 +329,7 @@ func ContactSuggestion(db *sql.DB, contactUsername string) ([]string, error) {
rows, err := db.Query(query, "%"+strings.ToLower(contactUsername)+"%")
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return []string{}, helpers.NewError(helpers.ErrInternal, "Failed to get contact suggestions", fmt.Errorf("failed to get contact suggestions: %w", err))
return []string{}, utils.NewError(utils.ErrInternal, "Failed to get contact suggestions", fmt.Errorf("failed to get contact suggestions: %w", err))
}
defer rows.Close()
@@ -338,12 +338,12 @@ func ContactSuggestion(db *sql.DB, contactUsername string) ([]string, error) {
var suggestion string
err := rows.Scan(&suggestion)
if err != nil {
return []string{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact suggestion: %w", err))
return []string{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact suggestion: %w", err))
}
suggestions = append(suggestions, suggestion)
}
if err = rows.Err(); err != nil {
return []string{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process suggestions: %w", err))
return []string{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to process suggestions: %w", err))
}
return suggestions, nil
}

View File

@@ -4,8 +4,8 @@ import (
"database/sql"
"fmt"
"github.com/google/uuid"
"relay-server/helpers"
"relay-server/model"
"relay-server/utils"
)
func CreateGroup(db *sql.DB, groupName string, userID uuid.UUID) (uuid.UUID, error) {
@@ -25,14 +25,14 @@ func CreateGroup(db *sql.DB, groupName string, userID uuid.UUID) (uuid.UUID, err
var groupID uuid.UUID
err := db.QueryRow(createConversationQuery, groupName).Scan(&groupID)
if err != nil {
return uuid.Nil, helpers.NewError(helpers.ErrInternal, "Failed to create group", fmt.Errorf("failed to create group: %w", err))
return uuid.Nil, utils.NewError(utils.ErrInternal, "Failed to create group", fmt.Errorf("failed to create group: %w", err))
}
// Insert group admin (make user that created the group an admin)
var grantedAt string
err = db.QueryRow(insertGroupAdminQuery, groupID, userID, userID).Scan(&grantedAt)
if err != nil {
return uuid.Nil, helpers.NewError(helpers.ErrInternal, "Failed to create group", fmt.Errorf("failed to insert group admin: %w", err))
return uuid.Nil, utils.NewError(utils.ErrInternal, "Failed to create group", fmt.Errorf("failed to insert group admin: %w", err))
}
// Add self as group member
@@ -44,7 +44,7 @@ func CreateGroup(db *sql.DB, groupName string, userID uuid.UUID) (uuid.UUID, err
// Insert group contact
_, err = InsertContactByID(db, userID, groupID)
if err != nil {
return groupID, helpers.NewError(helpers.ErrInternal, "Failed to create group contact", fmt.Errorf("failed to insert group contact: %w", err))
return groupID, utils.NewError(utils.ErrInternal, "Failed to create group contact", fmt.Errorf("failed to insert group contact: %w", err))
}
return groupID, nil
@@ -60,7 +60,7 @@ func AddMemberToGroup(db *sql.DB, userID uuid.UUID, groupID uuid.UUID) (uuid.UUI
var memberID uuid.UUID
err := db.QueryRow(query, groupID, userID).Scan(&memberID)
if err != nil {
return uuid.Nil, helpers.NewError(helpers.ErrInternal, "Failed to add member to group", fmt.Errorf("failed to add member to group: %w", err))
return uuid.Nil, utils.NewError(utils.ErrInternal, "Failed to add member to group", fmt.Errorf("failed to add member to group: %w", err))
}
return memberID, nil
}
@@ -83,7 +83,7 @@ func GetMembers(db *sql.DB, groupID uuid.UUID) ([]*model.Member, error) {
rows, err := db.Query(query, groupID)
if err != nil {
return []*model.Member{}, helpers.NewError(helpers.ErrInternal, "Failed to get members", fmt.Errorf("failed to get members: %w", err))
return []*model.Member{}, utils.NewError(utils.ErrInternal, "Failed to get members", fmt.Errorf("failed to get members: %w", err))
}
defer rows.Close()
@@ -92,13 +92,13 @@ func GetMembers(db *sql.DB, groupID uuid.UUID) ([]*model.Member, error) {
var member model.Member
err = rows.Scan(&member.UserID, &member.Username, &member.IsAdmin, &member.IsOwner)
if err != nil {
return []*model.Member{}, helpers.NewError(helpers.ErrInternal, "Failed to get members", fmt.Errorf("failed to scan member: %w", err))
return []*model.Member{}, utils.NewError(utils.ErrInternal, "Failed to get members", fmt.Errorf("failed to scan member: %w", err))
}
members = append(members, &member)
}
if err = rows.Err(); err != nil {
return []*model.Member{}, helpers.NewError(helpers.ErrInternal, "Failed to get members", fmt.Errorf("error iterating members: %w", err))
return []*model.Member{}, utils.NewError(utils.ErrInternal, "Failed to get members", fmt.Errorf("error iterating members: %w", err))
}
return members, nil
@@ -113,7 +113,7 @@ func IsAdmin(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) (bool, erro
var count int
err := db.QueryRow(query, userID, conversationID).Scan(&count)
if err != nil {
return false, helpers.NewError(helpers.ErrInternal, "Failed to check admin status", fmt.Errorf("failed to check admin status: %w", err))
return false, utils.NewError(utils.ErrInternal, "Failed to check admin status", fmt.Errorf("failed to check admin status: %w", err))
}
return count > 0, nil
}
@@ -127,7 +127,83 @@ func IsMember(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) (bool, err
var count int
err := db.QueryRow(query, userID, conversationID).Scan(&count)
if err != nil {
return false, helpers.NewError(helpers.ErrInternal, "Failed to check membership", fmt.Errorf("failed to check membership: %w", err))
return false, utils.NewError(utils.ErrInternal, "Failed to check membership", fmt.Errorf("failed to check membership: %w", err))
}
return count > 0, nil
}
func GetUserConversations(db *sql.DB, userID string) ([]string, error) {
query := `
SELECT DISTINCT m.conversation_id
FROM Memberships m
JOIN Conversations c ON m.conversation_id = c.conversation_id
WHERE m.user_id = $1
AND c.conversation_type = 'group';
`
var conversations []string
rows, err := db.Query(query, userID)
if err != nil {
return []string{}, fmt.Errorf("failed to get user conversations: %w", err)
}
defer rows.Close()
for rows.Next() {
var conversationID string
err = rows.Scan(&conversationID)
if err != nil {
return []string{}, fmt.Errorf("failed to scan conversation: %w", err)
}
conversations = append(conversations, conversationID)
}
if err := rows.Err(); err != nil {
return []string{}, fmt.Errorf("error iterating conversations: %w", err)
}
return conversations, nil
}
func RemoveUserFromGroup(db *sql.DB, userID uuid.UUID, groupID uuid.UUID) (string, error) {
removeUserFromGroupQuery := `
DELETE FROM Memberships
WHERE conversation_id = $1 AND user_id = $2;
`
isOwner, err := IsGroupOwner(db, userID, groupID)
if err != nil {
return "Failed to remove user from group", fmt.Errorf("failed to check if user is group owner: %w", err)
}
if !isOwner {
return "Cannot remove group owner", nil
}
res, err := db.Exec(removeUserFromGroupQuery, groupID, userID)
if err != nil {
return "Failed to remove user from group", fmt.Errorf("failed to remove user from group: %w", err)
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return "Failed to remove user from group", fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return "User is not a member of the group", nil
}
return "Successfully removed user from group", nil
}
func IsGroupOwner(db *sql.DB, userID uuid.UUID, groupID uuid.UUID) (bool, error) {
query := `
SELECT EXISTS (
SELECT 1 FROM GroupAdmins
WHERE conversation_id = $1
AND user_id = $2
AND is_owner = true
) AS is_owner;
`
var isOwner bool
err := db.QueryRow(query, groupID, userID).Scan(&isOwner)
if err != nil {
return false, fmt.Errorf("failed to check if user is group owner: %w", err)
}
return isOwner, nil
}

View File

@@ -4,8 +4,8 @@ import (
"database/sql"
"fmt"
"github.com/google/uuid"
"relay-server/helpers"
"relay-server/model"
"relay-server/utils"
)
func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit int, cursor int) ([]*model.Message, error) {
@@ -33,20 +33,20 @@ func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit i
`
rows, err := db.Query(query, conversationID, cursor, limit)
if err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err))
}
defer rows.Close()
for rows.Next() {
message := &model.Message{}
err = rows.Scan(&message.MessageID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender)
err = rows.Scan(&message.ID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender)
if err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err))
}
messages = append(messages, message)
}
if err = rows.Err(); err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err))
}
} else {
@@ -65,20 +65,20 @@ func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit i
`
rows, err := db.Query(query, conversationID, cursor, limit)
if err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err))
}
defer rows.Close()
for rows.Next() {
message := &model.Message{}
err = rows.Scan(&message.MessageID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender)
err = rows.Scan(&message.ID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender)
if err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err))
}
messages = append(messages, message)
}
if err = rows.Err(); err != nil {
return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err))
return []*model.Message{}, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err))
}
}
if cursor != 0 {
@@ -102,10 +102,10 @@ func checkMembership(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) (bo
var isMember bool
err := db.QueryRow(query, userID, conversationID).Scan(&isMember)
if err != nil {
return false, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check membership: %w", err))
return false, utils.NewError(utils.ErrInternal, "internal server error", fmt.Errorf("failed to check membership: %w", err))
}
if !isMember {
return false, helpers.NewError(helpers.ErrForbidden, "You are member of the conversation", nil)
return false, utils.NewError(utils.ErrForbidden, "You are member of the conversation", nil)
}
return isMember, nil
}
@@ -121,7 +121,7 @@ func DeleteMessage(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, messa
var messageOwnerID uuid.UUID
err := db.QueryRow(checkMessageOwnershipQuery, messageID).Scan(&messageOwnerID)
if err != nil {
return helpers.NewError(helpers.ErrInternal, "Failed to delete message", fmt.Errorf("failed to check message ownership: %w", err))
return utils.NewError(utils.ErrInternal, "Failed to delete message", fmt.Errorf("failed to check message ownership: %w", err))
}
var isSelfMessage bool
@@ -134,20 +134,51 @@ func DeleteMessage(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, messa
return err
}
if !isSelfMessage && !isAdmin {
return helpers.NewError(helpers.ErrForbidden, "You don't have permissions to delete that message ", nil)
return utils.NewError(utils.ErrForbidden, "You don't have permissions to delete that message ", nil)
}
row, err := db.Exec(deleteMessageQuery, messageID)
if err != nil {
return helpers.NewError(helpers.ErrInternal, "Failed to delete message", fmt.Errorf("failed to delete message: %w", err))
return utils.NewError(utils.ErrInternal, "Failed to delete message", fmt.Errorf("failed to delete message: %w", err))
}
rowsAffected, err := row.RowsAffected()
if err != nil {
return helpers.NewError(helpers.ErrInternal, "Failed to delete message", fmt.Errorf("failed to get rows affected: %w", err))
return utils.NewError(utils.ErrInternal, "Failed to delete message", fmt.Errorf("failed to get rows affected: %w", err))
}
if rowsAffected == 0 {
return helpers.NewError(helpers.ErrNotFound, "Message not found", nil)
return utils.NewError(utils.ErrNotFound, "Message not found", nil)
}
return nil
}
func InsertMessage(db *sql.DB, senderID uuid.UUID, conversationID uuid.UUID, message string, attachmentUrls []string) (*model.Message, error) {
isMember, err := checkMembership(db, senderID, conversationID)
if err != nil {
return &model.Message{}, fmt.Errorf("failed to check membership: %w", err)
}
if !isMember {
return &model.Message{}, fmt.Errorf("user is not a member of the conversation")
}
query := `
INSERT INTO Messages (conversation_id, user_id, content, attachment_urls)
VALUES ($1, $2, $3, $4)
RETURNING message_id, content AS message, sent_at, attachment_urls, user_id AS sender_id, conversation_id;
`
var msg model.Message
err = db.QueryRow(query, conversationID, senderID, message, attachmentUrls).Scan(
&msg.ID,
&msg.Message,
&msg.SentAt,
&msg.AttachmentUrl,
&msg.SenderID,
&msg.ConversationID,
)
if err != nil {
return &model.Message{}, fmt.Errorf("failed to insert message: %w", err)
}
return &msg, nil
}