A community based topic aggregation platform built on atproto
1package community
2
3import (
4 "encoding/json"
5 "net/http"
6
7 "Coves/internal/api/middleware"
8 "Coves/internal/core/communities"
9)
10
11// CreateHandler handles community creation
12type CreateHandler struct {
13 service communities.Service
14}
15
16// NewCreateHandler creates a new create handler
17func NewCreateHandler(service communities.Service) *CreateHandler {
18 return &CreateHandler{
19 service: service,
20 }
21}
22
23// HandleCreate creates a new community
24// POST /xrpc/social.coves.community.create
25// Body matches CreateCommunityRequest
26func (h *CreateHandler) HandleCreate(w http.ResponseWriter, r *http.Request) {
27 if r.Method != http.MethodPost {
28 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
29 return
30 }
31
32 // Parse request body
33 var req communities.CreateCommunityRequest
34 if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
35 writeError(w, http.StatusBadRequest, "InvalidRequest", "Invalid request body")
36 return
37 }
38
39 // Extract authenticated user DID from request context (injected by auth middleware)
40 userDID := middleware.GetUserDID(r)
41 if userDID == "" {
42 writeError(w, http.StatusUnauthorized, "AuthRequired", "Authentication required")
43 return
44 }
45
46 // Client should not send createdByDid - we derive it from authenticated user
47 if req.CreatedByDID != "" {
48 writeError(w, http.StatusBadRequest, "InvalidRequest",
49 "createdByDid must not be provided - derived from authenticated user")
50 return
51 }
52
53 // Client should not send hostedByDid - we derive it from the instance
54 if req.HostedByDID != "" {
55 writeError(w, http.StatusBadRequest, "InvalidRequest",
56 "hostedByDid must not be provided - derived from instance")
57 return
58 }
59
60 // Set the authenticated user as the creator
61 req.CreatedByDID = userDID
62 // Note: hostedByDID will be set by the service layer based on instance configuration
63
64 // Create community via service (write-forward to PDS)
65 community, err := h.service.CreateCommunity(r.Context(), req)
66 if err != nil {
67 handleServiceError(w, err)
68 return
69 }
70
71 // Return success response matching lexicon output
72 response := map[string]interface{}{
73 "uri": community.RecordURI,
74 "cid": community.RecordCID,
75 "did": community.DID,
76 "handle": community.Handle,
77 }
78
79 w.Header().Set("Content-Type", "application/json")
80 w.WriteHeader(http.StatusOK)
81 if err := json.NewEncoder(w).Encode(response); err != nil {
82 // Log encoding errors but don't return error response (headers already sent)
83 // This follows Go's standard practice for HTTP handlers
84 _ = err
85 }
86}