From 9ed3fa2a22d20b01d5b38b5be59ad77f2ebd7079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Tue, 10 May 2016 18:31:50 +0200 Subject: [PATCH 1/5] creates manager role --- app/models/manager.rb | 6 ++++++ db/migrate/20160510161858_create_manager_role.rb | 7 +++++++ db/schema.rb | 9 ++++++++- spec/factories.rb | 4 ++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 app/models/manager.rb create mode 100644 db/migrate/20160510161858_create_manager_role.rb diff --git a/app/models/manager.rb b/app/models/manager.rb new file mode 100644 index 000000000..d9c1aff07 --- /dev/null +++ b/app/models/manager.rb @@ -0,0 +1,6 @@ +class Manager < ActiveRecord::Base + belongs_to :user, touch: true + delegate :name, :email, :name_and_email, to: :user + + validates :user_id, presence: true, uniqueness: true +end diff --git a/db/migrate/20160510161858_create_manager_role.rb b/db/migrate/20160510161858_create_manager_role.rb new file mode 100644 index 000000000..48ceb7e20 --- /dev/null +++ b/db/migrate/20160510161858_create_manager_role.rb @@ -0,0 +1,7 @@ +class CreateManagerRole < ActiveRecord::Migration + def change + create_table :managers do |t| + t.belongs_to :user, index: true, foreign_key: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index b105a2b2c..78a3ffd45 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160426211658) do +ActiveRecord::Schema.define(version: 20160510161858) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -214,6 +214,12 @@ ActiveRecord::Schema.define(version: 20160426211658) do add_index "locks", ["user_id"], name: "index_locks_on_user_id", using: :btree + create_table "managers", force: :cascade do |t| + t.integer "user_id" + end + + add_index "managers", ["user_id"], name: "index_managers_on_user_id", using: :btree + create_table "moderators", force: :cascade do |t| t.integer "user_id" end @@ -510,6 +516,7 @@ ActiveRecord::Schema.define(version: 20160426211658) do add_foreign_key "flags", "users" add_foreign_key "identities", "users" add_foreign_key "locks", "users" + add_foreign_key "managers", "users" add_foreign_key "moderators", "users" add_foreign_key "notifications", "users" add_foreign_key "organizations", "users" diff --git a/spec/factories.rb b/spec/factories.rb index 20a0b2b51..67c2e2c07 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -256,6 +256,10 @@ FactoryGirl.define do user end + factory :manager do + user + end + factory :organization do user responsible_name "Johnny Utah" From d1e50d70d68c5eeed2e60cd2ec98c6127088d24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Tue, 10 May 2016 19:10:02 +0200 Subject: [PATCH 2/5] managers can login to /management --- .../management/sessions_controller.rb | 8 ++++++- app/models/user.rb | 5 +++++ app/views/shared/_admin_login_items.html.erb | 2 +- .../management/sessions_controller_spec.rb | 21 +++++++++++++++---- spec/features/management/account_spec.rb | 2 +- spec/features/management/users_spec.rb | 2 +- spec/models/user_spec.rb | 12 +++++++++++ spec/support/common_actions.rb | 8 ++++++- 8 files changed, 51 insertions(+), 9 deletions(-) diff --git a/app/controllers/management/sessions_controller.rb b/app/controllers/management/sessions_controller.rb index d3a85402b..bca17bf4c 100644 --- a/app/controllers/management/sessions_controller.rb +++ b/app/controllers/management/sessions_controller.rb @@ -4,7 +4,7 @@ class Management::SessionsController < ActionController::Base def create destroy_session - if admin? || manager? + if admin? || manager? || authenticated_manager? redirect_to management_root_path else raise CanCan::AccessDenied @@ -31,6 +31,12 @@ class Management::SessionsController < ActionController::Base end def manager? + if current_user.try(:manager?) + session[:manager] = {login: "manager_user_#{current_user.id}"} + end + end + + def authenticated_manager? if manager = ManagerAuthenticator.new(params).auth session[:manager] = manager end diff --git a/app/models/user.rb b/app/models/user.rb index 7da80b6fb..4839d3ced 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -12,6 +12,7 @@ class User < ActiveRecord::Base has_one :administrator has_one :moderator has_one :valuator + has_one :manager has_one :organization has_one :lock has_many :flags @@ -104,6 +105,10 @@ class User < ActiveRecord::Base valuator.present? end + def manager? + manager.present? + end + def organization? organization.present? end diff --git a/app/views/shared/_admin_login_items.html.erb b/app/views/shared/_admin_login_items.html.erb index 3625432a8..6ba10bbca 100644 --- a/app/views/shared/_admin_login_items.html.erb +++ b/app/views/shared/_admin_login_items.html.erb @@ -17,7 +17,7 @@ <% end %> - <% if current_user.administrator? %> + <% if current_user.administrator? || current_user.manager? %>
  • <%= link_to t("layouts.header.management"), management_sign_in_path %>
  • diff --git a/spec/controllers/management/sessions_controller_spec.rb b/spec/controllers/management/sessions_controller_spec.rb index a07067ed9..d2d6b5f8b 100644 --- a/spec/controllers/management/sessions_controller_spec.rb +++ b/spec/controllers/management/sessions_controller_spec.rb @@ -6,31 +6,44 @@ describe Management::SessionsController do it "should deny access if wrong manager credentials" do allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return(false) expect { get :create, login: "nonexistent" , clave_usuario: "wrong"}.to raise_error CanCan::AccessDenied + expect(session[:manager]).to be_nil end - it "should redirect to management root path if right credentials" do + it "should redirect to management root path if authorized manager with right credentials" do manager = {login: "JJB033", user_key: "31415926" , date: "20151031135905"} allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return(manager) get :create, login: "JJB033" , clave_usuario: "31415926", fecha_conexion: "20151031135905" expect(response).to be_redirect + expect(session[:manager][:login]).to eq "JJB033" end it "should redirect to management root path if user is admin" do - sign_in create(:administrator).user + user = create(:administrator).user + sign_in user get :create expect(response).to be_redirect + expect(session[:manager][:login]).to eq "admin_user_#{user.id}" end - it "should deny access if user is not admin" do + it "should redirect to management root path if user is manager" do + user = create(:manager).user + sign_in user + get :create + expect(response).to be_redirect + expect(session[:manager][:login]).to eq "manager_user_#{user.id}" + end + + it "should deny access if user is not admin or manager" do sign_in create(:user) expect { get :create}.to raise_error CanCan::AccessDenied + expect(session[:manager]).to be_nil end end describe 'Sign out' do it "should destroy the session data and redirect" do - session[:manager] = {user_key: "31415926" , date: "20151031135905", login: "JJB033"} + session[:manager] = {user_key: "31415926", date: "20151031135905", login: "JJB033"} session[:document_type] = "1" session[:document_number] = "12345678Z" diff --git a/spec/features/management/account_spec.rb b/spec/features/management/account_spec.rb index 3b9951d41..04a2e7213 100644 --- a/spec/features/management/account_spec.rb +++ b/spec/features/management/account_spec.rb @@ -26,7 +26,7 @@ feature 'Account' do expect(page).to have_content "User account deleted." - expect(user.reload.erase_reason).to eq "Deleted by manager: JJB042" + expect(user.reload.erase_reason).to eq "Deleted by manager: manager_user_#{Manager.last.user_id}" end end \ No newline at end of file diff --git a/spec/features/management/users_spec.rb b/spec/features/management/users_spec.rb index 021edaaad..1a0618e60 100644 --- a/spec/features/management/users_spec.rb +++ b/spec/features/management/users_spec.rb @@ -59,7 +59,7 @@ feature 'Users' do expect(page).to have_content "User account deleted." - expect(level_2_user.reload.erase_reason).to eq "Deleted by manager: JJB042" + expect(level_2_user.reload.erase_reason).to eq "Deleted by manager: manager_user_#{Manager.last.user_id}" visit management_document_verifications_path fill_in 'document_verification_document_number', with: '13579' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b49e3cc6b..054e043f9 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -121,6 +121,18 @@ describe User do end end + describe "manager?" do + it "is false when the user is not a manager" do + expect(subject.manager?).to be false + end + + it "is true when the user is a manager" do + subject.save + create(:manager, user: subject) + expect(subject.manager?).to be true + end + end + describe "organization?" do it "is false when the user is not an organization" do expect(subject.organization?).to be false diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index bba79441b..18a3f9499 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -24,12 +24,18 @@ module CommonActions click_button 'Enter' end - def login_as_manager + def login_as_authenticated_manager login, user_key, date = "JJB042", "31415926", Time.now.strftime("%Y%m%d%H%M%S") allow_any_instance_of(ManagerAuthenticator).to receive(:auth).and_return({login: login, user_key: user_key, date: date}.with_indifferent_access) visit management_sign_in_path(login: login, clave_usuario: user_key, fecha_conexion: date) end + def login_as_manager + manager = create(:manager) + login_as(manager.user) + visit management_sign_in_path + end + def login_managed_user(user) allow_any_instance_of(Management::BaseController).to receive(:managed_user).and_return(user) end From c4bf90f5763a363b04417ee84ee8d623c6389e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Wed, 11 May 2016 11:24:38 +0200 Subject: [PATCH 3/5] adds managers section to admin --- app/controllers/admin/managers_controller.rb | 32 ++++++++++++++++ .../admin/moderators_controller.rb | 10 ++--- app/models/abilities/administrator.rb | 1 + app/views/admin/managers/_manager.html.erb | 13 +++++++ app/views/admin/managers/index.html.erb | 24 ++++++++++++ app/views/admin/managers/search.js.erb | 1 + .../admin/managers/user_not_found.js.erb | 1 + config/locales/admin.en.yml | 11 ++++++ config/locales/admin.es.yml | 13 ++++++- config/routes.rb | 4 ++ spec/features/admin/managers_spec.rb | 37 +++++++++++++++++++ spec/features/admin_spec.rb | 11 ++++++ spec/features/moderation_spec.rb | 14 +++++++ spec/features/valuation_spec.rb | 13 +++++++ 14 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 app/controllers/admin/managers_controller.rb create mode 100644 app/views/admin/managers/_manager.html.erb create mode 100644 app/views/admin/managers/index.html.erb create mode 100644 app/views/admin/managers/search.js.erb create mode 100644 app/views/admin/managers/user_not_found.js.erb create mode 100644 spec/features/admin/managers_spec.rb diff --git a/app/controllers/admin/managers_controller.rb b/app/controllers/admin/managers_controller.rb new file mode 100644 index 000000000..5023a1380 --- /dev/null +++ b/app/controllers/admin/managers_controller.rb @@ -0,0 +1,32 @@ +class Admin::ManagersController < Admin::BaseController + load_and_authorize_resource + + def index + @managers = @managers.page(params[:page]) + end + + def search + @user = User.find_by(email: params[:email]) + + respond_to do |format| + if @user + @manager = Manager.find_or_initialize_by(user: @user) + format.js + else + format.js { render "user_not_found" } + end + end + end + + def create + @manager.user_id = params[:user_id] + @manager.save + + redirect_to admin_managers_path + end + + def destroy + @manager.destroy + redirect_to admin_managers_path + end +end diff --git a/app/controllers/admin/moderators_controller.rb b/app/controllers/admin/moderators_controller.rb index e15e9273f..2566c0c02 100644 --- a/app/controllers/admin/moderators_controller.rb +++ b/app/controllers/admin/moderators_controller.rb @@ -18,15 +18,15 @@ class Admin::ModeratorsController < Admin::BaseController end end - def destroy - @moderator.destroy - redirect_to admin_moderators_path - end - def create @moderator.user_id = params[:user_id] @moderator.save redirect_to admin_moderators_path end + + def destroy + @moderator.destroy + redirect_to admin_moderators_path + end end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 587b4954b..6b77c130d 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -37,6 +37,7 @@ module Abilities can [:search, :create, :index, :destroy], ::Moderator can [:search, :create, :index, :summary], ::Valuator + can [:search, :create, :index, :destroy], ::Manager can :manage, Annotation diff --git a/app/views/admin/managers/_manager.html.erb b/app/views/admin/managers/_manager.html.erb new file mode 100644 index 000000000..24dd1565c --- /dev/null +++ b/app/views/admin/managers/_manager.html.erb @@ -0,0 +1,13 @@ +<%= manager.name %> + •  +<%= manager.email %> +<% if manager.persisted? %> + <%= link_to t('admin.managers.manager.delete'), + admin_manager_path(manager), + method: :delete, + class: "button small alert float-right" + %> +<% else %> + <%= link_to t('admin.managers.manager.add'),{ controller: "admin/managers", action: :create, user_id: manager.user_id }, + method: :post, class: "button small success float-right" %> +<% end %> diff --git a/app/views/admin/managers/index.html.erb b/app/views/admin/managers/index.html.erb new file mode 100644 index 000000000..3113907a4 --- /dev/null +++ b/app/views/admin/managers/index.html.erb @@ -0,0 +1,24 @@ +

    <%= t("admin.managers.index.title") %>

    +
    +
    + <%= form_tag search_admin_managers_path, method: :get, remote: true do %> +
    + <%= text_field_tag :email, '', placeholder: t('admin.managers.search.email_placeholder') %> +
    +
    + <%= submit_tag t('admin.managers.search.search'), class: 'button' %> +
    + <% end %> +
    +
    +
    +

    <%= page_entries_info @managers %>

    +
      + <% @managers.each do |manager| %> +
    • + <%= render 'manager', manager: manager %> +
    • + <% end %> +
    + +<%= paginate @managers %> diff --git a/app/views/admin/managers/search.js.erb b/app/views/admin/managers/search.js.erb new file mode 100644 index 000000000..0f0fd09cd --- /dev/null +++ b/app/views/admin/managers/search.js.erb @@ -0,0 +1 @@ +$("#search-result").html("
    <%= j render 'manager', manager: @manager %>
    "); diff --git a/app/views/admin/managers/user_not_found.js.erb b/app/views/admin/managers/user_not_found.js.erb new file mode 100644 index 000000000..0116de21d --- /dev/null +++ b/app/views/admin/managers/user_not_found.js.erb @@ -0,0 +1 @@ +$("#search-result").html("
    <%= j t('admin.managers.search.user_not_found') %>
    "); diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 15b3870d8..282e72d27 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -47,6 +47,16 @@ en: with_confirmed_hide: Confirmed without_confirmed_hide: Pending title: Hidden debates + managers: + index: + title: Managers + manager: + add: Add + delete: Delete + search: + email_placeholder: Search user by email + search: Search + user_not_found: User not found menu: activity: Moderator activity debate_topics: Debate topics @@ -55,6 +65,7 @@ en: hidden_proposals: Hidden proposals hidden_users: Hidden users incomplete_verifications: Incomplete verifications + managers: Managers moderators: Moderators valuators: Valuators officials: Officials diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 803073b2d..66b419d26 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -47,6 +47,16 @@ es: with_confirmed_hide: Confirmados without_confirmed_hide: Pendientes title: Debates ocultos + managers: + index: + title: Gestores + manager: + add: Añadir como Gestor + delete: Borrar + search: + email_placeholder: Buscar usuario por email + search: Buscar + user_not_found: Usuario no encontrado menu: activity: Actividad de moderadores debate_topics: Temas de debate @@ -55,6 +65,7 @@ es: hidden_proposals: Propuestas ocultas hidden_users: Usuarios bloqueados incomplete_verifications: Verificaciones incompletas + managers: Gestores moderators: Moderadores valuators: Evaluadores officials: Cargos públicos @@ -66,7 +77,7 @@ es: index: title: Moderadores moderator: - add: Añadir + add: Añadir como Moderador delete: Borrar search: email_placeholder: Buscar usuario por email diff --git a/config/routes.rb b/config/routes.rb index 1c7af6800..a2035a0b7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -165,6 +165,10 @@ Rails.application.routes.draw do get :summary, on: :collection end + resources :managers, only: [:index, :create, :destroy] do + get :search, on: :collection + end + resources :verifications, controller: :verifications, only: :index do get :search, on: :collection end diff --git a/spec/features/admin/managers_spec.rb b/spec/features/admin/managers_spec.rb new file mode 100644 index 000000000..100781446 --- /dev/null +++ b/spec/features/admin/managers_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +feature 'Admin managers' do + background do + @admin = create(:administrator) + @user = create(:user) + @manager = create(:manager) + login_as(@admin.user) + visit admin_managers_path + end + + scenario 'Index' do + expect(page).to have_content @manager.name + expect(page).to have_content @manager.email + expect(page).to_not have_content @user.name + end + + scenario 'Create Manager', :js do + fill_in 'email', with: @user.email + click_button 'Search' + + expect(page).to have_content @user.name + click_link 'Add' + within("#managers") do + expect(page).to have_content @user.name + end + end + + scenario 'Delete Manager' do + click_link 'Delete' + + within("#managers") do + expect(page).to_not have_content @manager.name + end + end +end + diff --git a/spec/features/admin_spec.rb b/spec/features/admin_spec.rb index 87c60355b..1561a60a8 100644 --- a/spec/features/admin_spec.rb +++ b/spec/features/admin_spec.rb @@ -36,6 +36,16 @@ feature 'Admin' do expect(page).to have_content "You do not have permission to access this page" end + scenario 'Access as a manager is not authorized' do + create(:manager, user: user) + login_as(user) + visit admin_root_path + + expect(current_path).not_to eq(admin_root_path) + expect(current_path).to eq(proposals_path) + expect(page).to have_content "You do not have permission to access this page" + end + scenario 'Access as an administrator is authorized' do login_as(administrator) visit admin_root_path @@ -51,6 +61,7 @@ feature 'Admin' do expect(page).to have_link('Administration') expect(page).to have_link('Moderation') expect(page).to have_link('Valuation') + expect(page).to have_link('Management') end scenario 'Admin dashboard' do diff --git a/spec/features/moderation_spec.rb b/spec/features/moderation_spec.rb index 12eb07358..6607ec48a 100644 --- a/spec/features/moderation_spec.rb +++ b/spec/features/moderation_spec.rb @@ -29,6 +29,20 @@ feature 'Moderation' do expect(page).to have_content "You do not have permission to access this page" end + scenario 'Access as manager is not authorized' do + create(:manager, user: user) + + login_as(user) + visit root_path + + expect(page).to_not have_link("Moderation") + visit moderation_root_path + + expect(current_path).not_to eq(moderation_root_path) + expect(current_path).to eq(proposals_path) + expect(page).to have_content "You do not have permission to access this page" + end + scenario 'Access as a moderator is authorized' do create(:moderator, user: user) diff --git a/spec/features/valuation_spec.rb b/spec/features/valuation_spec.rb index 571a4323f..fab16027a 100644 --- a/spec/features/valuation_spec.rb +++ b/spec/features/valuation_spec.rb @@ -28,6 +28,19 @@ feature 'Valuation' do expect(page).to have_content "You do not have permission to access this page" end + scenario 'Access as manager is not authorized' do + create(:manager, user: user) + login_as(user) + visit root_path + + expect(page).to_not have_link("Valuation") + visit valuation_root_path + + expect(current_path).not_to eq(valuation_root_path) + expect(current_path).to eq(proposals_path) + expect(page).to have_content "You do not have permission to access this page" + end + scenario 'Access as a valuator is authorized' do create(:valuator, user: user) login_as(user) From ddc86143940532229175ffc855174978cbb42f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Wed, 11 May 2016 11:24:52 +0200 Subject: [PATCH 4/5] adds managers to admin menu --- app/views/admin/_menu.html.erb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index f435c5511..bf0382dbd 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -85,6 +85,13 @@ <% end %> +
  • > + <%= link_to admin_managers_path do %> + + <%= t('admin.menu.managers') %> + <% end %> +
  • +
  • > <%= link_to admin_activity_path do %> From ef9546968bfe19c0762b44dd1f51eb4982c39fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juanjo=20Baz=C3=A1n?= Date: Wed, 11 May 2016 11:25:35 +0200 Subject: [PATCH 5/5] removes duplicate specs (already present in features/admin/tags_spec.rb) --- spec/features/admin_spec.rb | 43 ------------------------------------- 1 file changed, 43 deletions(-) diff --git a/spec/features/admin_spec.rb b/spec/features/admin_spec.rb index 1561a60a8..9ef1b334e 100644 --- a/spec/features/admin_spec.rb +++ b/spec/features/admin_spec.rb @@ -76,47 +76,4 @@ feature 'Admin' do expect(page).to_not have_css('#valuation_menu') end - context 'Tags' do - let(:unfeatured_tag) { create :tag, :unfeatured, name: 'Mi barrio' } - - background do - login_as(administrator) - end - - scenario 'adding a new tag' do - visit admin_tags_path - - fill_in 'tag_name', with: 'Papeleras' - - click_on 'Create Topic' - - expect(page).to have_content 'Papeleras' - end - - scenario 'deleting tag' do - unfeatured_tag - - visit admin_tags_path - - expect(page).to have_content 'Mi barrio' - - click_link 'Destroy Topic' - - expect(page).not_to have_content 'Mi barrio' - end - - scenario 'marking tags as featured / unfeatured' do - expect(unfeatured_tag).not_to be_featured - - visit admin_tags_path - - expect(page).to have_content 'Mi barrio' - - check "tag_featured_#{unfeatured_tag.id}" - click_button 'Update Topic' - - expect(page).to have_checked_field("tag_featured_#{unfeatured_tag.id}") - end - end - end