170 lines
4.1 KiB
Go
170 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
type clearChatRequest struct {
|
|
Scope string `json:"scope"`
|
|
}
|
|
|
|
func (s *Server) handleClearChat(w http.ResponseWriter, r *http.Request) {
|
|
user, ok := userFromContext(r.Context())
|
|
if !ok {
|
|
writeError(w, http.StatusUnauthorized, "Unauthorized")
|
|
return
|
|
}
|
|
|
|
conversationID := strings.TrimSpace(r.PathValue("id"))
|
|
if !s.canAccessConversation(r.Context(), conversationID, user.ID) {
|
|
writeError(w, http.StatusForbidden, "Kein Zugriff auf diesen Chat")
|
|
return
|
|
}
|
|
if !s.isConversationMember(r.Context(), conversationID, user.ID) {
|
|
writeError(w, http.StatusForbidden, "Nur Mitglieder können diesen Chat leeren")
|
|
return
|
|
}
|
|
|
|
var input clearChatRequest
|
|
if err := readJSON(r, &input); err != nil {
|
|
writeError(w, http.StatusBadRequest, "Ungültige Anfrage")
|
|
return
|
|
}
|
|
|
|
scope := strings.TrimSpace(input.Scope)
|
|
if scope != "me" && scope != "all" {
|
|
writeError(w, http.StatusBadRequest, "Ungültiger Löschumfang")
|
|
return
|
|
}
|
|
|
|
var conversationType, ownerID, teamID string
|
|
err := s.db.QueryRow(
|
|
r.Context(),
|
|
`
|
|
SELECT type, COALESCE(created_by::TEXT, ''), COALESCE(team_id::TEXT, '')
|
|
FROM conversations
|
|
WHERE id = $1
|
|
`,
|
|
conversationID,
|
|
).Scan(&conversationType, &ownerID, &teamID)
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
writeError(w, http.StatusNotFound, "Chat wurde nicht gefunden")
|
|
return
|
|
}
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden")
|
|
return
|
|
}
|
|
|
|
if scope == "all" {
|
|
switch conversationType {
|
|
case "direct":
|
|
case "group":
|
|
if teamID != "" {
|
|
if !canManageTeamGroup(user) {
|
|
writeError(w, http.StatusForbidden, "Keine Berechtigung zum Leeren dieses Team-Gruppenchats")
|
|
return
|
|
}
|
|
} else if !canManageGroup(user, ownerID) {
|
|
writeError(w, http.StatusForbidden, "Nur der Ersteller oder ein Administrator darf die Gruppe für alle leeren")
|
|
return
|
|
}
|
|
default:
|
|
writeError(w, http.StatusBadRequest, "Dieser Chat kann nicht für alle geleert werden")
|
|
return
|
|
}
|
|
}
|
|
|
|
if scope == "me" {
|
|
if _, err := s.db.Exec(
|
|
r.Context(),
|
|
`
|
|
UPDATE conversation_members
|
|
SET last_cleared_at = now(), last_read_at = now()
|
|
WHERE conversation_id = $1
|
|
AND user_id = $2
|
|
`,
|
|
conversationID,
|
|
user.ID,
|
|
); err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden")
|
|
return
|
|
}
|
|
|
|
conversation, err := s.getChatConversation(r.Context(), conversationID, user.ID, user.ShowLastSeen)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
"conversation": conversation,
|
|
})
|
|
return
|
|
}
|
|
|
|
tx, err := s.db.Begin(r.Context())
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden")
|
|
return
|
|
}
|
|
defer tx.Rollback(r.Context())
|
|
|
|
if _, err := tx.Exec(
|
|
r.Context(),
|
|
`
|
|
UPDATE messages
|
|
SET deleted_at = now()
|
|
WHERE conversation_id = $1
|
|
AND deleted_at IS NULL
|
|
`,
|
|
conversationID,
|
|
); err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden")
|
|
return
|
|
}
|
|
|
|
if _, err := tx.Exec(
|
|
r.Context(),
|
|
`
|
|
UPDATE conversations
|
|
SET
|
|
last_message_at = (
|
|
SELECT MAX(created_at)
|
|
FROM messages
|
|
WHERE conversation_id = $1
|
|
AND deleted_at IS NULL
|
|
AND (expires_at IS NULL OR expires_at > now())
|
|
),
|
|
updated_at = now()
|
|
WHERE id = $1
|
|
`,
|
|
conversationID,
|
|
); err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden")
|
|
return
|
|
}
|
|
|
|
if err := tx.Commit(r.Context()); err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden")
|
|
return
|
|
}
|
|
|
|
s.publishChatMessagesReload(r.Context(), conversationID)
|
|
s.publishConversationUpdate(r.Context(), conversationID)
|
|
|
|
conversation, err := s.getChatConversation(r.Context(), conversationID, user.ID, user.ShowLastSeen)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
"conversation": conversation,
|
|
})
|
|
}
|