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