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}