CommunityPro / CommunityPro/community-pro-api

Content: admin approval queue + Brevo decision emails (Phase 4.3, 8.3)

Open
#4 0 comments 0 reactions 0 assignees View on GitHub
admin content
Dominant language
C#
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Scope
Admin decision endpoints for the blog workflow, plus author notification emails.

| Method | Path | Notes |
|---|---|---|
| GET | `/admin/posts?status=submitted` | approval queue, paginated, newest first |
| POST | `/admin/posts/{id}/approve` | Submitted → Published (immediately — no scheduling in v1); sets `PublishedAt`; publishes `PostPublished` domain event |
| POST | `/admin/posts/{id}/reject` | body requires `reason`; Submitted → Draft with `RejectionReason` |
| POST | `/admin/posts/{id}/feature` | set `IsFeatured` (clears previous) |

## Emails
On approve/reject, send the author a Brevo email with the decision (+ reason when rejected) via the existing `IEmailSender` abstraction (Identity module owns the SMTP relay — reuse the same best-effort, never-throw pattern as the welcome email).

## Events
`PostPublished` (and `PostUnpublished` if unpublish is added later) are consumed by the search/revalidation ticket {{C3}} — this ticket only emits.

## Error codes
`content.not_found`, `content.invalid_state`, `content.rejection_reason_required`

## Dependencies
Blocked by #3 (submitted posts must exist) and #1 (admin policy + route group).

## Acceptance criteria
- [ ] Approve/reject only valid from `Submitted`; reason mandatory on reject
- [ ] Approve sets `PublishedAt` and emits `PostPublished` exactly once
- [ ] Email failures are logged, never fail the request
- [ ] Feature clears the previously featured post
- [ ] xUnit coverage incl. the event emission

### Conventions (project-wide, non-negotiable)
- .NET 9, records for immutable shapes, file-scoped namespaces, primary constructors where they read well. Minimal-API endpoints grouped per module via `IEndpointModule.MapEndpoints`.
- `Result` (SharedKernel) instead of exception-driven control flow. Endpoint results map failures to ProblemDetails with the stable error codes listed above — the frontend keys off them.
- Module owns its EF Core `DbContext` mapped to its own Postgres schema. Modules never reference each other's internals — cross-module needs go through a public contract interface or an in-process domain event (`IEventPublisher`).
- All external calls (GitHub, Stripe, Brevo, Cloudinary, Meilisearch) behind interfaces owned by the consuming module.
- Every list endpoint paginated (offset is fine). xUnit tests in `tests/CommunityPro.Tests//` following the existing harness patterns (see `Members/MembersTestHarness.cs`).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading the existing module patterns for IEndpointModule.MapEndpoints and the welcome email's IEmailSender usage, then review tests/CommunityPro.Tests/Members/MembersTestHarness.cs for the test setup. Implement the listed admin workflow and email behavior after #3 and #1 are available, and verify the acceptance criteria, including xUnit coverage for exactly-once event emission and non-failing email errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, postgresql
Domain
backend-api-design, content, databases, testing
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.