GRN2-xx: Made role priority unique scoped to provider (#942)

* Made role priority unique scoped to provider

* Fixed issues related to update_role after making role priority unique
This commit is contained in:
Ahmad Farhat 2020-02-19 13:38:16 -05:00 committed by GitHub
parent feccee7d62
commit c75c624a1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 81 additions and 57 deletions

View File

@ -74,7 +74,7 @@ module Populator
def shared_user_list def shared_user_list
roles_can_appear = [] roles_can_appear = []
Role.where(provider: @user_domain).each do |role| Role.where(provider: @user_domain).each do |role|
roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.name != "super_admin" roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.priority >= 0
end end
initial_list = User.where.not(uid: current_user.uid) initial_list = User.where.not(uid: current_user.uid)

View File

@ -119,17 +119,32 @@ module Rolify
return false if role.priority <= current_user_role.priority || role.provider != @user_domain return false if role.priority <= current_user_role.priority || role.provider != @user_domain
end end
# Update the roles priority including the user role # Get the priority of the current user's role and start with 1 higher
top_priority = 0 new_priority = [current_user_role.priority, 0].max + 1
role_to_update.each_with_index do |id, index| begin
new_priority = index + [current_user_role.priority, 0].max + 1 # Save the old priorities incase something fails
top_priority = new_priority old_priority = Role.where(id: role_to_update).select(:id, :priority).index_by(&:id)
Role.where(id: id).update_all(priority: new_priority)
# Set all the priorities to nil to avoid unique column issues
Role.where(id: role_to_update).update_all(priority: nil)
# Starting at the starting priority, increase by 1 every time
role_to_update.each_with_index do |id, index|
Role.find(id).update_attribute(:priority, new_priority + index)
end
true
rescue => e
# Reset to old prorities
role_to_update.each_with_index do |id, _index|
Role.find(id).update_attribute(:priority, old_priority[id.to_i].priority)
end
logger.error "#{current_user} failed to update role priorities: #{e}"
false
end end
user_role.priority = top_priority + 1
user_role.save!
end end
# Update Permissions # Update Permissions

View File

@ -38,8 +38,8 @@ class Role < ApplicationRecord
send_demoted_email: true, can_edit_site_settings: true, can_manage_rooms_recordings: true, send_demoted_email: true, can_edit_site_settings: true, can_manage_rooms_recordings: true,
can_edit_roles: true, can_manage_users: true) can_edit_roles: true, can_manage_users: true)
Role.create(name: "pending", provider: provider, priority: -1, colour: "#17a2b8").update_all_role_permissions Role.create(name: "pending", provider: provider, priority: -1, colour: "#17a2b8").update_all_role_permissions
Role.create(name: "denied", provider: provider, priority: -1, colour: "#343a40").update_all_role_permissions Role.create(name: "denied", provider: provider, priority: -2, colour: "#343a40").update_all_role_permissions
Role.create(name: "super_admin", provider: provider, priority: -2, colour: "#cd201f") Role.create(name: "super_admin", provider: provider, priority: -3, colour: "#cd201f")
.update_all_role_permissions(can_create_rooms: true, .update_all_role_permissions(can_create_rooms: true,
send_promoted_email: true, send_demoted_email: true, can_edit_site_settings: true, send_promoted_email: true, send_demoted_email: true, can_edit_site_settings: true,
can_edit_roles: true, can_manage_users: true, can_manage_rooms_recordings: true, can_edit_roles: true, can_manage_users: true, can_manage_rooms_recordings: true,
@ -56,8 +56,8 @@ class Role < ApplicationRecord
role.priority = user_role.priority role.priority = user_role.priority
user_role.priority += 1 user_role.priority += 1
role.save!
user_role.save! user_role.save!
role.save!
role role
end end

View File

@ -238,9 +238,9 @@ class User < ApplicationRecord
end end
def self.all_users_highest_priority_role def self.all_users_highest_priority_role
User.joins("INNER JOIN (SELECT user_id, role_id, min(roles.priority) FROM users_roles " \ User.joins("INNER JOIN (SELECT user_id, min(roles.priority) as role_priority FROM users_roles " \
"INNER JOIN roles ON users_roles.role_id = roles.id GROUP BY user_id) as a ON " \ "INNER JOIN roles ON users_roles.role_id = roles.id GROUP BY user_id) as a ON " \
"a.user_id = users.id INNER JOIN roles ON roles.id = a.role_id " \ "a.user_id = users.id INNER JOIN roles ON roles.priority = a.role_priority " \
" INNER JOIN role_permissions ON roles.id = role_permissions.role_id").distinct " INNER JOIN role_permissions ON roles.id = role_permissions.role_id").distinct
end end

View File

@ -21,13 +21,15 @@
<span class="icon mr-3"><i class="fas fa-users"></i></span><%= t("administrator.users.title") %> <span class="icon mr-3"><i class="fas fa-users"></i></span><%= t("administrator.users.title") %>
<% end %> <% end %>
<% end %> <% end %>
<% if highest_role.get_permission("can_edit_site_settings") || highest_role.name == "super_admin" %> <% if highest_role.get_permission("can_manage_rooms_recordings") || highest_role.name == "super_admin" %>
<%= link_to admin_rooms_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_rooms"}" do %> <%= link_to admin_rooms_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_rooms"}" do %>
<span class="icon mr-4"><i class="fas fa-binoculars"></i></span><%= t("administrator.rooms.title") %> <span class="icon mr-4"><i class="fas fa-binoculars"></i></span><%= t("administrator.rooms.title") %>
<% end %> <% end %>
<%= link_to admin_recordings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_recordings"}" do %> <%= link_to admin_recordings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_recordings"}" do %>
<span class="icon mr-4"><i class="fas fa-video"></i></span><%= t("administrator.recordings.title") %> <span class="icon mr-4"><i class="fas fa-video"></i></span><%= t("administrator.recordings.title") %>
<% end %> <% end %>
<% end %>
<% if highest_role.get_permission("can_edit_site_settings") || highest_role.name == "super_admin" %>
<%= link_to admin_site_settings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "site_settings"}" do %> <%= link_to admin_site_settings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "site_settings"}" do %>
<span class="icon mr-4"><i class="fas fa-cogs"></i></span><%= t("administrator.site_settings.title") %> <span class="icon mr-4"><i class="fas fa-cogs"></i></span><%= t("administrator.site_settings.title") %>
<% end %> <% end %>

View File

@ -63,6 +63,10 @@
<%= link_to admins_path, class: "dropdown-item" do %> <%= link_to admins_path, class: "dropdown-item" do %>
<i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %> <i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %>
<% end %> <% end %>
<% elsif highest_role.get_permission("can_manage_rooms_recordings")%>
<%= link_to admin_rooms_path, class: "dropdown-item" do %>
<i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %>
<% end %>
<% elsif highest_role.get_permission("can_edit_site_settings") %> <% elsif highest_role.get_permission("can_edit_site_settings") %>
<%= link_to admin_site_settings_path, class: "dropdown-item" do %> <%= link_to admin_site_settings_path, class: "dropdown-item" do %>
<i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %> <i class="dropdown-icon fas fa-user-tie mr-3"></i><%= t("header.dropdown.account_settings") %>

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class MigrationProduct < ActiveRecord::Base
self.table_name = :roles
end
class ChangeRolePriorityToUnique < ActiveRecord::Migration[5.2]
def change
reversible do |dir|
dir.up do
MigrationProduct.where("priority < 0").where.not(name: "pending").each do |role|
role.decrement!(:priority)
end
add_index MigrationProduct, [:priority, :provider], unique: true
end
dir.down do
remove_index MigrationProduct, [:priority, :provider]
MigrationProduct.where("priority < 0").where.not(name: "pending").each do |role|
role.increment!(:priority)
end
end
end
end
end

View File

@ -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: 2019_11_28_212935) do ActiveRecord::Schema.define(version: 2020_01_30_144841) do
create_table "features", force: :cascade do |t| create_table "features", force: :cascade do |t|
t.integer "setting_id" t.integer "setting_id"
@ -58,6 +58,7 @@ ActiveRecord::Schema.define(version: 2019_11_28_212935) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["name", "provider"], name: "index_roles_on_name_and_provider", unique: true t.index ["name", "provider"], name: "index_roles_on_name_and_provider", unique: true
t.index ["name"], name: "index_roles_on_name" t.index ["name"], name: "index_roles_on_name"
t.index ["priority", "provider"], name: "index_roles_on_priority_and_provider", unique: true
end end
create_table "rooms", force: :cascade do |t| create_table "rooms", force: :cascade do |t|

