package handlers import ( "encoding/json" "errors" "net/http" "github.com/go-chi/chi/v5" "github.com/noderunners/nip05api/internal/audit" "github.com/noderunners/nip05api/internal/dm" "github.com/noderunners/nip05api/internal/nostr" "github.com/noderunners/nip05api/internal/user" "github.com/noderunners/nip05api/internal/webhook" ) type AdminExtend struct { Users *user.Service DMs *dm.Service Hooks *webhook.Service Audit *audit.Logger Domain string Frontend string } type extendReq struct { Years int `json:"years"` SubscriptionType string `json:"subscription_type"` } func (h *AdminExtend) Handle(w http.ResponseWriter, r *http.Request) { hexpk, err := nostr.NormalizePubkey(chi.URLParam(r, "pubkey")) if err != nil { WriteError(w, http.StatusBadRequest, "ValidationError", "Invalid pubkey format") return } var body extendReq if err := json.NewDecoder(r.Body).Decode(&body); err != nil { WriteError(w, http.StatusBadRequest, "ValidationError", "invalid JSON") return } u, err := h.Users.Repo().GetByPubkey(r.Context(), hexpk) if errors.Is(err, user.ErrUserNotFound) { WriteError(w, http.StatusNotFound, "NotFound", "user not found") return } if err != nil { WriteError(w, http.StatusInternalServerError, "InternalError", err.Error()) return } sub := u.SubscriptionType if body.SubscriptionType != "" { s := user.SubscriptionType(body.SubscriptionType) if !s.Valid() { WriteError(w, http.StatusBadRequest, "ValidationError", "invalid subscription_type") return } sub = s } years := body.Years if sub == user.SubYearly && years <= 0 { years = 1 } if err := h.Users.Renew(r.Context(), u, sub, years); err != nil { WriteError(w, http.StatusInternalServerError, "InternalError", err.Error()) return } vars := dmVars(u, h.Domain, h.Frontend) _ = h.DMs.Send(r.Context(), dm.EventExtended, u.Pubkey, vars) _ = h.Hooks.Enqueue(r.Context(), webhook.EventUserExtended, hookData(u, h.Domain)) h.Audit.Log(r.Context(), audit.ActionUserExtended, audit.ActorAdmin, u.Pubkey, map[string]any{ "subscription_type": string(sub), "years": years, }) WriteJSON(w, http.StatusOK, userResponse(u)) }