feat: disciple link
This commit is contained in:
@@ -34,6 +34,11 @@ type Server struct {
|
||||
pg *repository.Postgres
|
||||
redis *repository.Redis
|
||||
|
||||
// discipleRepo is held on the struct (unlike the other Mongo repos, which
|
||||
// stay local to New) because initAuth re-builds discipleH with the
|
||||
// Postgres userRepo once it exists — see the direct-disciple link feature.
|
||||
discipleRepo *repository.DiscipleRepo
|
||||
|
||||
// Worker lifecycle
|
||||
workerCancel context.CancelFunc
|
||||
workerCtx context.Context // derived in initShortener; cancelled on Close
|
||||
@@ -103,12 +108,15 @@ func New(cfg *config.Config, logger *zap.Logger) *Server {
|
||||
logger: logger,
|
||||
mongo: mongoDB,
|
||||
|
||||
discipleRepo: discipleRepo,
|
||||
|
||||
// Initialize handlers
|
||||
bookH: handler.NewBookHandler(bookRepo),
|
||||
letterH: handler.NewLetterHandler(letterRepo),
|
||||
essayH: handler.NewEssayHandler(essayRepo),
|
||||
glossaryH: handler.NewGlossaryHandler(glossaryRepo),
|
||||
discipleH: handler.NewDiscipleHandler(discipleRepo),
|
||||
// userRepo half is attached later in initAuth (Postgres isn't up yet).
|
||||
discipleH: handler.NewDiscipleHandler(discipleRepo, nil),
|
||||
journalH: handler.NewJournalHandler(journalRepo),
|
||||
magazineH: handler.NewMagazineHandler(magazineRepo),
|
||||
otherDocH: handler.NewOtherDocumentHandler(otherDocRepo),
|
||||
@@ -196,6 +204,14 @@ func (s *Server) initAuth(cfg *config.Config, logger *zap.Logger) {
|
||||
s.authH = handler.NewAuthHandler(authSvc, cookieOpts)
|
||||
s.userH = handler.NewUserHandler(userSvc)
|
||||
|
||||
// Re-wire the disciple handler now that Postgres-backed users exist: its
|
||||
// /disciples/linked route joins the Mongo disciple records to the platform
|
||||
// accounts an admin has linked to them. Built in New() with a nil userRepo
|
||||
// (Mongo is up before Postgres), so this is where it gets the other half.
|
||||
if s.discipleRepo != nil {
|
||||
s.discipleH = handler.NewDiscipleHandler(s.discipleRepo, userRepo)
|
||||
}
|
||||
|
||||
// Audio playback resume points — per-user, per-file last position that
|
||||
// lets the floating player pick up where it left off across devices.
|
||||
audioProgressRepo := repository.NewAudioProgressRepo(s.pg)
|
||||
@@ -303,7 +319,7 @@ func (s *Server) initAuth(cfg *config.Config, logger *zap.Logger) {
|
||||
// Reuses the notification service (delivery) and mailer (feedback reply).
|
||||
// Gated by RequireAuth + RequireAdmin in the router.
|
||||
adminRepo := repository.NewAdminRepo(s.pg)
|
||||
adminSvc := service.NewAdminService(adminRepo, statsRepo, notifSvc, feedbackSvc, mail, logger, cfg.FrontendURL)
|
||||
adminSvc := service.NewAdminService(adminRepo, statsRepo, notifSvc, feedbackSvc, userRepo, s.discipleRepo, mail, logger, cfg.FrontendURL)
|
||||
s.adminH = handler.NewAdminHandler(adminSvc)
|
||||
}
|
||||
|
||||
@@ -610,6 +626,9 @@ func (s *Server) setupRouter() {
|
||||
r.Get("/letters", s.discipleH.LetterCounts)
|
||||
r.Get("/suffixes", s.discipleH.SuffixCounts)
|
||||
r.Get("/search", s.discipleH.Search)
|
||||
// Disciples with a platform account (admin-linked) — drives the
|
||||
// highlight in the /disciples browser.
|
||||
r.Get("/linked", s.discipleH.Linked)
|
||||
})
|
||||
|
||||
// Journals
|
||||
@@ -1037,6 +1056,11 @@ func (s *Server) setupRouter() {
|
||||
r.Post("/users/{id}/ban", s.adminH.BanUser)
|
||||
r.Delete("/users/{id}/ban", s.adminH.UnbanUser)
|
||||
r.Post("/users/{id}/limits", s.adminH.SetUserLimits)
|
||||
// Direct-disciple linking: mark an account as one of Śrīla
|
||||
// Prabhupāda's initiated disciples (or clear the mark).
|
||||
r.Get("/disciples", s.adminH.ListDisciples)
|
||||
r.Post("/users/{id}/disciple", s.adminH.LinkDisciple)
|
||||
r.Delete("/users/{id}/disciple", s.adminH.UnlinkDisciple)
|
||||
r.Get("/posts", s.adminH.ListPosts)
|
||||
r.Post("/posts/{id}/hide", s.adminH.HidePost)
|
||||
r.Delete("/posts/{id}/hide", s.adminH.UnhidePost)
|
||||
|
||||
Reference in New Issue
Block a user