fix: add authorization to AI and suggestion endpoints#9
Conversation
|
✅ @khasinski — Superconductor finished — View implementation Standing by for instructions. |
There was a problem hiding this comment.
Pull request overview
This pull request adds authorization checks to prevent unauthorized access to AI assistant features and suggestion management. Previously, any authenticated user could invoke AI actions on any page or accept/reject suggestions regardless of their access to the parent report.
Changes:
- Added
authorize_suggestion!method to SuggestionsController to verify users have editor access to a suggestion's parent report before accepting/rejecting - Added
authorize_page_access!method to AssistantsController to verify users have access to a page's report when invoking AI actions with a page_id parameter - Uses conditional before_action in AssistantsController to only enforce authorization when page_id is present
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| app/controllers/suggestions_controller.rb | Adds authorization to verify editor access before accepting/rejecting suggestions |
| app/controllers/assistants_controller.rb | Adds authorization to verify report access when AI actions are invoked with a page_id parameter |
Comments suppressed due to low confidence (2)
app/controllers/assistants_controller.rb:306
- Spelling error: "accessable" should be "accessible". This is consistent with a misspelling throughout the codebase in the Report::Accessable module and related methods. While this is an existing codebase-wide issue, this new code continues the pattern. Consider fixing the spelling throughout the codebase in a separate refactoring.
head :forbidden unless page&.report&.accessable?
app/controllers/assistants_controller.rb:305
- Maintainability: When page_id is present, the page is queried twice - once in
authorize_page_access!(line 305) and once in actions likestream(line 210) andresearch(line 105). Consider storing the page in an instance variable in the authorization method (e.g.,@page = Page.find_by(id: params[:page_id])) and reusing it in actions to avoid duplicate database queries. This would follow the pattern seen in other controllers like SuggestionsController whereset_suggestionstores@suggestionfor use in the authorization method.
def authorize_page_access!
page = Page.find_by(id: params[:page_id])
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| def authorize_page_access! | ||
| page = Page.find_by(id: params[:page_id]) | ||
| head :forbidden unless page&.report&.accessable? |
There was a problem hiding this comment.
API design consideration: The authorization check uses accessable? which allows both readers and editors to invoke AI actions. This means readers can generate AI suggestions on pages they can read, but cannot accept/reject those suggestions (since SuggestionsController requires editable? access).
If this is intentional (readers can propose AI-generated changes that editors must approve), consider documenting this behavior. If AI actions should be editor-only, change accessable? to editable? to match the SuggestionsController pattern and prevent readers from generating suggestions they cannot manage.
| head :forbidden unless page&.report&.accessable? | |
| head :forbidden unless page&.report&.editable? |
| def authorize_suggestion! | ||
| report = @suggestion.suggestable&.report | ||
| head :forbidden unless report&.editable? | ||
| end |
There was a problem hiding this comment.
Test coverage: The new authorization logic in authorize_suggestion! should have explicit test coverage. Consider adding controller tests that verify:
- Editors can accept/reject suggestions on their reports
- Readers cannot accept/reject suggestions (should get 403 Forbidden)
- Users without access cannot accept/reject suggestions (should get 403 Forbidden)
- The behavior when suggestion.suggestable or report is nil
This is critical security functionality that should have comprehensive test coverage. See similar authorization tests in test/controllers/sectionables_controller_test.rb lines 51-61 for reference.
| def authorize_page_access! | ||
| page = Page.find_by(id: params[:page_id]) | ||
| head :forbidden unless page&.report&.accessable? | ||
| end |
There was a problem hiding this comment.
Test coverage: The new authorization logic in authorize_page_access! should have explicit test coverage. Consider adding controller tests that verify:
- Users with access to a page's report can invoke AI actions with page_id
- Users without access to a page's report get 403 Forbidden when page_id is provided
- The behavior when page_id is invalid or page doesn't exist
- AI actions work correctly when page_id is not provided (no authorization required)
This is critical security functionality that should have comprehensive test coverage. See similar authorization tests in test/controllers/sectionables_controller_test.rb lines 51-61 for reference.
Previously any authenticated user could invoke AI on any page or accept/reject any suggestion by ID, regardless of report access. - SuggestionsController: verify user has editor access to the suggestion's parent report before allowing accept/reject - AssistantsController: when page_id is provided, verify user has access to the page's report before invoking AI actions
- Change authorize_page_access! from accessable? to editable? since AI assistant actions modify content and shouldn't be available to readers - Add test for editor access with page_id (succeeds) - Add test for reader access with page_id (forbidden) - Add test for requests without page_id (skips page auth)
2f20e3c to
deb1583
Compare
Summary
Previously any authenticated user could invoke AI on any page or accept/reject any suggestion by ID, regardless of report access.
Test plan