Use Rolify for admin and moderator roles
This commit is contained in:
parent
a0c9641994
commit
946bb3ae9d
2
Gemfile
2
Gemfile
|
@ -42,6 +42,8 @@ gem 'tiny-color-rails'
|
||||||
gem 'jquery-minicolors-rails'
|
gem 'jquery-minicolors-rails'
|
||||||
gem 'colorize'
|
gem 'colorize'
|
||||||
|
|
||||||
|
gem "rolify", "~> 5.2"
|
||||||
|
|
||||||
source "https://rails-assets.org" do
|
source "https://rails-assets.org" do
|
||||||
gem 'rails-assets-growl'
|
gem 'rails-assets-growl'
|
||||||
gem 'rails-assets-jquery', '~> 2.2.0'
|
gem 'rails-assets-jquery', '~> 2.2.0'
|
||||||
|
|
|
@ -382,6 +382,7 @@ GEM
|
||||||
responders (3.0.0)
|
responders (3.0.0)
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.0)
|
||||||
railties (>= 5.0)
|
railties (>= 5.0)
|
||||||
|
rolify (5.2.0)
|
||||||
rspec-core (3.9.1)
|
rspec-core (3.9.1)
|
||||||
rspec-support (~> 3.9.1)
|
rspec-support (~> 3.9.1)
|
||||||
rspec-expectations (3.9.1)
|
rspec-expectations (3.9.1)
|
||||||
|
@ -554,6 +555,7 @@ DEPENDENCIES
|
||||||
rake
|
rake
|
||||||
redcarpet
|
redcarpet
|
||||||
redis
|
redis
|
||||||
|
rolify (~> 5.2)
|
||||||
rspec-rails (~> 3.9)
|
rspec-rails (~> 3.9)
|
||||||
ruby-progressbar
|
ruby-progressbar
|
||||||
sanitize
|
sanitize
|
||||||
|
|
52
Rakefile
52
Rakefile
|
@ -105,44 +105,48 @@ namespace :justask do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Gives admin status to an user."
|
desc "Gives admin status to a user."
|
||||||
task :admin, [:screen_name] => :environment do |t, args|
|
task :admin, [:screen_name] => :environment do |t, args|
|
||||||
fail "screen name required" if args[:screen_name].nil?
|
abort "screen name required" if args[:screen_name].nil?
|
||||||
|
|
||||||
user = User.find_by_screen_name(args[:screen_name])
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
fail "user #{args[:screen_name]} not found" if user.nil?
|
abort "user #{args[:screen_name]} not found" if user.nil?
|
||||||
user.admin = true
|
|
||||||
user.save!
|
user.add_role :administrator
|
||||||
puts "#{user.screen_name} is now an admin."
|
puts "#{user.screen_name} is now an administrator."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Removes admin status from an user."
|
desc "Removes admin status from a user."
|
||||||
task :deadmin, [:screen_name] => :environment do |t, args|
|
task :deadmin, [:screen_name] => :environment do |t, args|
|
||||||
fail "screen name required" if args[:screen_name].nil?
|
abort "screen name required" if args[:screen_name].nil?
|
||||||
|
|
||||||
user = User.find_by_screen_name(args[:screen_name])
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
fail "user #{args[:screen_name]} not found" if user.nil?
|
abort "user #{args[:screen_name]} not found" if user.nil?
|
||||||
user.admin = false
|
|
||||||
user.save!
|
user.remove_role :administrator
|
||||||
puts "#{user.screen_name} is no longer an admin."
|
puts "#{user.screen_name} is no longer an administrator."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Gives moderator status to an user."
|
desc "Gives moderator status to a user."
|
||||||
task :mod, [:screen_name] => :environment do |t, args|
|
task :mod, [:screen_name] => :environment do |t, args|
|
||||||
fail "screen name required" if args[:screen_name].nil?
|
abort "screen name required" if args[:screen_name].nil?
|
||||||
|
|
||||||
user = User.find_by_screen_name(args[:screen_name])
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
fail "user #{args[:screen_name]} not found" if user.nil?
|
abort "user #{args[:screen_name]} not found" if user.nil?
|
||||||
user.moderator = true
|
|
||||||
user.save!
|
user.add_role :moderator
|
||||||
puts "#{user.screen_name} is now an moderator."
|
puts "#{user.screen_name} is now a moderator."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Removes moderator status from an user."
|
desc "Removes moderator status from a user."
|
||||||
task :demod, [:screen_name] => :environment do |t, args|
|
task :demod, [:screen_name] => :environment do |t, args|
|
||||||
fail "screen name required" if args[:screen_name].nil?
|
abort "screen name required" if args[:screen_name].nil?
|
||||||
|
|
||||||
user = User.find_by_screen_name(args[:screen_name])
|
user = User.find_by_screen_name(args[:screen_name])
|
||||||
fail "user #{args[:screen_name]} not found" if user.nil?
|
abort "user #{args[:screen_name]} not found" if user.nil?
|
||||||
user.moderator = false
|
|
||||||
user.save!
|
user.remove_role :moderator
|
||||||
puts "#{user.screen_name} is no longer an moderator."
|
puts "#{user.screen_name} is no longer a moderator."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Hits an user with the banhammer."
|
desc "Hits an user with the banhammer."
|
||||||
|
|
|
@ -125,9 +125,9 @@ class Ajax::ModerationController < ApplicationController
|
||||||
unban = params[:ban] == "0"
|
unban = params[:ban] == "0"
|
||||||
perma = params[:permaban] == "1"
|
perma = params[:permaban] == "1"
|
||||||
|
|
||||||
buntil = DateTime.strptime params[:until], "%m/%d/%Y %I:%M %p" unless unban or perma
|
buntil = DateTime.strptime params[:until], "%m/%d/%Y %I:%M %p" unless unban || perma
|
||||||
|
|
||||||
if not unban and target.admin?
|
if !unban && target.has_role?(:administrator)
|
||||||
@status = :nopriv
|
@status = :nopriv
|
||||||
@message = I18n.t('messages.moderation.ban.nopriv')
|
@message = I18n.t('messages.moderation.ban.nopriv')
|
||||||
@success = false
|
@success = false
|
||||||
|
@ -166,7 +166,7 @@ class Ajax::ModerationController < ApplicationController
|
||||||
@message = I18n.t('messages.moderation.privilege.nope')
|
@message = I18n.t('messages.moderation.privilege.nope')
|
||||||
return unless %w(blogger supporter moderator admin contributor translator).include? params[:type].downcase
|
return unless %w(blogger supporter moderator admin contributor translator).include? params[:type].downcase
|
||||||
|
|
||||||
if %w(supporter moderator admin).include?(params[:type].downcase) and !current_user.admin?
|
if %w(supporter moderator admin).include?(params[:type].downcase) && !current_user.has_role?(:administrator)
|
||||||
@status = :nopriv
|
@status = :nopriv
|
||||||
@message = I18n.t('messages.moderation.privilege.nopriv')
|
@message = I18n.t('messages.moderation.privilege.nopriv')
|
||||||
@success = false
|
@success = false
|
||||||
|
@ -174,7 +174,9 @@ class Ajax::ModerationController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@checked = status
|
@checked = status
|
||||||
case params[:type].downcase
|
type = params[:type].downcase
|
||||||
|
target_role = {"admin" => "administrator"}.fetch(type, type).to_sym
|
||||||
|
case type
|
||||||
when 'blogger'
|
when 'blogger'
|
||||||
target_user.blogger = status
|
target_user.blogger = status
|
||||||
when 'contributor'
|
when 'contributor'
|
||||||
|
@ -183,10 +185,12 @@ class Ajax::ModerationController < ApplicationController
|
||||||
target_user.translator = status
|
target_user.translator = status
|
||||||
when 'supporter'
|
when 'supporter'
|
||||||
target_user.supporter = status
|
target_user.supporter = status
|
||||||
when 'moderator'
|
when 'moderator', 'admin'
|
||||||
target_user.moderator = status
|
if status
|
||||||
when 'admin'
|
target_user.add_role target_role
|
||||||
target_user.admin = status
|
else
|
||||||
|
target_user.remove_role target_role
|
||||||
|
end
|
||||||
end
|
end
|
||||||
target_user.save!
|
target_user.save!
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Role < ApplicationRecord
|
||||||
|
has_and_belongs_to_many :users, join_table: :users_roles
|
||||||
|
|
||||||
|
belongs_to :resource,
|
||||||
|
polymorphic: true,
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
validates :resource_type,
|
||||||
|
inclusion: { in: Rolify.resource_types },
|
||||||
|
allow_nil: true
|
||||||
|
|
||||||
|
scopify
|
||||||
|
end
|
|
@ -5,6 +5,8 @@ class User < ApplicationRecord
|
||||||
:recoverable, :rememberable, :trackable,
|
:recoverable, :rememberable, :trackable,
|
||||||
:validatable, :confirmable, :authentication_keys => [:login]
|
:validatable, :confirmable, :authentication_keys => [:login]
|
||||||
|
|
||||||
|
rolify
|
||||||
|
|
||||||
# attr_accessor :login
|
# attr_accessor :login
|
||||||
|
|
||||||
has_many :questions, dependent: :destroy
|
has_many :questions, dependent: :destroy
|
||||||
|
@ -183,7 +185,7 @@ class User < ApplicationRecord
|
||||||
|
|
||||||
# @return [Boolean] is the user a moderator?
|
# @return [Boolean] is the user a moderator?
|
||||||
def mod?
|
def mod?
|
||||||
self.moderator? || self.admin?
|
has_role?(:moderator) || has_role?(:administrator)
|
||||||
end
|
end
|
||||||
|
|
||||||
# region stuff used for reporting/moderation
|
# region stuff used for reporting/moderation
|
||||||
|
@ -258,4 +260,10 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
!self.export_processing
|
!self.export_processing
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# %w[admin moderator].each do |m|
|
||||||
|
# define_method(m) { raise "not allowed: #{m}" }
|
||||||
|
# define_method(m+??) { raise "not allowed: #{m}?"}
|
||||||
|
# define_method(m+?=) { |*a| raise "not allowed: #{m}="}
|
||||||
|
# end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
%i.fa.fa-fw.fa-cog
|
%i.fa.fa-fw.fa-cog
|
||||||
= t('views.navigation.settings')
|
= t('views.navigation.settings')
|
||||||
%li.divider
|
%li.divider
|
||||||
- if current_user.admin?
|
- if current_user.has_role?(:administrator)
|
||||||
%li
|
%li
|
||||||
%a{href: rails_admin_path}
|
%a{href: rails_admin_path}
|
||||||
%i.fa.fa-fw.fa-cogs
|
%i.fa.fa-fw.fa-cogs
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
%a{href: '#', data: { target: "#modal-privileges", toggle: :modal }}
|
%a{href: '#', data: { target: "#modal-privileges", toggle: :modal }}
|
||||||
%i.fa.fa-wrench
|
%i.fa.fa-wrench
|
||||||
= raw t('views.actions.privilege', user: user.screen_name)
|
= raw t('views.actions.privilege', user: user.screen_name)
|
||||||
- unless user.admin?
|
- unless user.has_role?(:administrator)
|
||||||
%li
|
%li
|
||||||
%a{href: '#', data: { target: "#modal-ban", toggle: :modal }}
|
%a{href: '#', data: { target: "#modal-ban", toggle: :modal }}
|
||||||
%i.fa.fa-ban
|
%i.fa.fa-ban
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
= render 'user/modal_privileges_item', privilege: 'blogger', description: t('views.modal.privilege.blogger'), user: @user
|
= render 'user/modal_privileges_item', privilege: 'blogger', description: t('views.modal.privilege.blogger'), user: @user
|
||||||
= render 'user/modal_privileges_item', privilege: 'contributor', description: t('views.modal.privilege.contributor'), user: @user
|
= render 'user/modal_privileges_item', privilege: 'contributor', description: t('views.modal.privilege.contributor'), user: @user
|
||||||
= render 'user/modal_privileges_item', privilege: 'translator', description: t('views.modal.privilege.translator'), user: @user
|
= render 'user/modal_privileges_item', privilege: 'translator', description: t('views.modal.privilege.translator'), user: @user
|
||||||
- if current_user.admin?
|
- if current_user.has_role?(:administrator)
|
||||||
= render 'user/modal_privileges_item', privilege: 'supporter', description: t('views.modal.privilege.supporter'), user: @user
|
= render 'user/modal_privileges_item', privilege: 'supporter', description: t('views.modal.privilege.supporter'), user: @user
|
||||||
= render 'user/modal_privileges_item', privilege: 'moderator', description: t('views.modal.privilege.moderator'),user: @user
|
= render 'user/modal_privileges_item', privilege: 'moderator', description: t('views.modal.privilege.moderator'),user: @user
|
||||||
= render 'user/modal_privileges_item', privilege: 'admin', description: t('views.modal.privilege.admin'), user: @user
|
= render 'user/modal_privileges_item', privilege: 'admin', description: t('views.modal.privilege.admin'), user: @user
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
- description ||= ''
|
- description ||= ''
|
||||||
|
- role_mapping = {"admin" => "administrator"}
|
||||||
|
- requires_role = %w[admin moderator].include?(privilege)
|
||||||
|
- checked = requires_role ? user.has_role?(role_mapping.fetch(privilege, privilege).to_sym) : user.public_send("#{privilege}?")
|
||||||
%li.list-group-item{id: "privilege-#{privilege}"}
|
%li.list-group-item{id: "privilege-#{privilege}"}
|
||||||
.media
|
.media
|
||||||
.pull-left.j2-table
|
.pull-left.j2-table
|
||||||
%input.input--center{type: :checkbox, name: 'check-your-privileges', data: { type: privilege, user: user.screen_name }, checked: user.send("#{privilege}?"), autocomplete: 'off'}
|
%input.input--center{type: :checkbox, name: 'check-your-privileges', data: { type: privilege, user: user.screen_name }, checked: checked, autocomplete: 'off'}
|
||||||
.media-body
|
.media-body
|
||||||
.list-group-item-heading= privilege.capitalize
|
.list-group-item-heading= privilege.capitalize
|
||||||
- unless description.blank?
|
- unless description.blank?
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
.panel.panel-default#profile
|
.panel.panel-default#profile
|
||||||
%img.profile--avatar{src: @user.profile_picture.url(:large)}
|
%img.profile--avatar{src: @user.profile_picture.url(:large)}
|
||||||
- if user_signed_in? && current_user.admin?
|
- if user_signed_in? && current_user.has_role?(:administrator)
|
||||||
- if @user.admin?
|
- if @user.has_role?(:administrator)
|
||||||
.profile--panel-badge.panel-badge-danger
|
.profile--panel-badge.panel-badge-danger
|
||||||
%i.fa.fa-flask
|
%i.fa.fa-flask
|
||||||
= t 'views.user.title.admin'
|
= t 'views.user.title.admin'
|
||||||
- if @user.moderator?
|
- if @user.has_role?(:moderator)
|
||||||
.profile--panel-badge.panel-badge-success
|
.profile--panel-badge.panel-badge-success
|
||||||
%i.fa.fa-users
|
%i.fa.fa-users
|
||||||
= t 'views.user.title.moderator'
|
= t 'views.user.title.moderator'
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
%p.data-heading Admin
|
%p.data-heading Admin
|
||||||
%p
|
%p
|
||||||
- if current_user.admin?
|
- if current_user.has_role?(:administrator)
|
||||||
%span.label.label-success
|
%span.label.label-success
|
||||||
%i.fa.fa-fw.fa-check
|
%i.fa.fa-fw.fa-check
|
||||||
- else
|
- else
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# workaround to get pagination right
|
# workaround to get pagination right
|
||||||
if defined? WillPaginate
|
if defined? WillPaginate
|
||||||
Kaminari.configure do |config|
|
Kaminari.configure do |config|
|
||||||
|
@ -6,12 +8,11 @@ if defined? WillPaginate
|
||||||
end
|
end
|
||||||
|
|
||||||
RailsAdmin.config do |config|
|
RailsAdmin.config do |config|
|
||||||
|
|
||||||
config.main_app_name = ['justask', 'Kontrollzentrum']
|
config.main_app_name = ['justask', 'Kontrollzentrum']
|
||||||
|
|
||||||
## == Authentication ==
|
## == Authentication ==
|
||||||
config.authenticate_with do
|
config.authenticate_with do
|
||||||
redirect_to main_app.root_path unless current_user.try :admin?
|
redirect_to main_app.root_path unless current_user&.has_role?(:administrator)
|
||||||
end
|
end
|
||||||
config.current_user_method(&:current_user)
|
config.current_user_method(&:current_user)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
Rolify.configure do |config|
|
||||||
|
# By default ORM adapter is ActiveRecord. uncomment to use mongoid
|
||||||
|
# config.use_mongoid
|
||||||
|
|
||||||
|
# Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false
|
||||||
|
# config.use_dynamic_shortcuts
|
||||||
|
|
||||||
|
# Configuration to remove roles from database once the last resource is removed. Default is: true
|
||||||
|
config.remove_role_if_empty = false
|
||||||
|
end
|
|
@ -2,19 +2,19 @@ require 'sidekiq/web'
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
start = Time.now
|
start = Time.now
|
||||||
|
|
||||||
# Admin panel
|
|
||||||
mount RailsAdmin::Engine => '/justask_admin', as: 'rails_admin'
|
|
||||||
|
|
||||||
# Sidekiq
|
# Sidekiq
|
||||||
constraints ->(req) { req.env["warden"].authenticate?(scope: :user) &&
|
constraints ->(req) { req.env["warden"].authenticate?(scope: :user) &&
|
||||||
req.env['warden'].user.admin? } do
|
req.env["warden"].user.has_role?(:administrator) } do
|
||||||
|
# Admin panel
|
||||||
|
mount RailsAdmin::Engine => "/justask_admin", as: "rails_admin"
|
||||||
|
|
||||||
mount Sidekiq::Web, at: "/sidekiq"
|
mount Sidekiq::Web, at: "/sidekiq"
|
||||||
mount PgHero::Engine, at: "/pghero", as: 'pghero'
|
mount PgHero::Engine, at: "/pghero", as: "pghero"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Moderation panel
|
# Moderation panel
|
||||||
constraints ->(req) { req.env['warden'].authenticate?(scope: :user) &&
|
constraints ->(req) { req.env["warden"].authenticate?(scope: :user) &&
|
||||||
(req.env['warden'].user.mod?) } do
|
req.env["warden"].user.mod? } do
|
||||||
match '/moderation/priority(/:user_id)', to: 'moderation#priority', via: :get, as: :moderation_priority
|
match '/moderation/priority(/:user_id)', to: 'moderation#priority', via: :get, as: :moderation_priority
|
||||||
match '/moderation/ip/:user_id', to: 'moderation#ip', via: :get, as: :moderation_ip
|
match '/moderation/ip/:user_id', to: 'moderation#ip', via: :get, as: :moderation_ip
|
||||||
match '/moderation(/:type)', to: 'moderation#index', via: :get, as: :moderation, defaults: {type: 'all'}
|
match '/moderation(/:type)', to: 'moderation#index', via: :get, as: :moderation, defaults: {type: 'all'}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RolifyCreateRoles < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
create_table(:roles) do |t|
|
||||||
|
t.string :name
|
||||||
|
t.references :resource, polymorphic: true
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table(:users_roles, id: false) do |t|
|
||||||
|
t.references :user
|
||||||
|
t.references :role
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index(:roles, %i[name resource_type resource_id])
|
||||||
|
add_index(:users_roles, %i[user_id role_id])
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CreateInitialRoles < ActiveRecord::Migration[5.2]
|
||||||
|
def up
|
||||||
|
%w[Administrator Moderator].each do |role|
|
||||||
|
Role.where(name: role.parameterize).first_or_create
|
||||||
|
end
|
||||||
|
|
||||||
|
{
|
||||||
|
admin: :administrator,
|
||||||
|
moderator: :moderator
|
||||||
|
}.each do |legacy_role, new_role|
|
||||||
|
User.where(legacy_role => true).each do |u|
|
||||||
|
puts "-- migrating #{u.screen_name} (#{u.id}) from field:#{legacy_role} to role:#{new_role}"
|
||||||
|
u.add_role new_role
|
||||||
|
u.public_send("#{legacy_role}=", false)
|
||||||
|
u.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
{
|
||||||
|
administrator: :admin,
|
||||||
|
moderator: :moderator
|
||||||
|
}.each do |new_role, legacy_role|
|
||||||
|
User.with_role(new_role).each do |u|
|
||||||
|
puts "-- migrating #{u.screen_name} (#{u.id}) from role:#{new_role} to field:#{legacy_role}"
|
||||||
|
u.public_send("#{legacy_role}=", true)
|
||||||
|
u.save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
20
db/schema.rb
20
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2016_01_05_165913) do
|
ActiveRecord::Schema.define(version: 2020_04_19_185535) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -137,6 +137,16 @@ ActiveRecord::Schema.define(version: 2016_01_05_165913) do
|
||||||
t.string "reason"
|
t.string "reason"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "roles", force: :cascade do |t|
|
||||||
|
t.string "name"
|
||||||
|
t.string "resource_type"
|
||||||
|
t.bigint "resource_id"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"
|
||||||
|
t.index ["resource_type", "resource_id"], name: "index_roles_on_resource_type_and_resource_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "services", id: :serial, force: :cascade do |t|
|
create_table "services", id: :serial, force: :cascade do |t|
|
||||||
t.string "type", null: false
|
t.string "type", null: false
|
||||||
t.integer "user_id", null: false
|
t.integer "user_id", null: false
|
||||||
|
@ -270,4 +280,12 @@ ActiveRecord::Schema.define(version: 2016_01_05_165913) do
|
||||||
t.index ["screen_name"], name: "index_users_on_screen_name", unique: true
|
t.index ["screen_name"], name: "index_users_on_screen_name", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "users_roles", id: false, force: :cascade do |t|
|
||||||
|
t.bigint "user_id"
|
||||||
|
t.bigint "role_id"
|
||||||
|
t.index ["role_id"], name: "index_users_roles_on_role_id"
|
||||||
|
t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id"
|
||||||
|
t.index ["user_id"], name: "index_users_roles_on_user_id"
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,3 +5,7 @@
|
||||||
#
|
#
|
||||||
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
||||||
# Mayor.create(name: 'Emanuel', city: cities.first)
|
# Mayor.create(name: 'Emanuel', city: cities.first)
|
||||||
|
|
||||||
|
%w[Administrator Moderator].each do |role|
|
||||||
|
Role.where(name: role.parameterize).first_or_create
|
||||||
|
end
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'json'
|
require 'json'
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
require 'httparty'
|
require 'httparty'
|
||||||
require 'securerandom'
|
require 'securerandom'
|
||||||
|
|
||||||
class Exporter
|
class Exporter
|
||||||
|
EXPORT_ROLES = [:administrator, :moderator].freeze
|
||||||
|
|
||||||
def initialize(user)
|
def initialize(user)
|
||||||
@user = user
|
@user = user
|
||||||
@obj = {}
|
@obj = {}
|
||||||
|
@ -30,10 +34,10 @@ class Exporter
|
||||||
private
|
private
|
||||||
|
|
||||||
def collect_user_info
|
def collect_user_info
|
||||||
%i(admin answered_count asked_count ban_reason banned_until bio blogger comment_smiled_count commented_count
|
%i(answered_count asked_count ban_reason banned_until bio blogger comment_smiled_count commented_count
|
||||||
confirmation_sent_at confirmed_at contributor created_at crop_h crop_h_h crop_h_w crop_h_x crop_h_y
|
confirmation_sent_at confirmed_at contributor created_at crop_h crop_h_h crop_h_w crop_h_x crop_h_y
|
||||||
crop_w crop_x crop_y current_sign_in_at current_sign_in_ip display_name email follower_count friend_count
|
crop_w crop_x crop_y current_sign_in_at current_sign_in_ip display_name email follower_count friend_count
|
||||||
id last_sign_in_at last_sign_in_ip locale location moderator motivation_header permanently_banned
|
id last_sign_in_at last_sign_in_ip locale location motivation_header permanently_banned
|
||||||
privacy_allow_anonymous_questions privacy_allow_public_timeline privacy_allow_stranger_answers
|
privacy_allow_anonymous_questions privacy_allow_public_timeline privacy_allow_stranger_answers
|
||||||
privacy_show_in_search profile_header_content_type profile_header_file_name profile_header_file_size
|
privacy_show_in_search profile_header_content_type profile_header_file_name profile_header_file_size
|
||||||
profile_header_updated_at profile_picture_content_type profile_picture_file_name profile_picture_file_size
|
profile_header_updated_at profile_picture_content_type profile_picture_file_name profile_picture_file_size
|
||||||
|
@ -41,6 +45,10 @@ class Exporter
|
||||||
updated_at website).each do |f|
|
updated_at website).each do |f|
|
||||||
@obj[f] = @user.send f
|
@obj[f] = @user.send f
|
||||||
end
|
end
|
||||||
|
|
||||||
|
EXPORT_ROLES.each do |role|
|
||||||
|
@obj[role] = @user.has_role?(role)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def collect_questions
|
def collect_questions
|
||||||
|
@ -221,11 +229,16 @@ class Exporter
|
||||||
|
|
||||||
def user_stub(user)
|
def user_stub(user)
|
||||||
uobj = {}
|
uobj = {}
|
||||||
%i(admin answered_count asked_count bio blogger comment_smiled_count commented_count contributor created_at
|
%i(answered_count asked_count bio blogger comment_smiled_count commented_count contributor created_at
|
||||||
display_name follower_count friend_count id location moderator motivation_header permanently_banned screen_name
|
display_name follower_count friend_count id location motivation_header permanently_banned screen_name
|
||||||
smiled_count supporter translator website).each do |f|
|
smiled_count supporter translator website).each do |f|
|
||||||
uobj[f] = user.send f
|
uobj[f] = user.send f
|
||||||
end
|
end
|
||||||
|
|
||||||
|
EXPORT_ROLES.each do |role|
|
||||||
|
uobj[role] = user.has_role?(role)
|
||||||
|
end
|
||||||
|
|
||||||
uobj
|
uobj
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe 'role-constrained routes', type: :request do
|
||||||
|
shared_examples_for 'fails to access route' do
|
||||||
|
it 'fails to access route' do
|
||||||
|
# 404 = no user found -- we have a fallback route if something could not be matched
|
||||||
|
expect(subject).to eq 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples_for 'routes for' do |roles, subject_block, skip_reason: nil|
|
||||||
|
before { skip(skip_reason) } if skip_reason
|
||||||
|
|
||||||
|
subject(&subject_block)
|
||||||
|
|
||||||
|
context 'not signed in' do
|
||||||
|
include_examples 'fails to access route'
|
||||||
|
end
|
||||||
|
|
||||||
|
roles.each do |role|
|
||||||
|
context "signed in user without #{role} role" do
|
||||||
|
let(:user) { FactoryBot.create(:user, password: 'test1234') }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
post '/sign_in', params: { user: { login: user.email, password: user.password } }
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples 'fails to access route'
|
||||||
|
end
|
||||||
|
|
||||||
|
context "signed in user with #{role} role" do
|
||||||
|
let(:user) { FactoryBot.create(:user, password: 'test1234', roles: [role]) }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
post '/sign_in', params: { user: { login: user.email, password: user.password } }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can access route' do
|
||||||
|
expect(subject).to be_in 200..299
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like('routes for', [:administrator], -> { get('/justask_admin') })
|
||||||
|
it_behaves_like('routes for', [:administrator], -> { get('/sidekiq') })
|
||||||
|
it_behaves_like('routes for', [:administrator], -> { get('/pghero') }, skip_reason: 'PG::InFailedSqlTransaction due to 5.1 upgrade, works fine outside specs though')
|
||||||
|
it_behaves_like('routes for', %i[administrator moderator], -> { get('/moderation') })
|
||||||
|
end
|
Loading…
Reference in New Issue