code refactor, implementing sockets
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user