feat: disciple link
This commit is contained in:
@@ -31,6 +31,27 @@ type AdminUser struct {
|
||||
BookmarkLimit int `json:"bookmark_limit"`
|
||||
PublicCollectionLimit int `json:"public_collection_limit"`
|
||||
PrivateCollectionLimit int `json:"private_collection_limit"`
|
||||
|
||||
// Direct-disciple link. DiscipleID is the raw Mongo ObjectID stored on the
|
||||
// users row; DiscipleName is hydrated from Mongo by the admin service so the
|
||||
// panel can show who the account is linked to (nil when unlinked, or when
|
||||
// the id no longer resolves to a disciple document).
|
||||
DiscipleID *string `json:"disciple_id"`
|
||||
DiscipleName *string `json:"disciple_name"`
|
||||
}
|
||||
|
||||
// AdminDisciple is one option in the admin panel's disciple picker — enough to
|
||||
// disambiguate similarly-named disciples, plus the handle of the account that
|
||||
// already claims it (nil when free to link).
|
||||
type AdminDisciple struct {
|
||||
ID string `json:"id"`
|
||||
InitiatedName string `json:"initiated_name"`
|
||||
Suffix string `json:"suffix"`
|
||||
InitiationDate *time.Time `json:"initiation_date"`
|
||||
InitiationPlace *string `json:"initiation_place"`
|
||||
// LinkedHandle is the @handle of the user already linked to this disciple,
|
||||
// so the picker can grey the row out instead of failing on submit.
|
||||
LinkedHandle *string `json:"linked_handle"`
|
||||
}
|
||||
|
||||
// AdminPost is a row in the admin posts table.
|
||||
|
||||
@@ -38,6 +38,14 @@ type Feedback struct {
|
||||
ReplyMessage *string `json:"reply_message,omitempty"`
|
||||
RepliedAt *time.Time `json:"replied_at,omitempty"`
|
||||
|
||||
// HasContactEmail reports *whether* an anonymous submitter left a reply-to
|
||||
// address, without carrying the address itself. Populated only by
|
||||
// Recent(), whose sole consumer is the PUBLIC /stats page — that page has
|
||||
// to distinguish "anonymous, but we can reply" from "anonymous dead end"
|
||||
// while never handling the email. Admins see the real address in the
|
||||
// admin panel, which is auth-gated.
|
||||
HasContactEmail bool `json:"-"`
|
||||
|
||||
AuthorHandle *string `json:"author_handle,omitempty"`
|
||||
AuthorName *string `json:"author_name,omitempty"`
|
||||
AuthorEmail *string `json:"-"` // server-side only; never serialised
|
||||
|
||||
@@ -152,6 +152,9 @@ type PublicProfile struct {
|
||||
JoinedAt time.Time `json:"joined_at"`
|
||||
PostCount int `json:"post_count"`
|
||||
BookmarkCount int `json:"-"` // never serialized — private
|
||||
// IsDirectDisciple marks an account an admin has linked to the disciples
|
||||
// directory — one of Śrīla Prabhupāda's own initiated disciples.
|
||||
IsDirectDisciple bool `json:"is_direct_disciple"`
|
||||
}
|
||||
|
||||
// RelationshipState is the viewer's relationship to a target profile,
|
||||
|
||||
+20
-6
@@ -42,6 +42,16 @@ type User struct {
|
||||
// nil until known.
|
||||
Country *string `json:"country"`
|
||||
|
||||
// DiscipleID links this account to a row in the Mongo `disciples`
|
||||
// collection (ObjectID hex) when the account belongs to one of Śrīla
|
||||
// Prabhupāda's own initiated disciples. Admin-set only — never
|
||||
// self-serve — and unique across users, so one disciple maps to at most
|
||||
// one account. nil for everybody else.
|
||||
//
|
||||
// Tagged `json:"-"`: the raw cross-store id is an internal detail. The
|
||||
// public profile exposes only the derived `is_direct_disciple` flag.
|
||||
DiscipleID *string `json:"-"`
|
||||
|
||||
// --- Devotional profile (user-editable) ---
|
||||
// Gender is a free-but-constrained string ("male"|"female"|"other"),
|
||||
// nil when unspecified.
|
||||
@@ -86,17 +96,21 @@ type User struct {
|
||||
|
||||
// MarshalJSON adds a derived `has_password` flag so the frontend can pick
|
||||
// "Change password" vs "Set a password" for OAuth-only accounts, without
|
||||
// the password hash itself ever leaving the server.
|
||||
// the password hash itself ever leaving the server. `is_direct_disciple` is
|
||||
// likewise derived — the raw cross-store DiscipleID stays server-side while
|
||||
// the frontend gets the one bit it needs to render the badge.
|
||||
func (u User) MarshalJSON() ([]byte, error) {
|
||||
type alias User
|
||||
return json.Marshal(&struct {
|
||||
alias
|
||||
HasPassword bool `json:"has_password"`
|
||||
Limits UserLimits `json:"limits"`
|
||||
HasPassword bool `json:"has_password"`
|
||||
IsDirectDisciple bool `json:"is_direct_disciple"`
|
||||
Limits UserLimits `json:"limits"`
|
||||
}{
|
||||
alias: alias(u),
|
||||
HasPassword: u.PasswordHash != nil,
|
||||
Limits: u.EffectiveLimits(),
|
||||
alias: alias(u),
|
||||
HasPassword: u.PasswordHash != nil,
|
||||
IsDirectDisciple: u.DiscipleID != nil && *u.DiscipleID != "",
|
||||
Limits: u.EffectiveLimits(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user