Private spaces implementation#1339
Open
valentinRyckaert wants to merge 92 commits into
Open
Conversation
…the private space
…vate-spaces into private-spaces
…oogle for viewing all materials
…ce (and all the others)
…he user is part of from the main app
…zed users in main app
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces “private spaces” backed by a new group/membership system, and threads the resulting access-control rules through Pundit policies, controllers (space resolution + search/index filtering), UI, and tests.
Changes:
- Adds Group/GroupMembership models + CRUD UI, plus authorization rules that allow read access to members/admins and restrict write access to owners/admins (and block API writes).
- Adds
spaces.is_privateand space↔group association, with sharedApplicationPolicy#shown?visibility logic and private-space enforcement inApplicationController#set_current_space. - Filters indexed/search results (incl. Solr-backed listings) by
shown?, and adds documentation + test coverage for the private-space access scenario.
Reviewed changes
Copilot reviewed 53 out of 55 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| test/system/groups_test.rb | System tests for basic Groups UI flows (index/create/update/destroy). |
| test/models/space_test.rb | Model validation test for “private space must have required groups”. |
| test/models/group_test.rb | Placeholder Group model test file. |
| test/integration/private_space_access_test.rb | Integration-style coverage for private-space access across spaces/materials surfaces. |
| test/fixtures/groups.yml | Adds Group fixtures used by tests. |
| test/controllers/groups_controller_test.rb | Controller-level tests for Group authorization + API write restrictions. |
| Gemfile | Adds explicit rdoc (>= 8.0) dependency. |
| Gemfile.lock | Updates lockfile for rdoc/rbs/prism-related dependencies. |
| docs/spaces.md | Documents private spaces behavior and deletion/nullification semantics. |
| docs/docstrings.md | Adds RDoc/docstring conventions documentation. |
| db/schema.rb | Adds groups, group_memberships, groups_spaces, and spaces.is_private to schema. |
| db/migrate/20260612065213_create_groups.rb | Creates groups table. |
| db/migrate/20260612065245_create_join_table_groups_users.rb | Creates interim groups↔users join table (later replaced). |
| db/migrate/20260612065251_create_join_table_groups_spaces.rb | Creates groups↔spaces join table. |
| db/migrate/20260618090239_add_is_private_to_spaces.rb | Adds is_private boolean to spaces. |
| db/migrate/20260618141208_replace_groups_users_with_group_memberships.rb | Replaces groups_users with group_memberships join model (with owner flag). |
| config/routes.rb | Adds RESTful routes for groups. |
| config/locales/en.yml | Updates “spaces” copy to mention private spaces/groups. |
| config/application.rb | Whitespace-only change. |
| app/views/users/show.html.erb | Adds a “Groups” section to the user sidebar with collapse/overflow UI. |
| app/views/users/_list.json.jbuilder | Alters /users.json list output (now excluding admins). |
| app/views/spaces/edit.html.erb | Whitespace-only change. |
| app/views/spaces/_form.html.erb | Adds private-space toggle and groups autocompleter; includes JS. |
| app/views/layouts/_user_menu.html.erb | Adds “View groups” to admin/curator/owner admin menu. |
| app/views/groups/index.html.erb | New Groups index UI. |
| app/views/groups/show.html.erb | New Groups show page with members + related spaces sections. |
| app/views/groups/new.html.erb | New group page. |
| app/views/groups/edit.html.erb | Edit group page. |
| app/views/groups/_form.html.erb | Group form with user autocompleter + owner flag selection. |
| app/views/groups/_group.html.erb | Group partial. |
| app/views/groups/_group.json.jbuilder | Group JSON representation. |
| app/views/groups/index.json.jbuilder | Groups index JSON. |
| app/views/groups/show.json.jbuilder | Group show JSON. |
| app/serializers/group_serializer.rb | Adds Group serializer for API/JSON:API usage. |
| app/policies/application_policy.rb | Adds shared shown? visibility logic for private-space scoping + docstrings. |
| app/policies/space_policy.rb | Aligns SpacePolicy show/edit/destroy with shown?/admin/space-admin rules. |
| app/policies/group_policy.rb | New GroupPolicy for member/admin visibility and HTML-only writes. |
| app/policies/material_policy.rb | Ensures Material show? also requires shown? (private-space visibility). |
| app/policies/event_policy.rb | Ensures Event show? also requires shown? (private-space visibility). |
| app/models/user.rb | Adds group/group_membership associations + owner helper methods. |
| app/models/space.rb | Adds groups association, private-space validation, and destroy-time handling + docstrings. |
| app/models/group.rb | New Group model with memberships and spaces associations. |
| app/models/group_membership.rb | New join model with owner flag and composite PK intent. |
| app/models/global_space.rb | Adjusts equality semantics for GlobalSpace. |
| app/helpers/groups_helper.rb | Adds Groups helper module. |
| app/controllers/groups_controller.rb | Adds Groups CRUD with membership owner syncing + policy enforcement. |
| app/controllers/spaces_controller.rb | Filters spaces#index by shown? and permits group_ids/is_private. |
| app/controllers/materials_controller.rb | Adds @results_count for index results. |
| app/controllers/concerns/searchable_index.rb | Filters Solr results by shown? and changes JSON:API meta keys. |
| app/controllers/application_controller.rb | Enforces private-space access at space resolution time (host-based). |
| app/assets/javascripts/templates/autocompleter/group_member.hbs | Autocompleter template for group membership rows (incl. owner checkbox). |
| app/assets/javascripts/templates/autocompleter/group_id.hbs | Autocompleter template for group selection in space form. |
| app/assets/javascripts/show_private_groups.js | Toggles required-groups UI based on “private space” checkbox. |
| app/assets/javascripts/autocompleters.js | Adds groups transform function for autocompleter responses. |
| app/assets/config/manifest.js | Includes show_private_groups.js in asset pipeline. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+12
to
16
| @spaces = Space.all.select { |space| policy(space).shown? } | ||
| respond_to do |format| | ||
| format.html | ||
| format.json { render json: @groups.as_json(only: [:id, :title]) } | ||
| end |
Contributor
Author
There was a problem hiding this comment.
Why removing @spaces = Space.all.select { |space| policy(space).shown? }? @spaces needs to be initialized.
Comment on lines
+55
to
+61
| # Override total on the Solr result object so the view gets the right count | ||
| @search_results.instance_variable_set(:@total, filtered.length) | ||
| def @search_results.total; @total; end | ||
|
|
||
| @index_resources = WillPaginate::Collection.create(page, per_page, filtered.length) do |pager| | ||
| pager.replace(filtered) | ||
| end |
Comment on lines
+93
to
+97
| # Returns:: the default Pundit policy scope for the record's class, | ||
| # filtered by #shown?. | ||
| def scope | ||
| Pundit.policy_scope!(user, record.class) | ||
| Pundit.policy_scope!(user, record.class).shown? | ||
| end |
Comment on lines
+394
to
+396
| def is_owner_in_any_group? | ||
| Group.all.any? { |group| group.group_memberships.find_by(user: self)&.owner == true } | ||
| end |
Comment on lines
+45
to
+50
| def validate(record) | ||
| Rails.logger.info "Validating space: is_private=#{record.is_private}, groups_count=#{record.groups.length}" | ||
| if record.is_private && record.groups.length == 0 | ||
| record.errors.add(:base, "If the space is private, you must add required groups.") | ||
| end | ||
| end |
Comment on lines
+66
to
+70
| <%= button_to @group, method: :delete, | ||
| class: 'btn btn-danger', | ||
| form: { data: { confirm: "Are you sure you want to delete this group?" } } do %> | ||
| <i class="glyphicon glyphicon-trash"></i> Delete | ||
| <% end %> |
| @@ -0,0 +1,23 @@ | |||
| // excuted for space form | |||
Comment on lines
+3
to
+6
| create_join_table :groups, :spaces do |t| | ||
| # t.index [:group_id, :space_id] | ||
| # t.index [:space_id, :group_id] | ||
| end |
Comment on lines
+1
to
+5
| class AddIsPrivateToSpaces < ActiveRecord::Migration[7.2] | ||
| def change | ||
| add_column :spaces, :is_private, :boolean | ||
| end | ||
| end |
Comment on lines
122
to
127
| meta: { | ||
| facets: facets, | ||
| available_facets: available_facets, | ||
| query: @search_params, | ||
| results_count: total | ||
| facets: facets, | ||
| :'available-facets' => available_facets, | ||
| query: @search_params, | ||
| :'results-count' => total | ||
| } |
Contributor
|
I just ran the whole test suite on this branch, it works locally....... Maybe tests fail because of the gem audit failing as well? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of changes
Database
3 new tables
Changes in existing tables
Code
New group controller and policy
New MemberShip Model
Shown? in application policy
Spaces controller and policy updates
space policy:
space controller:
Solr search_index updates
Application controller updates
Space model update
Rdoc
Screenshots
Checklist