diff --git a/app/controllers/additional_content_boxes_controller.rb b/app/controllers/additional_content_boxes_controller.rb index 973487b86..7908bf7a7 100644 --- a/app/controllers/additional_content_boxes_controller.rb +++ b/app/controllers/additional_content_boxes_controller.rb @@ -1,4 +1,5 @@ class AdditionalContentBoxesController < ApplicationController + # No authorization required for entirely public controller def index article_ids = params[:article_id].split(",") @article = Article.find(article_ids[0]) diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index 3f4052ee8..d9356198f 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -6,26 +6,17 @@ # you're free to overwrite the RESTful controller actions. module Admin class ApplicationController < Administrate::ApplicationController - skip_before_action :verify_authenticity_token - include EnforceAdmin - before_action :authenticate_admin + include Pundit + before_action :authorize_admin - def authenticate_admin - unless current_user_is_admin? - authenticate_or_request_with_http_basic do |username, password| - username == ENV["APP_NAME"] && password == ENV["APP_PASSWORD"] - end - end - end - - # Override this value to specify the number of elements to display at a time - # on index pages. Defaults to 20. - # def records_per_page - # params[:per_page] || 20 - # end def order @_order ||= Administrate::Order.new(params[:order] || "id",params[:direction] || "desc") end + private + + def authorize_admin + authorize :admin, :show? + end end end diff --git a/app/controllers/analytics_controller.rb b/app/controllers/analytics_controller.rb index 3ccae3496..98e761e2a 100644 --- a/app/controllers/analytics_controller.rb +++ b/app/controllers/analytics_controller.rb @@ -2,39 +2,21 @@ class AnalyticsController < ApplicationController caches_action :index, cache_path: Proc.new { "#{request.params}___#{current_user.id}" }, expires_in: 15.minutes + after_action :verify_authorized def index article_ids = analytics_params.split(",") - if has_analytics_privilege?(article_ids.first, current_user) - cache_name = "pageviews-#{article_ids}/dashboard-index" - pageviews = Rails.cache.fetch(cache_name, expires_in: 15.minutes) do - GoogleAnalytics.new(article_ids).get_pageviews - end - render json: pageviews.to_json - else - render json: {} + article_to_check = Article.find_by(id: article_ids.first) + authorize article_to_check, :analytics_index? + cache_name = "pageviews-#{article_ids}/dashboard-index" + pageviews = Rails.cache.fetch(cache_name, expires_in: 15.minutes) do + GoogleAnalytics.new(article_ids).get_pageviews end + render json: pageviews.to_json end private - def has_analytics_privilege?(article_id, current_user) - return false unless current_user - current_user_is_admin? || - current_user_is_author_with_beta_acess?(article_id, current_user) || - current_user_is_org_admin?(article_id, current_user) - end - - def current_user_is_author_with_beta_acess?(article_id, user) - author = Article.find_by_id(article_id)&.user - author == user && user.has_role?(:analytics_beta_tester) - end - - def current_user_is_org_admin?(article_id, user) - org_id = Article.find_by_id(article_id)&.organization_id - user.org_admin && user.organization_id == org_id - end - def analytics_params params.require(:article_ids) end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4bf5c75ec..dec4463a5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,14 +1,8 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception, prepend: true - include EnforceAdmin - include Pundit - # before_action :require_http_auth if ENV["APP_NAME"] == "dev_stage" - - #before_action :customize_params - def require_http_auth authenticate_or_request_with_http_basic do |username, password| username == ENV["APP_NAME"] && password == ENV["APP_PASSWORD"] diff --git a/app/controllers/blocks_controller.rb b/app/controllers/blocks_controller.rb index fb002b600..d6c91d3b6 100644 --- a/app/controllers/blocks_controller.rb +++ b/app/controllers/blocks_controller.rb @@ -1,7 +1,9 @@ class BlocksController < ApplicationController before_action :set_block, only: [:show, :edit, :update, :destroy] + after_action :verify_authorized + # GET /blocks # GET /blocks.json def index @@ -78,4 +80,5 @@ class BlocksController < ApplicationController def set_block @block = Block.find(params[:id]) end + end diff --git a/app/controllers/buffered_articles_controller.rb b/app/controllers/buffered_articles_controller.rb index 26fed2bb9..2797d7386 100644 --- a/app/controllers/buffered_articles_controller.rb +++ b/app/controllers/buffered_articles_controller.rb @@ -1,4 +1,5 @@ class BufferedArticlesController < ApplicationController + # No authorization required for entirely public controller def index @article_urls = buffered_article_urls render json: { diff --git a/app/controllers/concerns/enforce_admin.rb b/app/controllers/concerns/enforce_admin.rb deleted file mode 100644 index b83c4ac69..000000000 --- a/app/controllers/concerns/enforce_admin.rb +++ /dev/null @@ -1,17 +0,0 @@ -module EnforceAdmin - extend ActiveSupport::Concern - - def require_super_admin - return verify_admin_status if current_user - redirect_to "/enter" - end - - def verify_admin_status - return if current_user_is_admin? - redirect_to "/", status: 422 - end - - def current_user_is_admin? - current_user&.has_any_role?(:super_admin, :admin) - end -end diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index cfe241e63..04da56cf6 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -4,7 +4,7 @@ class DashboardsController < ApplicationController after_action :verify_authorized def show - @user = if params[:username] && current_user_is_admin? + @user = if params[:username] && current_user.is_admin? User.find_by_username(params[:username]) else current_user diff --git a/app/controllers/followed_articles_controller.rb b/app/controllers/followed_articles_controller.rb index be7a64013..5bad9c71b 100644 --- a/app/controllers/followed_articles_controller.rb +++ b/app/controllers/followed_articles_controller.rb @@ -1,4 +1,5 @@ class FollowedArticlesController < ApplicationController + # No authorization required for entirely public controller caches_action :index, :cache_path => Proc.new { "followed_articles_#{current_user.id}__#{current_user.updated_at}__#{user_signed_in?.to_s}" }, diff --git a/app/controllers/ga_events_controller.rb b/app/controllers/ga_events_controller.rb index dbe65aa44..cf1d7b42f 100644 --- a/app/controllers/ga_events_controller.rb +++ b/app/controllers/ga_events_controller.rb @@ -1,4 +1,5 @@ class GaEventsController < ApplicationController + # No authorization required for entirely public controller # This controller is for tracking activity when GA script fails # IP is scrambled as to not be persisted to limit fingerprinting abilities on our end. diff --git a/app/controllers/internal/application_controller.rb b/app/controllers/internal/application_controller.rb index 69b88e849..1388af441 100644 --- a/app/controllers/internal/application_controller.rb +++ b/app/controllers/internal/application_controller.rb @@ -1,4 +1,9 @@ class Internal::ApplicationController < ApplicationController - include EnforceAdmin - before_action :require_super_admin + before_action :authorize_admin + + private + + def authorize_admin + authorize :admin, :show? + end end diff --git a/app/controllers/internal/broadcasts_controller.rb b/app/controllers/internal/broadcasts_controller.rb index 080484c07..10d331d03 100644 --- a/app/controllers/internal/broadcasts_controller.rb +++ b/app/controllers/internal/broadcasts_controller.rb @@ -3,26 +3,12 @@ class Internal::BroadcastsController < Internal::ApplicationController def create @broadcast = Broadcast.new(broadcast_params) - if @broadcast.save - # custom notifications not in use yet - # if @broadcast.sent && @broadcast.type_of == "Announcement" - # # only send new notifications for announcements - # # onboarding notifications are automated - # Notification.send_all(@broadcast, @broadcast.type_of) - # end - end redirect_to "/internal/broadcasts" end def update @broadcast = Broadcast.find(params[:id]) @broadcast.update(broadcast_params) - # if @broadcast.save - # if @broadcast.sent && @broadcast.type_of == "Announcement" - # # see create action comments - # Notification.send_all(@broadcast, @broadcast.type_of) - # end - # end redirect_to "/internal/broadcasts" end diff --git a/app/controllers/live_articles_controller.rb b/app/controllers/live_articles_controller.rb index 085fe0b91..c7d7944a0 100644 --- a/app/controllers/live_articles_controller.rb +++ b/app/controllers/live_articles_controller.rb @@ -1,4 +1,5 @@ class LiveArticlesController < ApplicationController + # No authorization required for entirely public controller before_action :set_cache_control_headers, only: [:index] def index diff --git a/app/controllers/moderations_controller.rb b/app/controllers/moderations_controller.rb index 79001d591..222a8b72b 100644 --- a/app/controllers/moderations_controller.rb +++ b/app/controllers/moderations_controller.rb @@ -1,20 +1,15 @@ class ModerationsController < ApplicationController - - before_action :check_trusted + after_action :verify_authorized def article + authorize(User, :moderation_routes?) @moderatable = Article.find_by_slug(params[:slug]) render template: "moderations/mod" end def comment + authorize(User, :moderation_routes?) @moderatable = Comment.find(params[:id_code].to_i(26)) render template: "moderations/mod" end - - private - - def check_trusted - not_found unless current_user&.has_role?(:trusted) - end end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 46559d835..0d41186fa 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -4,7 +4,7 @@ class NotificationsController < ApplicationController def index if user_signed_in? @notifications_index = true - @user = if params[:username] && current_user_is_admin? + @user = if params[:username] && current_user.is_admin? User.find_by_username(params[:username]) else current_user diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 86ba22efa..55da2a686 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -1,11 +1,13 @@ class OrganizationsController < ApplicationController before_action :authenticate_user!, except: [:show] + after_action :verify_authorized def create @tab = "organization" @user = current_user @tab_list = @user.settings_tab_list @organization = Organization.new(organization_params) + authorize @organization if @organization.save current_user.update(organization_id: @organization.id, org_admin: true) redirect_to "/settings/organization", notice: @@ -21,8 +23,9 @@ class OrganizationsController < ApplicationController @user = current_user @tab = "organization" @tab_list = @user.settings_tab_list - raise unless @user.org_admin @organization = @user.organization + authorize @organization + if @organization.update(organization_params) redirect_to "/settings/organization", notice: "Your organization was successfully updated." else @@ -33,6 +36,7 @@ class OrganizationsController < ApplicationController def generate_new_secret raise unless current_user.org_admin @organization = current_user.organization + authorize @organization @organization.secret = @organization.generated_random_secret @organization.save redirect_to "/settings/organization", notice: "Your org secret was updated" diff --git a/app/controllers/podcast_episodes_controller.rb b/app/controllers/podcast_episodes_controller.rb index 17b8b6434..1fd943f91 100644 --- a/app/controllers/podcast_episodes_controller.rb +++ b/app/controllers/podcast_episodes_controller.rb @@ -1,7 +1,6 @@ class PodcastEpisodesController < ApplicationController - - before_action :require_http_auth, only: [:edit,:update,:admin] - before_action :set_cache_control_headers, only: [:index, :show] + # No authorization required for entirely public controller + before_action :set_cache_control_headers, only: [:index] def index @podcast_index = true diff --git a/app/controllers/social_previews_controller.rb b/app/controllers/social_previews_controller.rb index c735cccb1..67ac211b5 100644 --- a/app/controllers/social_previews_controller.rb +++ b/app/controllers/social_previews_controller.rb @@ -1,4 +1,5 @@ class SocialPreviewsController < ApplicationController + # No authorization required for entirely public controller def article @article = Article.find(params[:id]) @@ -20,5 +21,4 @@ class SocialPreviewsController < ApplicationController @tag = Tag.find(params[:id]) || not_found render layout: false end - -end \ No newline at end of file +end diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb index 0ce474cf6..a4fd60620 100644 --- a/app/controllers/stories_controller.rb +++ b/app/controllers/stories_controller.rb @@ -89,8 +89,7 @@ class StoriesController < ApplicationController @stories = @stories.where(approved: true) end - @stories = stories_by_timeframe - + @stories = stories_by_timeframe @stories = @stories.decorate @featured_story = Article.new diff --git a/app/models/user.rb b/app/models/user.rb index d64a93b6a..c2a90c40e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -217,6 +217,10 @@ class User < ApplicationRecord has_role? :warned end + def is_admin? + has_role?(:super_admin) + end + def trusted Rails.cache.fetch("user-#{id}/has_trusted_role", expires_in: 200.hours) do has_role? :trusted @@ -246,6 +250,10 @@ class User < ApplicationRecord has_any_role?(:workshop_pass, :level_3_member, :level_4_member, :triple_unicorn_member) end + def is_org_admin?(organization) + user.org_admin && user.organization_id == organization.id + end + def unique_including_orgs errors.add(:username, "is taken.") if Organization.find_by_slug(username) end @@ -264,7 +272,7 @@ class User < ApplicationRecord handle_asynchronously :subscribe_to_mailchimp_newsletter def can_view_analytics? - has_any_role?(:super_admin, :admin, :analytics_beta_tester) + has_any_role?(:super_admin, :analytics_beta_tester) end def a_sustaining_member? @@ -293,6 +301,7 @@ class User < ApplicationRecord end + private def unescape_summary diff --git a/app/policies/admin_policy.rb b/app/policies/admin_policy.rb new file mode 100644 index 000000000..621181143 --- /dev/null +++ b/app/policies/admin_policy.rb @@ -0,0 +1,5 @@ +class AdminPolicy < ApplicationPolicy + def show? + user_is_admin? + end +end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 2cc6e0854..0a6245c2d 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -54,10 +54,10 @@ class ApplicationPolicy end def user_is_admin? - user.has_any_role?(:super_admin, :admin) + user.has_role?(:super_admin) end def user_is_banned? - user.has_role?(:banned) + user.banned end end diff --git a/app/policies/article_policy.rb b/app/policies/article_policy.rb index 3e1df7bf8..9c15c6029 100644 --- a/app/policies/article_policy.rb +++ b/app/policies/article_policy.rb @@ -23,6 +23,10 @@ class ArticlePolicy < ApplicationPolicy true end + def analytics_index? + (user_is_author? && user_can_view_analytics?) || user_is_org_admin? + end + def permitted_attributes %i[title body_html body_markdown user_id main_image published description allow_small_edits allow_big_edits tag_list publish_under_org @@ -39,7 +43,7 @@ class ArticlePolicy < ApplicationPolicy user.org_admin && user.organization_id == record.organization_id end - def user_is_banned? - user.has_role?(:banned) + def user_can_view_analytics? + user.can_view_analytics? end end diff --git a/app/policies/block_policy.rb b/app/policies/block_policy.rb index 4b1b06e30..1d0e6642a 100644 --- a/app/policies/block_policy.rb +++ b/app/policies/block_policy.rb @@ -30,10 +30,4 @@ class BlockPolicy < ApplicationPolicy def permitted_attributes %i[input_html input_css input_javascript featured index_position publish_now] end - - private - - def user_is_admin? - user.has_role? :super_admin - end end diff --git a/app/policies/comment_policy.rb b/app/policies/comment_policy.rb index 13a10a0ad..844fe25c1 100644 --- a/app/policies/comment_policy.rb +++ b/app/policies/comment_policy.rb @@ -40,8 +40,4 @@ class CommentPolicy < ApplicationPolicy def user_is_author? record.user_id == user.id end - - def user_is_banned? - user.has_role?(:banned) - end end diff --git a/app/policies/follow_policy.rb b/app/policies/follow_policy.rb index 36065b055..b86c86f91 100644 --- a/app/policies/follow_policy.rb +++ b/app/policies/follow_policy.rb @@ -1,5 +1,5 @@ class FollowPolicy < ApplicationPolicy def create? - !user.banned + !user_is_banned? end end diff --git a/app/policies/github_repo_policy.rb b/app/policies/github_repo_policy.rb index 6daf34b7a..52a105f74 100644 --- a/app/policies/github_repo_policy.rb +++ b/app/policies/github_repo_policy.rb @@ -1,10 +1,10 @@ class GithubRepoPolicy < ApplicationPolicy def create? - !user.banned + !user_is_banned? end def update? - !user.banned && user_is_owner? + !user_is_banned? && user_is_owner? end def permitted_attributes diff --git a/app/policies/image_upload_policy.rb b/app/policies/image_upload_policy.rb index 7de1a1d0d..693632b55 100644 --- a/app/policies/image_upload_policy.rb +++ b/app/policies/image_upload_policy.rb @@ -1,5 +1,5 @@ class ImageUploadPolicy < ApplicationPolicy def create? - !user.banned + !user_is_banned? end end diff --git a/app/policies/message_policy.rb b/app/policies/message_policy.rb index 8594b9879..3f38f236c 100644 --- a/app/policies/message_policy.rb +++ b/app/policies/message_policy.rb @@ -2,10 +2,4 @@ class MessagePolicy < ApplicationPolicy def create? !user_is_banned? end - - private - - def user_is_banned? - user&.has_role?(:banned) - end end diff --git a/app/policies/organization_policy.rb b/app/policies/organization_policy.rb new file mode 100644 index 000000000..541b1bd26 --- /dev/null +++ b/app/policies/organization_policy.rb @@ -0,0 +1,13 @@ +class OrganizationPolicy < ApplicationPolicy + def create? + !user.banned + end + + def update? + user.is_org_admin?(record) + end + + def generate_new_secret? + update? + end +end diff --git a/app/policies/tag_policy.rb b/app/policies/tag_policy.rb index 2c9796e9a..c95f6fd1e 100644 --- a/app/policies/tag_policy.rb +++ b/app/policies/tag_policy.rb @@ -14,7 +14,7 @@ class TagPolicy < ApplicationPolicy private def has_mod_permission? - user.has_role?(:super_admin) || + user_is_admin? || user.has_role?(:tag_moderator, record) end end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 40dffc2e5..f62b8e403 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -35,6 +35,10 @@ class UserPolicy < ApplicationPolicy current_user? || user_is_admin? end + def moderation_routes? + user.has_role?(:trusted) && !user.banned + end + private def within_the_same_org? @@ -48,8 +52,4 @@ class UserPolicy < ApplicationPolicy def current_user? user == record end - - def user_is_admin? - user.has_role? :super_admin - end end diff --git a/app/views/dashboards/show.html.erb b/app/views/dashboards/show.html.erb index 02beb5d54..7e46bd7be 100644 --- a/app/views/dashboards/show.html.erb +++ b/app/views/dashboards/show.html.erb @@ -3,8 +3,8 @@