Make subscription_type, username, and years optional on POST /v1/admin/users
- subscription_type defaults to lifetime when omitted; validated when provided - years is only required (and enforced) when subscription_type is yearly - username uniqueness check and validation are skipped when username is empty - Update OpenAPI spec to reflect pubkey as the only required field
This commit is contained in:
@@ -222,12 +222,12 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
required: [pubkey, username, subscription_type]
|
required: [pubkey]
|
||||||
properties:
|
properties:
|
||||||
pubkey: { type: string }
|
pubkey: { type: string }
|
||||||
username: { type: string }
|
username: { type: string, description: "Optional NIP-05 username to assign" }
|
||||||
subscription_type: { type: string, enum: [yearly, lifetime] }
|
subscription_type: { type: string, enum: [yearly, lifetime], description: "Defaults to lifetime when omitted" }
|
||||||
years: { type: integer }
|
years: { type: integer, description: "Required when subscription_type is yearly" }
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: Created
|
description: Created
|
||||||
|
|||||||
@@ -42,22 +42,28 @@ func (h *AdminUsers) Add(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
sub := user.SubscriptionType(body.SubscriptionType)
|
sub := user.SubscriptionType(body.SubscriptionType)
|
||||||
if !sub.Valid() {
|
if body.SubscriptionType == "" {
|
||||||
|
sub = user.SubLifetime
|
||||||
|
} else if !sub.Valid() {
|
||||||
WriteError(w, http.StatusBadRequest, "ValidationError", "invalid subscription_type")
|
WriteError(w, http.StatusBadRequest, "ValidationError", "invalid subscription_type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
years := body.Years
|
years := body.Years
|
||||||
if years <= 0 {
|
if sub == user.SubYearly && years <= 0 {
|
||||||
years = 1
|
WriteError(w, http.StatusBadRequest, "ValidationError", "years is required for yearly subscription")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if existing, err := h.Users.Repo().GetByPubkey(r.Context(), hexpk); err == nil && existing != nil {
|
if existing, err := h.Users.Repo().GetByPubkey(r.Context(), hexpk); err == nil && existing != nil {
|
||||||
WriteError(w, http.StatusConflict, "Conflict", "user already exists")
|
WriteError(w, http.StatusConflict, "Conflict", "user already exists")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if existing, err := h.Users.Repo().GetByUsername(r.Context(), user.NormalizeUsername(body.Username)); err == nil && existing != nil {
|
if body.Username != "" {
|
||||||
WriteError(w, http.StatusConflict, "Conflict", "username taken")
|
if existing, err := h.Users.Repo().GetByUsername(r.Context(), user.NormalizeUsername(body.Username)); err == nil && existing != nil {
|
||||||
return
|
WriteError(w, http.StatusConflict, "Conflict", "username taken")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := h.Users.CreateOrActivate(r.Context(), hexpk, body.Username, sub, years, true)
|
u, err := h.Users.CreateOrActivate(r.Context(), hexpk, body.Username, sub, years, true)
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ func (s *Service) IsAvailable(ctx context.Context, username string) (bool, error
|
|||||||
// concerns (e.g. payments worker uses this within a tx).
|
// concerns (e.g. payments worker uses this within a tx).
|
||||||
func (s *Service) CreateOrActivate(ctx context.Context, pubkey, username string, sub SubscriptionType, years int, manual bool) (*User, error) {
|
func (s *Service) CreateOrActivate(ctx context.Context, pubkey, username string, sub SubscriptionType, years int, manual bool) (*User, error) {
|
||||||
username = NormalizeUsername(username)
|
username = NormalizeUsername(username)
|
||||||
if err := ValidateUsername(username, s.reserved); err != nil {
|
if username != "" {
|
||||||
return nil, err
|
if err := ValidateUsername(username, s.reserved); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
expiresAt := computeExpiry(sub, years, time.Time{}, now)
|
expiresAt := computeExpiry(sub, years, time.Time{}, now)
|
||||||
|
|||||||
Reference in New Issue
Block a user