-
Notifications
You must be signed in to change notification settings - Fork 19
Update policies and tests to handle button normalization #844
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
Conversation
| @@ -1,4 +1,5 @@ | |||
| class ApplicationController < ActionController::Base | |||
| include ActionPolicy::Controller | |||
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.
this gives helper methods including allowed_to?, which we're now using on forms to determine if delete button should show
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.
| include ActionPolicy::Controller |
Shouldn't need this explicitly. allowed_to? was already working for me and the doc's say its included in ActionController::Base
Were you getting an error without it?
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.
oh interesting. yes, was getting an error.
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.
i just removed it and everything still worked. TY for catching this!
| @sectors = Sector.published | ||
| @windows_types = WindowsType.all | ||
| # @category_types = CategoryType.includes(:categories).published.decorate | ||
| @categories_grouped = |
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.
tags need the grouped categories, not @category_types
| admin? | ||
| end | ||
|
|
||
| def recent? |
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.
not using this endpoint anymore
app/policies/application_policy.rb
Outdated
|
|
||
| def index? | ||
| true | ||
| admin? |
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.
defaulting to the most secure first, and then greenlighting everything else in other policies.
this avoids mistakes in forgetting to set admin-only indexes to admin-only. this way we'll need to set not-admin-only to visible.
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.
Good idea.
Can you add index? to the alias_rule manage?. This keeps them all set to admin? in one place and follows the convention from the Action Policy docs.
alias_rule :index?, :new?, :create?, :edit?, :update?, :destroy?, to: :manage?
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.
ooo. great idea! yup, will do that now.
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.
adding both index? and show?
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.
@maebeale might as well!
app/policies/application_policy.rb
Outdated
|
|
||
| def show? | ||
| admin? || record.published? | ||
| admin? |
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.
same thing here -- defaulting to lockdown mode and we'll greenlight access in other policies
|
|
||
| def admin? | ||
| user&.super_user? | ||
| user&.admin? |
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.
trying to remove/minimize super_user from the code, as i'm sure we'll be moving to a different permissioning implementation once we have more roles.
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.
Do you think it makes more sense to have the user permission checked here as this this the authorization framework? The method in User model works but is that the best place?
The hope is that any check we make for an admin? is via action_policy not directly off current_user
I agree only one place for sure if we can help it.
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.
i like better using it here.
and removing all the places we say (...user.super_user or even ...user.admin) and instead use a policy.
| # true | ||
| # end | ||
| # | ||
| def show? |
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.
we don't have UI for non-admin banner show, but, technically we would be fine w users seeing it.
|
|
||
| relation_scope do |relation| | ||
| next relation if admin? | ||
| relation.where(user: user) |
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.
users can only see their own bookmarks on their /personal page
| if turbo_frame_request? | ||
| per_page = params[:number_of_items_per_page].presence || 12 | ||
| unfiltered = current_user.super_user? ? CommunityNews.all : CommunityNews.published | ||
| unfiltered = |
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.
do we still need to do this if we're using scopes in policies?
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.
If we want to display the count of the results vs total. e.g. 5/20 we need the unfiltered number. If we want to keep it simple we could remove the total.
"Total" gets a bit messy. Total of all? total for the current user? Do we include hidden for admin?
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.
yeah, it is getting messy. i think we'd want to say total for the current user (or guest)?
app/models/community_news.rb
Outdated
| scope :community_news_name, ->(community_news_name) { | ||
| community_news_name.present? ? where("community_news.name LIKE ?", "%#{community_news_name}%") : all } | ||
| scope :featured, -> { where(featured: true) } | ||
| scope :public_featured, -> { published.where(public_featured: true) } |
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.
prepending published to all scopes for public_featured and publicly_visible
| </div> | ||
|
|
||
| <div> | ||
| <div class="action-buttons mt-8 flex justify-center gap-3"> |
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.
added this class set to all form action sections
app/views/banners/_form.html.erb
Outdated
| <%= link_to "Cancel", banners_path, class: "btn btn-secondary-outline" %> | ||
|
|
||
| <%= f.button :submit, | ||
| (@banner.new_record? ? "Create Banner" : "Update Banner"), |
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.
don't need conditional text if using f.button :submit and en.yml
| class: "btn btn-danger-outline", | ||
| data: { confirm: "Are you sure you want to delete this banner?" } %> | ||
| <div class="action-buttons mt-8 flex justify-center gap-3"> | ||
| <% if f.object.persisted? && allowed_to?(:destroy?, f.object) %> |
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.
explicitly checking destroy permission before displaying delete button
|
|
||
| <% if @event.errors.any? %> | ||
| <%= render 'shared/errors', resource: @event %> | ||
| <%= render "shared/errors", resource: @event %> |
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.
some ' -> " changes throughout
| <%= f.input :short_name, | ||
| input_html: { readonly: true }, | ||
| as: :string %> | ||
| <% if params[:admin] || !f.object.persisted? %> |
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.
decided to offer an easter egg to change short_name from the UI
|
|
||
| <% | ||
| =begin %> | ||
| <%# begin %> |
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.
not sure why there's begin and end tags in here...
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.
Something was broken for me when I was fixing the workshop promotion.
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.
so it can be removed now?
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.
Yes, just need to check for error's on the page and flow but that can be a separate issue.
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.
i'll leave it in there for you to remove when you're ready
| =end %> | ||
| <%# =end %> | ||
|
|
||
| <div class="my-4"><%= render "assets/form", owner: workshop_idea %></div> |
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.
@jmilljr24 this doesn't seem broken when moved?
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.
In html you are not supposed to have a form nested within a form. It's hard to see on github where the main form ends so I can't tell exactly where you moved it.
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.
yeah, it is within it...
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.
i moved it back out
| project: "Organization" No newline at end of file | ||
| project: "Organization" | ||
| helpers: | ||
| submit: |
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.
this is where all the f.button :submit text will come from now
| @@ -0,0 +1,6 @@ | |||
| class AddPubliclyVisibleToModels < ActiveRecord::Migration[8.1] | |||
| def change | |||
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.
adding publicly_visible to the two help-related tables too
| # --- Traits for type-specific subclasses --- | ||
| factory :primary_asset, class: "PrimaryAsset" | ||
| factory :gallery_assets, class: "GalleryAsset" | ||
| factory :gallery_asset, class: "GalleryAsset" |
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.
factories are always singularly named
spec/factories/events.rb
Outdated
| registration_close_date { 13.days.from_now } | ||
| inactive { false } | ||
| cost_cents { 1099 } | ||
| public { false } |
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.
setting this to public false to start to make tests better match default state of the object
| it "checks authorization via ApplicationPolicy" do | ||
| expect_any_instance_of(ApplicationPolicy) | ||
| .to receive(:index?).and_call_original | ||
| it "checks authorization via TagPolicy" do |
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.
added a TagPolicy, to referring to that now
| visit event_path(event) | ||
|
|
||
| # Title (uses title_with_badges) | ||
| expect(page).to have_css("div.my-3", text: "My Event") |
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.
removing testing on specific css
| end | ||
|
|
||
| # Times block exists | ||
| expect(page).to have_text("Start:") |
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.
this text isn't on the page anymore
| create(:event_registration, event: event, registrant: user) | ||
| end | ||
|
|
||
| it "shows De-register button + registered badge + calendar links" do |
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.
chatgpt changes
|
|
||
| # READONLY FIELDS (since this is used in code, we're not exposing it to the user) | ||
| assert_select "input[name=?][readonly]", "windows_type[short_name]" | ||
| assert_select "input[name=?]", "windows_type[short_name]" |
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.
not readonly when new, since it's a required field
c9ab08f to
ae9b976
Compare
| if turbo_frame_request? | ||
| per_page = params[:number_of_items_per_page].presence || 12 | ||
| unfiltered = current_user.super_user? ? CommunityNews.all : CommunityNews.published | ||
| unfiltered = |
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.
If we want to display the count of the results vs total. e.g. 5/20 we need the unfiltered number. If we want to keep it simple we could remove the total.
"Total" gets a bit messy. Total of all? total for the current user? Do we include hidden for admin?
| @@ -1,4 +1,5 @@ | |||
| class ApplicationController < ActionController::Base | |||
| include ActionPolicy::Controller | |||
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.
| include ActionPolicy::Controller |
Shouldn't need this explicitly. allowed_to? was already working for me and the doc's say its included in ActionController::Base
Were you getting an error without it?
app/policies/application_policy.rb
Outdated
|
|
||
| def index? | ||
| true | ||
| admin? |
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.
Good idea.
Can you add index? to the alias_rule manage?. This keeps them all set to admin? in one place and follows the convention from the Action Policy docs.
alias_rule :index?, :new?, :create?, :edit?, :update?, :destroy?, to: :manage?
|
|
||
| def admin? | ||
| user&.super_user? | ||
| user&.admin? |
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.
Do you think it makes more sense to have the user permission checked here as this this the authorization framework? The method in User model works but is that the best place?
The hope is that any check we make for an admin? is via action_policy not directly off current_user
I agree only one place for sure if we can help it.
|
|
||
| <% | ||
| =begin %> | ||
| <%# begin %> |
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.
Something was broken for me when I was fixing the workshop promotion.
| =end %> | ||
| <%# =end %> | ||
|
|
||
| <div class="my-4"><%= render "assets/form", owner: workshop_idea %></div> |
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.
In html you are not supposed to have a form nested within a form. It's hard to see on github where the main form ends so I can't tell exactly where you moved it.
| hint: "Any tips on how to make this workshop a success") %> | ||
| <% end %> | ||
|
|
||
| <%= render "shared/form_dropdown", form: f, field: :extra_field, label: "Extra Field" do %> |
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.
The only reason I had this at the top was because of the order displayed on the show page. Extra Field is the first thing displayed. We should ask what order they expect.
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.
i want to leave it at the bottom of the edit screen, and still display it at the top on show. then it's not their first instinct, AND, we still allow them to insert something above everything else?
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.
That make sense. There are workshops where they literally have pages worth of content all in "extra_field" which doesn't make sense.
As long as they know where the field will be displayed that make sense to have it as a secondary option.
| included do | ||
| scope :featured, -> { where(featured: true, inactive: false) } | ||
| scope :public_featured, -> { where(public_featured: true, public: true, inactive: false) } | ||
| scope :featured, -> { published.where(featured: true) } |
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.
Thanks for cleaning this up. I wanted to get most of the similar scope into a concern but the inactive vs published on different models side tracked me and this is where I left off.
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.
i'm taking a second pass on all of these booleans and scopes and trying to normalize inactive/published
| per_page = params[:number_of_items_per_page].presence || 12 | ||
| unfiltered = current_user.super_user? ? CommunityNews.all : CommunityNews.published | ||
| unfiltered = | ||
| if current_user&.admin? |
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.
Sorry I missed this.
To use the relation_scope in the policy you need to call authorized_scope(CommunityNews.all)
That will look in the Community News Policy for the relation_scope. authorized_scope allows other options like specifying which policy or a specific named scope withing a policy as well if you need it.
What is the goal of this PR and why is this important?
Improve UX and change policy defaults
allowed_to?will find the right policypublic->publicly_visibleHow did you approach the change?
Anything else to add?