-
Notifications
You must be signed in to change notification settings - Fork 1
feat(content): add published-to-private unpublish endpoint #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,6 +103,23 @@ public ContentResponse publish(String contentId, String userId) { | |
| return toResponse(contentRepository.save(content)); | ||
| } | ||
|
|
||
| @Transactional | ||
| public ContentResponse unpublish(String contentId, String userId) { | ||
| ContentEntity content = contentRepository.findById(contentId).orElseThrow( | ||
| () -> new ApiException(HttpStatus.NOT_FOUND, "CONTENT_NOT_FOUND", "Content not found", null)); | ||
| assertMember(content.getChannel().getId(), userId); | ||
|
|
||
| if (content.getState() != ContentState.PUBLISHED) { | ||
| throw new ApiException(HttpStatus.CONFLICT, "CONTENT_STATE_INVALID", | ||
| "Content can only be unpublished from published state", null); | ||
| } | ||
|
|
||
| content.setState(ContentState.PRIVATE); | ||
| content.setUpdatedAt(LocalDateTime.now()); | ||
|
|
||
| return toResponse(contentRepository.save(content)); | ||
|
Comment on lines
+112
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make the state transition atomic to preserve guardrails under concurrency. Line 112 and Line 117 perform check-then-write in separate steps; concurrent requests can both pass the 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public PlaybackResponse getPlayback(String contentId, String countryCode, Boolean ageVerified) { | ||
| ContentEntity content = contentRepository.findById(contentId).orElseThrow( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document the membership failure case (
403 CHANNEL_ACCESS_DENIED).This endpoint is membership-protected in implementation, but the contract currently only documents the
409case. Add403 CHANNEL_ACCESS_DENIEDso client behavior is fully specified.📝 Suggested doc patch
### `POST /v1/content/{content_id}/unpublish` - Unpublishes content from `PUBLISHED` to `PRIVATE` - Request fields (MVP): `userId` +- Returns `403 CHANNEL_ACCESS_DENIED` when user is not a channel member - Returns `409 CONTENT_STATE_INVALID` when state is not `PUBLISHED`📝 Committable suggestion
🤖 Prompt for AI Agents