View File

@ -497,6 +497,7 @@ describe AdminsController, type: :controller do
context "PATCH #change_role_order" do context "PATCH #change_role_order" do
before do before do
Role.create_default_roles("provider1") Role.create_default_roles("provider1")
@user.roles.delete(Role.find_by(name: "user", provider: "greenlight"))
end end
it "should fail if user attempts to change the order of the admin or user roles" do it "should fail if user attempts to change the order of the admin or user roles" do
@ -512,35 +513,9 @@ describe AdminsController, type: :controller do
end end
it "should fail if a user attempts to edit a role with a higher priority than their own" do it "should fail if a user attempts to edit a role with a higher priority than their own" do
Role.create(name: "test1", priority: 1, provider: "greenlight") new_role3 = Role.create_new_role("test3", "provider1")
new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight") new_role2 = Role.create_new_role("test2", "provider1")
new_role2.update_permission("can_edit_roles", "true") new_role2.update_permission("can_edit_roles", "true")
new_role3 = Role.create(name: "test3", priority: 3, provider: "greenlight")
user_role = Role.find_by(name: "user", provider: "greenlight")
user_role.priority = 4
user_role.save!
@user.roles << new_role2
@user.save!
@request.session[:user_id] = @user.id
patch :change_role_order, params: { role: [new_role3.id, new_role2.id] }
expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_order"))
expect(response).to redirect_to admin_roles_path
end
it "should fail if a user attempts to edit a role with a higher priority than their own" do
Role.create(name: "test1", priority: 1, provider: "greenlight")
new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight")
new_role2.update_permission("can_edit_roles", "true")
new_role3 = Role.create(name: "test3", priority: 3, provider: "greenlight")
user_role = Role.find_by(name: "user", provider: "greenlight")
user_role.priority = 4
user_role.save!
@user.roles << new_role2 @user.roles << new_role2
@user.save! @user.save!
@ -554,10 +529,11 @@ describe AdminsController, type: :controller do
end end
it "should update the role order" do it "should update the role order" do
user_role = Role.find_by(name: "user", provider: "provider1")
user_role.update_attribute(:priority, 4)
new_role1 = Role.create(name: "test1", priority: 1, provider: "provider1") new_role1 = Role.create(name: "test1", priority: 1, provider: "provider1")
new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1") new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1")
new_role3 = Role.create(name: "test3", priority: 3, provider: "provider1") new_role3 = Role.create(name: "test3", priority: 3, provider: "provider1")
user_role = Role.find_by(name: "user", provider: "provider1")
@request.session[:user_id] = @admin.id @request.session[:user_id] = @admin.id
@ -578,16 +554,15 @@ describe AdminsController, type: :controller do
context 'POST #update_role' do context 'POST #update_role' do
before do before do
Role.create_default_roles("provider1") Role.create_default_roles("provider1")
@user.roles.delete(Role.find_by(name: "user", provider: "greenlight"))
end end
it "should fail to update a role with a lower priority than the user" do it "should fail to update a role with a lower priority than the user" do
user_role = Role.find_by(name: "user", provider: "provider1")
user_role.update_attribute(:priority, 3)
new_role1 = Role.create(name: "test1", priority: 1, provider: "provider1") new_role1 = Role.create(name: "test1", priority: 1, provider: "provider1")
new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1") new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1")
new_role2.update_permission("can_edit_roles", "true") new_role2.update_permission("can_edit_roles", "true")
user_role = Role.find_by(name: "user", provider: "greenlight")
user_role.priority = 3
user_role.save!
@user.roles << new_role2 @user.roles << new_role2
@user.save! @user.save!
@ -601,7 +576,7 @@ describe AdminsController, type: :controller do
end end
it "should fail to update if there is a duplicate name" do it "should fail to update if there is a duplicate name" do
new_role = Role.create(name: "test2", priority: 1, provider: "provider1") new_role = Role.create(name: "test2", priority: 2, provider: "provider1")
new_role.update_permission("can_edit_roles", "true") new_role.update_permission("can_edit_roles", "true")
@request.session[:user_id] = @admin.id @request.session[:user_id] = @admin.id
@ -613,7 +588,7 @@ describe AdminsController, type: :controller do
end end
it "should update role permisions" do it "should update role permisions" do
new_role = Role.create(name: "test2", priority: 1, provider: "provider1") new_role = Role.create(name: "test2", priority: 2, provider: "provider1")
new_role.update_permission("can_edit_roles", "true") new_role.update_permission("can_edit_roles", "true")
@request.session[:user_id] = @admin.id @request.session[:user_id] = @admin.id
@ -658,7 +633,7 @@ describe AdminsController, type: :controller do
end end
it "should successfully delete the role" do it "should successfully delete the role" do
new_role = Role.create(name: "test2", priority: 1, provider: "provider1") new_role = Role.create(name: "test2", priority: 2, provider: "provider1")
new_role.update_permission("can_edit_roles", "true") new_role.update_permission("can_edit_roles", "true")
@request.session[:user_id] = @admin.id @request.session[:user_id] = @admin.id

View File

@ -312,7 +312,7 @@ describe UsersController, type: :controller do
user_role.save! user_role.save!
tmp_role = Role.create(name: "test", priority: -2, provider: "greenlight") tmp_role = Role.create(name: "test", priority: -4, provider: "greenlight")
params = random_valid_user_params params = random_valid_user_params
patch :update, params: params.merge!(user_uid: user, user: { role_ids: tmp_role.id.to_s }) patch :update, params: params.merge!(user_uid: user, user: { role_ids: tmp_role.id.to_s })
@ -354,9 +354,9 @@ describe UsersController, type: :controller do
@request.session[:user_id] = admin.id @request.session[:user_id] = admin.id
tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight") tmp_role1 = Role.create(name: "test1", priority: 2, provider: "greenlight")
tmp_role1.update_permission("send_promoted_email", "true") tmp_role1.update_permission("send_promoted_email", "true")
tmp_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight") tmp_role2 = Role.create(name: "test2", priority: 3, provider: "greenlight")
params = random_valid_user_params params = random_valid_user_params
params = params.merge!(user_uid: user, user: { role_ids: "#{tmp_role1.id} #{tmp_role2.id}" }) params = params.merge!(user_uid: user, user: { role_ids: "#{tmp_role1.id} #{tmp_role2.id}" })
@ -375,7 +375,7 @@ describe UsersController, type: :controller do
admin.add_role :admin admin.add_role :admin
tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight") tmp_role1 = Role.create(name: "test1", priority: 2, provider: "greenlight")
tmp_role1.update_permission("send_demoted_email", "true") tmp_role1.update_permission("send_demoted_email", "true")
user.roles << tmp_role1 user.roles << tmp_role1
user.save! user.save!