diff --git a/app/controllers/admin/admin_controller.rb b/app/controllers/admin/admin_controller.rb index f4ea193..780defc 100644 --- a/app/controllers/admin/admin_controller.rb +++ b/app/controllers/admin/admin_controller.rb @@ -2,13 +2,22 @@ class Admin::AdminController < ApplicationController layout 'admin' + # The admin has two roles: Admin, who gets everything, and Guest (the `user` + # role), who gets a read-only slice -- the analytics dashboard and the + # published leaderboard. Listed by controller name. + GUEST_SECTIONS = %w[analytics leaderboard].freeze + + # The nav sections in the order they appear in the sidebar. + ADMIN_SECTIONS = %i[analytics leaderboard nodes assets].freeze + before_action :authenticate_user! - before_action :only_admin! + before_action :only_permitted_section! before_action :set_locale_to_default helper_method :current_user helper_method :user_signed_in? helper_method :form_locale, :available_locales + helper_method :admin?, :permitted_admin_sections # DELETE admin/cache/clear def clear_cache @@ -50,10 +59,41 @@ private end + def admin? + current_user&.admin_role? + end + + + # What a Guest is allowed to open. Anything else bounces them to analytics + # rather than out of the admin entirely, so every link in the nav they see + # actually works and a stray URL doesn't log them out. + def only_permitted_section! + return if admin? + return if GUEST_SECTIONS.include?(controller_name) + + bounce_guest! + end + + + # For the handful of actions inside a Guest section that still change + # something -- clearing a cache, say. Guests may look, not touch, so this + # cannot lean on the section check: the section itself is permitted. def only_admin! - unless current_user&.admin_role? - redirect_to root_path - end + return if admin? + + bounce_guest! + end + + + def bounce_guest! + redirect_to admin_analytics_path(locale: params[:locale] || I18n.default_locale) + end + + + def permitted_admin_sections + return ADMIN_SECTIONS if admin? + + ADMIN_SECTIONS.select { |section| GUEST_SECTIONS.include?(section.to_s) } end diff --git a/app/controllers/admin/leaderboard_controller.rb b/app/controllers/admin/leaderboard_controller.rb index f1949f0..bdf2846 100644 --- a/app/controllers/admin/leaderboard_controller.rb +++ b/app/controllers/admin/leaderboard_controller.rb @@ -6,6 +6,9 @@ # preview of what the next API call will publish, and says so. class Admin::LeaderboardController < Admin::AdminController + # Guests may read the leaderboard but not drop what the API is serving. + before_action :only_admin!, only: :expire + # GET /admin/:locale/leaderboard def index @published = LeaderboardPayload.published diff --git a/app/controllers/admin/sessions_controller.rb b/app/controllers/admin/sessions_controller.rb index ab8c1d1..c1f0e86 100644 --- a/app/controllers/admin/sessions_controller.rb +++ b/app/controllers/admin/sessions_controller.rb @@ -3,7 +3,7 @@ class Admin::SessionsController < Admin::AdminController layout 'sessions' skip_before_action :authenticate_user!, except: %i[destroy] - skip_before_action :only_admin! + skip_before_action :only_permitted_section! def index render action: 'new' diff --git a/app/views/admin/leaderboard/index.html.erb b/app/views/admin/leaderboard/index.html.erb index 037bb10..5cc9cca 100644 --- a/app/views/admin/leaderboard/index.html.erb +++ b/app/views/admin/leaderboard/index.html.erb @@ -7,10 +7,12 @@

<%= yield(:title) %>

- <%= link_to "Clear cache", - admin_leaderboard_cache_path, - class: "analytics-period", - data: { turbo_method: :delete, turbo_frame: "main" } %> + <% if admin? %> + <%= link_to "Clear cache", + admin_leaderboard_cache_path, + class: "analytics-period", + data: { turbo_method: :delete, turbo_frame: "main" } %> + <% end %>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index dd1815c..e582eca 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -15,7 +15,7 @@