Skip to content

Conversation

@fedmag
Copy link

@fedmag fedmag commented Nov 6, 2025

Hello, this is a first draft for the addition of pre-moderation.
It uses an "approved" flag to define if a comment should be visible to non-admin users.
Only admins can approve/disapprove comments.

There are 3 modes:

  • none: this is the default and it basically "approves" all comments by default
  • all: every new comment must be approved before it becomes visible to non-admin users.
  • first: only the first comment from a given user must be approved. All subsequent and previous messages are approved as one of them is approved. If an approved comment is disapproved, only that specific comment becomes unapproved.

In the UI, I added a red border for unapproved comments so that they are easy to spot:
image
I'd assume this solution is not desirable, but I did not have any other idea.

@fedmag fedmag marked this pull request as ready for review November 8, 2025 09:08
@fedmag fedmag requested a review from umputun as a code owner November 8, 2025 09:08
@umputun umputun requested review from Mavrin, Copilot and paskal November 8, 2025 20:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a premoderation feature for comments with three configurable strategies: "none" (no premoderation), "first" (premoderate only the first comment from a user), and "all" (premoderate every comment). The feature allows admins to approve comments before they become visible to regular users.

  • Adds premoderation logic on both frontend and backend with an admin approval UI
  • Introduces filtering of unapproved comments for non-admin users
  • Implements approval workflow that can approve single or multiple comments based on strategy

Reviewed Changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
backend/app/store/comment.go Adds Approved boolean field to Comment struct
backend/app/store/service/service.go Implements ApproveComments method supporting single and bulk approval
backend/app/rest/api/rest.go Defines Premoderation type and factory function
backend/app/rest/api/rest_public.go Filters unapproved comments for non-admin users in public endpoints
backend/app/rest/api/rest_private.go Handles premoderation logic during comment creation
backend/app/rest/api/admin.go Adds admin endpoint for approving comments
backend/app/main.go Adds CLI flag for premoderation configuration
backend/app/cmd/cmd.go Passes premoderation option through command structure
backend/app/cmd/server.go Initializes server with premoderation strategy
backend/app/rest/httperrors.go Adds error code for premoderation failures
frontend/apps/remark42/app/common/types.ts Adds approved field to Comment interface
frontend/apps/remark42/app/common/api.ts Adds approveComment API function
frontend/apps/remark42/app/store/comments/actions.ts Adds approveComment Redux action
frontend/apps/remark42/app/components/comment/comment.tsx Adds UI logic and styling for unapproved comments
frontend/apps/remark42/app/components/comment/comment-actions.tsx Adds approve/disapprove button
frontend/apps/remark42/app/components/comment/connected-comment.tsx Connects approve action to component
backend/app/rest/api/rest_public_test.go Updates tests to handle approved field in responses
backend/app/rest/api/admin_test.go Adds tests for comment approval functionality
backend/app/store/service/service_test.go Adds test for ApproveComments service method

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

(id: Comment['id'], text: string, approved: boolean): StoreAction<Promise<void>> =>
async (dispatch) => {
const comment = await api.approveComment({ id, text, approved });
dispatch(patchComment({ ...comment, approved: comment.approved }));
Copy link

Copilot AI Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spread operator { ...comment, approved: comment.approved } is redundant since comment already contains the approved field. Consider simplifying to just dispatch(patchComment(comment)).

Suggested change
dispatch(patchComment({ ...comment, approved: comment.approved }));
dispatch(patchComment(comment));

Copilot uses AI. Check for mistakes.
comment.Approved = true
return comment, nil
}
}
Copy link

Copilot AI Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing fallback case: If PremoderationFirst is active and the user has previous comments but none are approved, the function doesn't explicitly set comment.Approved = false before falling through. The comment will remain with its default zero value, but this should be made explicit for clarity. Add comment.Approved = false after the loop (line 214).

Suggested change
}
}
// Explicitly set Approved to false if no previous comment was approved
comment.Approved = false

Copilot uses AI. Check for mistakes.
@cowsay
Copy link

cowsay commented Nov 9, 2025

@fedmag Hi, is it possible to add modes "with links" or/and "with images"?

@fedmag
Copy link
Author

fedmag commented Nov 9, 2025

@fedmag Hi, is it possible to add modes "with links" or/and "with images"?

Hi @cowsay, if this goes in and the code owners want such a feature, I can certainly look into that.
I can see why it might be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants