This patch only enables the UI to modify permissions on Pools. The vast majority of the
code is non-type-specific though, so once this part is finalized it will be easy to expand
it to other object types.
---
src/app/controllers/application_controller.rb | 10 +
src/app/controllers/permissions_controller.rb | 184 ++++++++++++++++-----
src/app/controllers/pools_controller.rb | 14 ++-
src/app/helpers/application_helper.rb | 1 +
src/app/stylesheets/custom.scss | 4 +
src/app/views/layouts/_filter_table.haml | 4 +
src/app/views/permissions/_form.haml | 16 ++
src/app/views/permissions/_new.haml | 14 ++
src/app/views/permissions/_permissions.haml | 24 +++
src/app/views/permissions/index.haml | 1 +
src/app/views/permissions/new.haml | 20 +--
src/app/views/pools/_permissions.haml | 8 +-
src/config/locales/en.yml | 4 +
src/config/routes.rb | 2 +
src/features/permission.feature | 58 ++++---
src/features/step_definitions/permission_steps.rb | 13 ++-
16 files changed, 285 insertions(+), 92 deletions(-)
create mode 100644 src/app/views/permissions/_form.haml
create mode 100644 src/app/views/permissions/_new.haml
create mode 100644 src/app/views/permissions/_permissions.haml
create mode 100644 src/app/views/permissions/index.haml
diff --git a/src/app/controllers/application_controller.rb
b/src/app/controllers/application_controller.rb
index b2d7453..2b7f9c5 100644
--- a/src/app/controllers/application_controller.rb
+++ b/src/app/controllers/application_controller.rb
@@ -241,4 +241,14 @@ class ApplicationController < ActionController::Base
raise "Tab '#{tab}' doesn't exist"
end
end
+
+ def set_permissions_header
+ @permission_list_header = [
+ { :name => '', :sortable => false },
+ { :name => t("user"), :sort_attr => :last_name },
+ { :name => t("role"), :sort_attr => :role},
+ { :name => t("privileges")},
+ ]
+ end
+
end
diff --git a/src/app/controllers/permissions_controller.rb
b/src/app/controllers/permissions_controller.rb
index 280fbe9..b2eaa7f 100644
--- a/src/app/controllers/permissions_controller.rb
+++ b/src/app/controllers/permissions_controller.rb
@@ -18,40 +18,150 @@
class PermissionsController < ApplicationController
before_filter :require_user
+ before_filter :set_permissions_header
- def show
- @permission = Permission.find(params[:id])
- require_privilege(Privilege::PERM_VIEW, @permission.permission_object)
- end
-
- def list
- set_permission_object Privilege::PERM_VIEW
+ def index
+ obj_type = params[:permission_object_type]
+ id = params[:permission_object_id]
+ @permission_object = obj_type.constantize.find(id) if obj_type and id
+ raise RuntimeError, "invalid permission object" if @permission_object.nil?
+ respond_to do |format|
+ format.html
+ format.json { render :json => @permission_object.as_json }
+ format.js { render :partial => 'index' }
+ end
end
def new
- set_permission_object Privilege::PERM_SET
- @permission = Permission.new(:permission_object_type => @permission_object.class,
- :permission_object_id => @permission_object.id)
+ obj_type = params[:permission_object_type]
+ id = params[:permission_object_id]
+ @permission_object = obj_type.constantize.find(id) if obj_type and id
+ require_privilege(Privilege::PERM_SET, @permission_object)
@users = User.all
@roles = Role.find_all_by_scope((a)permission_object.class.name)
+ load_headers
+ load_users
+ respond_to do |format|
+ format.html
+ format.js { render :partial => 'new' }
+ end
end
def create
- @permission = Permission.new(params[:permission])
- require_privilege(Privilege::PERM_SET, @permission.permission_object)
- if request.post? && @permission.save
- flash[:notice] = "Permission record added."
- redirect_to :action => "list",
- :permission_object_type => @permission.permission_object_type,
- :permission_object_id => @permission.permission_object_id
- else
- @permission_object = @permission.permission_object
- @users = User.all
- @roles = Role.find_all_by_scope((a)permission_object.class.name)
- render :action => 'new'
+ obj_type = params[:permission_object_type]
+ id = params[:permission_object_id]
+ @permission_object = obj_type.constantize.find(id) if obj_type and id
+ require_privilege(Privilege::PERM_SET, @permission_object)
+ added=[]
+ not_added=[]
+ params[:user_role_selected].each do |user_role|
+ user_id,role_id = user_role.split(",")
+ unless role_id.nil?
+ permission = Permission.new(:user_id => user_id,
+ :role_id => role_id,
+ :permission_object => @permission_object)
+ if permission.save
+ added << permission.user.login + " " + permission.role.name
+ else
+ not_added << permission.user.login + " " +
permission.role.name
+ end
+ end
+ end
+ unless added.empty?
+ flash[:notice] = "These User Roles were added: #{added.join(',
')}"
+ end
+ unless not_added.empty?
+ flash[:error] = "Could not add these User Roles: #{not_added.join(',
')}"
+ end
+ if added.empty? and not_added.empty?
+ flash[:error] = "No users selected"
+ end
+ respond_to do |format|
+ format.html { redirect_to polymorphic_path(@permission_object,
+ :details_tab => :permissions,
+ :only_tab => true) }
+ format.js { render :partial => 'index',
+ :permission_object_type => @permission_object.class.name,
+ :permission_object_id => @permission_object.id }
+ end
+ end
+
+ def multi_update
+ obj_type = params[:permission_object_type]
+ id = params[:permission_object_id]
+ @permission_object = obj_type.constantize.find(id) if obj_type and id
+ require_privilege(Privilege::PERM_SET, @permission_object)
+ modified=[]
+ not_modified=[]
+ params[:permission_role_selected].each do |permission_role|
+ permission_id,role_id = permission_role.split(",")
+ unless role_id.nil?
+ permission = Permission.find(permission_id)
+ role = Role.find(role_id)
+ old_role = permission.role
+ unless permission.role == role
+ permission.role = role
+ if permission.save
+ modified << permission.user.login + " " +
permission.role.name + " from " + old_role.name
+ else
+ not_modified << permission.user.login + " " +
permission.role.name
+ end
+ end
+ end
+ end
+ unless modified.empty?
+ flash[:notice] = "These User Roles were modified: #{modified.join(',
')}"
+ end
+ unless not_modified.empty?
+ flash[:error] = "Could not add these User Roles: #{not_modified.join(',
')}"
+ end
+ if modified.empty? and not_modified.empty?
+ flash[:error] = "No users selected"
+ end
+ respond_to do |format|
+ format.html { redirect_to polymorphic_path(@permission_object,
+ :details_tab => :permissions,
+ :only_tab => true) }
+ format.js { render :partial => 'index',
+ :permission_object_type => @permission_object.class.name,
+ :permission_object_id => @permission_object.id }
end
end
+ def multi_destroy
+ obj_type = params[:permission_object_type]
+ id = params[:permission_object_id]
+ @permission_object = obj_type.constantize.find(id) if obj_type and id
+ raise RuntimeError, "invalid permission object" if @permission_object.nil?
+ require_privilege(Privilege::PERM_SET, @permission_object)
+ deleted=[]
+ not_deleted=[]
+
+ Permission.find(params[:permission_selected]).each do |p|
+ if check_privilege(Privilege::PERM_SET, p.permission_object) && p.destroy
+ deleted << p.user.login + " " + p.role.name
+ else
+ not_deleted << p.user.login + " " + p.role.name
+ end
+ end
+
+ unless deleted.empty?
+ flash[:notice] = "These Permission Grants were deleted: #{deleted.join(',
')}"
+ end
+ unless not_deleted.empty?
+ flash[:error] = "Could not delete these Permission Grants:
#{not_deleted.join(', ')}"
+ end
+ respond_to do |format|
+ format.html { redirect_to polymorphic_path(@permission_object,
+ :details_tab => :permissions,
+ :only_tab => true) }
+ format.js { render :partial => 'index',
+ :permission_object_type => @permission_object.class.name,
+ :permission_object_id => @permission_object.id }
+ format.json { render :json => @permission, :status => :created }
+ end
+
+ end
def destroy
if request.post?
p =Permission.find(params[:permission][:id])
@@ -65,25 +175,19 @@ class PermissionsController < ApplicationController
private
- def set_permission_object(action)
- if !params[:permission_object_type].nil?
- @permission_object =
- params[:permission_object_type].constantize.find(params[:permission_object_id])
- elsif !params[:pool_id].nil?
- @permission_object = Pool.find params[:pool_id]
- elsif !params[:provider_id].nil?
- @permission_object = Provider.find params[:provider_id]
- elsif !params[:cloud_account_id].nil?
- @permission_object = ProviderAccount.find params[:cloud_account_id]
- elsif !params[:base_permission_object_id].nil?
- @permission_object = BasePermissionObject.find params[:base_permission_object_id]
- else
- @permission_object = BasePermissionObject.general_permission_scope
- end
-
- raise ActiveRecord::RecordNotFound if @permission_object.nil?
+ def load_users
+ sort_order = params[:sort_by].nil? ? "login" : params[:sort_by]
+ @users = User.all(:order => sort_order)
+ end
- require_privilege(action, @permission_object)
+ def load_headers
+ @header = [
+ { :name => '', :sortable => false },
+ { :name => t('users.index.username'), :sortable => false },
+ { :name => t('users.index.last_name'), :sortable => false },
+ { :name => t('users.index.first_name'), :sortable => false },
+ { :name => t('role'), :sortable => false }
+ ]
end
end
diff --git a/src/app/controllers/pools_controller.rb
b/src/app/controllers/pools_controller.rb
index 043af1d..1ab7c1b 100644
--- a/src/app/controllers/pools_controller.rb
+++ b/src/app/controllers/pools_controller.rb
@@ -20,6 +20,7 @@ class PoolsController < ApplicationController
before_filter :require_user
before_filter :set_params_and_header, :only => [:index, :show]
before_filter :load_pools, :only => [:show]
+ before_filter :set_permissions_header, :only => [:show]
viewstate :index do |default|
default.merge!({
@@ -91,11 +92,22 @@ class PoolsController < ApplicationController
#{:name => 'History', :view => @view, :id =>
'history'},
{:name => 'Properties', :view => 'properties',
:id => 'properties'},
{:name => 'Catalog Images', :view => 'images',
:id => 'images'}
- #{:name => 'Permissions', :view => 'permissions',
:id => 'permissions'}
]
if "images" == params[:details_tab]
@map = @pool.provider_image_map
end
+
+ if "permissions" == params[:details_tab]
+ require_privilege(Privilege::PERM_VIEW, @pool)
+ @permission_object = @pool
+ end
+ if @pool.has_privilege(current_user, Privilege::PERM_VIEW)
+ @roles = Role.find_all_by_scope((a)permission_object.class.name)
+ @tabs << {:name => 'Users',
+ :view => 'permissions',
+ :id => 'permissions',
+ :count => @pool.permissions.count}
+ end
details_tab_name = params[:details_tab].blank? ? 'deployments' :
params[:details_tab]
@details_tab = @tabs.find {|t| t[:id] == details_tab_name} ||
@tabs.first[:name].downcase
@deployments = @pool.deployments if @details_tab[:id] == 'deployments'
diff --git a/src/app/helpers/application_helper.rb
b/src/app/helpers/application_helper.rb
index 0135722..dc979c6 100644
--- a/src/app/helpers/application_helper.rb
+++ b/src/app/helpers/application_helper.rb
@@ -72,6 +72,7 @@ module ApplicationHelper
select_togle_opts = options[:show_select_toggle]
render :partial => 'layouts/filter_table', :locals => {
:form_header => options[:form_header] || :form_header,
+ :form_footer => options[:form_footer] || :form_footer,
# TODO - Right now saved_searches are not functional; this will need to be
expanded
:saved_searches => ["<option>All
#{_class.name.pluralize}</option>"],
:object_count => rows.count,
diff --git a/src/app/stylesheets/custom.scss b/src/app/stylesheets/custom.scss
index d019798..7b8d2cd 100644
--- a/src/app/stylesheets/custom.scss
+++ b/src/app/stylesheets/custom.scss
@@ -47,3 +47,7 @@
ul.deployment-array.small li.deployment {
height: 90px;
}
+
+.hidden {
+ display: none;
+}
diff --git a/src/app/views/layouts/_filter_table.haml
b/src/app/views/layouts/_filter_table.haml
index 0f98d0d..8a36b92 100644
--- a/src/app/views/layouts/_filter_table.haml
+++ b/src/app/views/layouts/_filter_table.haml
@@ -27,3 +27,7 @@
%th
= column[:name]
= rows.collect {|row| capture_haml(row, &block)}.to_s.html_safe
+
+ - if content_for? form_footer
+ %ul.obj_actions
+ = yield form_footer
diff --git a/src/app/views/permissions/_form.haml b/src/app/views/permissions/_form.haml
new file mode 100644
index 0000000..8c2debd
--- /dev/null
+++ b/src/app/views/permissions/_form.haml
@@ -0,0 +1,16 @@
+- content_for :form_footer do
+ = hidden_field_tag :permission_object_type, @permission_object.class.name
+ = hidden_field_tag :permission_object_id, @permission_object.id
+ = link_to 'Cancel', polymorphic_path(@permission_object,
+ :details_tab => :permissions,
+ :only_tab => true), :class => 'button
danger'
+ = restful_submit_tag "Grant Access", "create", permissions_path,
'POST', :id => 'save_button'
+= filter_table(@header, @users) do |user|
+ %tr{:class => cycle('nostripe','stripe')}
+ %td
+ -# - selected = params[:select] == 'all'
+ -# = check_box_tag "user_selected[]", user.id, selected, :id =>
"user_checkbox_#{user.id}"
+ %td= link_to user.login, user_path(user)
+ %td= user.last_name
+ %td= user.first_name
+ %td= select_tag "user_role_selected[]", options_for_select([['',
"#{user.id},"]] + @roles.map {|r| [ r.name, "#{user.id},#{r.id}" ] },
:disabled => @permission_object.permissions.where(:user_id=>user.id).collect {|p|
"#{user.id},#{p.role.id}"}), :id =>
"user_role_selected_#{user.id}"
diff --git a/src/app/views/permissions/_new.haml b/src/app/views/permissions/_new.haml
new file mode 100644
index 0000000..63d8125
--- /dev/null
+++ b/src/app/views/permissions/_new.haml
@@ -0,0 +1,14 @@
+%header.page-header
+ %h1{:class => controller.controller_name} Grant Access
+ #obj_actions.button-group
+ Return to
+ = link_to "#{(a)permission_object.name} #{(a)permission_object.class}",
polymorphic_path(@permission_object, :details_tab => :permissions, :only_tab =>
true), :class => 'button primary', :id => 'new_pool_button'
+ .corner
+
+%section.content-section.pools
+ Choose roles for users you would like to grant access to this
#{(a)permission_object.class}
+ %header
+ %h2 Users
+
+ .content
+ = render :partial => 'form'
diff --git a/src/app/views/permissions/_permissions.haml
b/src/app/views/permissions/_permissions.haml
new file mode 100644
index 0000000..cf0cf4f
--- /dev/null
+++ b/src/app/views/permissions/_permissions.haml
@@ -0,0 +1,24 @@
+- content_for :form_header do
+ - if check_privilege(Privilege::PERM_SET)
+ %li
+ = link_to "Grant Access", new_permission_path(:permission_object_type
=> @permission_object.class.name, :permission_object_id => @permission_object.id), {
:class => 'button primary', :id => 'new_permission_button'}
+ = restful_submit_tag "Revoke Access", "destroy",
multi_destroy_permissions_path, 'DELETE', :id => 'delete_button',
:class => 'button danger'
+ = restful_submit_tag "Edit", "multi_update",
multi_update_permissions_path, 'POST', :id => 'edit_button', :class
=> 'hidden'
+ .corner
+ = hidden_field_tag :permission_object_type, @permission_object.class.name
+ = hidden_field_tag :permission_object_id, @permission_object.id
+
+= filter_table(@permission_list_header, @permission_object.permissions) do |permission|
+ %tr{:class => cycle('nostripe','stripe')}
+ %td
+ - if check_privilege(Privilege::PERM_SET)
+ - selected = params[:select] == 'all'
+ = check_box_tag "permission_selected[]", permission.id, selected, :id
=> "permission_checkbox_#{permission.id}"
+ %td= link_to "#{permission.user.first_name} #{permission.user.last_name}",
user_path(permission.user)
+ - if check_privilege(Privilege::PERM_SET)
+ %td= select_tag "permission_role_selected[]",
options_for_select((a)roles.map {|r| [ r.name, "#{permission.id},#{r.id}" ] },
:selected => "#{permission.id},#{permission.role.id}", :disabled =>
@permission_object.permissions.where(["user_id = ? and role_id != ?",
permission.user_id, permission.role_id]).collect {|p|
"#{permission.id},#{p.role.id}"}), :id =>
"permission_role_selected_#{permission.id}"
+ :javascript
+ $("#permission_role_selected_#{permission.id}").change(function () {
$("#edit_button").click(); } );
+
+ -else
+ %td= permission.role.name
diff --git a/src/app/views/permissions/index.haml b/src/app/views/permissions/index.haml
new file mode 100644
index 0000000..229236b
--- /dev/null
+++ b/src/app/views/permissions/index.haml
@@ -0,0 +1 @@
+= render :partial => 'permissions'
diff --git a/src/app/views/permissions/new.haml b/src/app/views/permissions/new.haml
index 25bae8e..b40557d 100644
--- a/src/app/views/permissions/new.haml
+++ b/src/app/views/permissions/new.haml
@@ -1,19 +1 @@
-.conductor_form
- - if @permission.errors.any?
- = render 'layouts/error_messages', :object => @permission
- %h2
- Add new Permission for #{(a)permission_object.name}
- %br/
- = form_tag :action => 'create' do
- %ul
- %li
- %label
- User
- %span User to receive permission grant
- = select("permission", "user_id", @users.collect {|u| [
u.login, u.id ] }, { :include_blank => true })
- %li
- %label Role
- = select("permission", "role_id", @roles.collect {|r| [
r.name, r.id ] }, { :include_blank => true })
- = hidden_field :permission, :permission_object_type
- = hidden_field :permission, :permission_object_id
- = submit_tag "Save", :class => "submit"
+= render :partial => 'new'
diff --git a/src/app/views/pools/_permissions.haml
b/src/app/views/pools/_permissions.haml
index e44abc9..e73ced3 100644
--- a/src/app/views/pools/_permissions.haml
+++ b/src/app/views/pools/_permissions.haml
@@ -1,7 +1 @@
-%h3
- Permissions have not been implemented yet.
-
-:javascript
- Conductor.setupPrettyFilterURL(
- '#{url_for(:action => :show, :details_tab => 'permissions',
:view => 'filter' )}',
- '#{url_for(:action => :show, :details_tab => 'permissions',
:view => 'pretty' )}');
\ No newline at end of file
+= render :partial => 'permissions/permissions'
diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml
index 6c87532..c475943 100644
--- a/src/config/locales/en.yml
+++ b/src/config/locales/en.yml
@@ -5,6 +5,7 @@ en:
confirm_delete: "Are you sure you want to delete this user?"
index:
user_id: User ID
+ username: Username
last_name: Last Name
first_name: First Name
quota_used: Quota Used
@@ -34,6 +35,9 @@ en:
define_profiles: Define Profiles
define_locales: Define Locales
permissions: Permissions
+ role: Role
+ user: User
+ privileges: Privileges
general_settings: General Settings
new_user: New User
edit_user: Edit User
diff --git a/src/config/routes.rb b/src/config/routes.rb
index 78340bd..0482bc6 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -83,6 +83,8 @@ Conductor::Application.routes.draw do
resources :permissions do
collection do
get :list
+ delete :multi_destroy
+ post :multi_update
end
end
diff --git a/src/features/permission.feature b/src/features/permission.feature
index ee2d736..ae9a642 100644
--- a/src/features/permission.feature
+++ b/src/features/permission.feature
@@ -7,40 +7,50 @@ Feature: Manage Permissions
Given I am an authorised user
And I am logged in
And a user "testuser" exists
+ And a pool "PermissionPool" exists
Scenario: Create a new Permission
- Given I am on the permissions page
+ Given I am viewing the pool "PermissionPool"
+ When I follow link with ID "details_permissions"
And there is not a permission for the user "testuser"
- When I follow "Add a new permission record"
+ When I follow "Grant Access"
Then I should be on the new permission page
- And I should see "new Permission"
- When I select "testuser" from "permission[user_id]"
- And I select "Provider Creator" from "permission[role_id]"
- And I press "Save"
- Then I should be on the permissions page
- And I should see "Permission record added"
+ And I should see "Choose roles for users"
+ When I select "Pool User" role for the user "testuser"
+ And I press "Grant Access"
+ Then I should be on the page for the pool "PermissionPool"
+ And I should see "These User Roles were added"
And I should see "testuser"
Scenario: Create a second permission on a resource
- Given there is a permission for the user "testuser"
- And I am on the new permission page
- When I select "testuser" from "permission[user_id]"
- And I select "Provider Creator" from "permission[role_id]"
- And I press "Save"
- Then I should be on the permissions page
- And I should see "Permission record added"
+ Given there is a permission for the user "testuser" on the pool
"PermissionPool"
+ And I am viewing the pool "PermissionPool"
+ When I follow link with ID "details_permissions"
+ When I follow "Grant Access"
+ Then I should be on the new permission page
+ And I should see "Choose roles for users"
+ When I select "Pool Owner" role for the user "testuser"
+ And I press "Grant Access"
+ Then I should be on the page for the pool "PermissionPool"
+ And I should see "These User Roles were added"
And I should see "testuser"
Scenario: Attempt to duplicate a permission
- Given there is a permission for the user "testuser"
- And I am on the new permission page
- When I select "testuser" from "permission[user_id]"
- And I select "Administrator" from "permission[role_id]"
- And I press "Save"
- Then I should see "new Permission"
+ Given there is a permission for the user "testuser" on the pool
"PermissionPool"
+ And I am viewing the pool "PermissionPool"
+ When I follow link with ID "details_permissions"
+ When I follow "Grant Access"
+ Then I should be on the new permission page
+ And I should see "Choose roles for users"
+ When I select "Pool User" role for the user "testuser"
+ And I press "Grant Access"
+ Then I should be on the page for the pool "PermissionPool"
+ And I should see "Could not add these User Roles"
+ And I should see "testuser"
Scenario: Delete a permission
- Given there is a permission for the user "testuser"
- And I am on the permissions page
+ Given there is a permission for the user "testuser" on the pool
"PermissionPool"
+ And I am viewing the pool "PermissionPool"
+ When I follow link with ID "details_permissions"
When I delete the permission
- Then I should be on the permissions page
+ Then I should be on the page for the pool "PermissionPool"
diff --git a/src/features/step_definitions/permission_steps.rb
b/src/features/step_definitions/permission_steps.rb
index d2007f5..1f8ae6b 100644
--- a/src/features/step_definitions/permission_steps.rb
+++ b/src/features/step_definitions/permission_steps.rb
@@ -10,6 +10,17 @@ Given /^there is a permission for the user "([^\"]*)"$/
do |login|
@admin_permission = FactoryGirl.create(:admin_permission, :user_id => @user.id)
end
+Given /^there is a permission for the user "([^\"]*)" on the pool
"([^\"]*)"$/ do |login, pool_name|
+ @pool_user_permission = FactoryGirl.create(:pool_user_permission, :user_id =>
@user.id,
+ :permission_object =>
Pool.find_by_name(pool_name))
+end
+
Given /^I delete the permission$/ do
- click_button "delete_#{(a)admin_permission.id}"
+ check "permission_checkbox_#{(a)pool_user_permission.id}"
+ click_button "delete_button"
+end
+
+When /^(?:|I )select "([^"]*)" role for the user
"([^"]*)"$/ do |role_name, user_name|
+ user = User.find_by_login(user_name)
+ select(role_name, :from => "user_role_selected_#{user.id}")
end
--
1.7.6.4