Scott Seago
2009-May-14 18:55 UTC
[Ovirt-devel] [PATCH server] PermissionController now uses the service layer
Signed-off-by: Scott Seago <sseago at redhat.com> --- src/app/controllers/permission_controller.rb | 129 +++++++++++--------------- src/app/models/permission.rb | 4 + src/app/services/permission_service.rb | 102 ++++++++++++++++++++ 3 files changed, 160 insertions(+), 75 deletions(-) create mode 100644 src/app/services/permission_service.rb diff --git a/src/app/controllers/permission_controller.rb b/src/app/controllers/permission_controller.rb index d4c3fb5..55e7942 100644 --- a/src/app/controllers/permission_controller.rb +++ b/src/app/controllers/permission_controller.rb @@ -18,105 +18,84 @@ # also available at http://www.gnu.org/copyleft/gpl.html. class PermissionController < ApplicationController + include PermissionService # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) verify :method => :post, :only => [ :destroy, :create ], :redirect_to => { :controller => 'dashboard' } - def redirect_to_parent - redirect_to :controller => @permission.pool.get_controller, :action => 'show', :id => @permission.pool_id - end - def show - @permission = Permission.find(params[:id]) - set_perms(@permission.pool) - authorize_action(Privilege::PERM_VIEW) + svc_show(params[:id]) end def new - @permission = Permission.new( { :pool_id => params[:pool_id]}) - @perms = @permission.pool.permissions - @pool = Pool.find(params[:pool_id]) - filter = @pool.permissions.collect{ |permission| permission.uid } - @users = Account.names(filter) + svc_new(params[:pool_id]) + @users = Account.names(@permission.pool.permissions.collect{ |permission| + permission.uid }) @roles = Role.find(:all).collect{ |role| [role.name, role.id] } - set_perms(@permission.pool) - # admin permission required to view permissions - if authorize_action(Privilege::PERM_SET) - render :layout => 'popup' - end + render :layout => 'popup' end def create - @permission = Permission.new(params[:permission]) - set_perms(@permission.pool) - if authorize_action(Privilege::PERM_SET) - begin - @permission.save_with_new_children - render :json => { :object => "permission", :success => true, - :alert => "created User Permissions for #{@permission.uid}." } - rescue - render :json => { :object => "permission", :success => false, - :alert => "Error adding user: #{$!}" } - end - end + alert = svc_create(params[:permission]) + render :json => { :object => "vm", :success => true, :alert => alert } end - #FIXME: we need permissions checks. user must have permission. We also need to fail - # for pools that aren't currently empty def update_roles - role = params[:role_id] - permission_ids_str = params[:permission_ids] - permission_ids = permission_ids_str.split(",").collect {|x| x.to_i} - - begin - Permission.transaction do - permissions = Permission.find(:all, :conditions => "id in (#{permission_ids.join(', ')})") - permissions.each do |permission| - permission.update_role(role) if permission.is_primary? - end + permission_ids = params[:permission_ids].split(",") + role_id = params[:role_id] + successes = [] + failures = {} + permission_ids.each do |permission_id| + begin + svc_update_role(permission_id, role_id) + successes << @permission + rescue PermissionError => perm_error + failures[@permission] = perm_error.message + rescue ActionError => ex + failures[@permission] = ex.message + rescue Exception => ex + failures[@permission] = ex.message end - render :json => { :object => "permission", :success => true, - :alert => "User roles were successfully updated." } - rescue - render :json => { :object => "permission", :success => false, - :alert => "Error updating user roles: #{$!}" } end + unless failures.empty? + raise PartialSuccessError.new("Update roles for some Permission records", + failures, successes) + end + render :json => { :object => "permission", :success => true, + :alert => "Permission roles were successfully updated." } end - #FIXME: we need permissions checks. user must have permission. We also need to fail - # for pools that aren't currently empty def delete - permission_ids_str = params[:permission_ids] - permission_ids = permission_ids_str.split(",").collect {|x| x.to_i} - - begin - Permission.transaction do - permissions = Permission.find(:all, :conditions => "id in (#{permission_ids.join(', ')})") - permissions.each do |permission| - permission.destroy if permission.is_primary? - end + permission_ids = params[:permission_ids].split(",") + successes = [] + failures = {} + permission_ids.each do |permission_id| + begin + svc_destroy(permission_id) + successes << @permission + rescue PermissionError => perm_error + failures[@permission] = perm_error.message + rescue Exception => ex + failures[@permission] = ex.message end - render :json => { :object => "permission", :success => true, - :alert => "User roles were successfully deleted." } - rescue - render :json => { :object => "permission", :success => false, - :alert => "Error deleting user roles." } end + unless failures.empty? + raise PartialSuccessError.new("Delete failed for some Permission records", + failures, successes) + end + render :json => { :object => "permission", :success => true, + :alert => "Permission records were successfully deleted." } end def destroy - @permission = Permission.find(params[:id]) - set_perms(@permission.pool) - if authorize_action(Privilege::PERM_SET) - pool = @permission.pool - if @permission.destroy - if pool - flash[:notice] = "<strong>#{@permission.uid}</strong> permissions were revoked successfully" - redirect_to :controller => pool.get_controller, :action => 'show', :id => pool.id - else - redirect_to :controller => 'dashboard', :action => 'list' - end - end - end + alert = svc_destroy(params[:id]) + render :json => { :object => "vm", :success => true, :alert => alert } + end + + # FIXME: remove these when service transition is complete. these are here + # to keep from running permissions checks and other setup steps twice + def tmp_pre_update + end + def tmp_authorize_admin end end diff --git a/src/app/models/permission.rb b/src/app/models/permission.rb index 2567b08..f74a11a 100644 --- a/src/app/models/permission.rb +++ b/src/app/models/permission.rb @@ -50,7 +50,10 @@ class Permission < ActiveRecord::Base def grid_id id.to_s + "_" + (is_primary? ? "1" : "0") end + # only update role for primary permissions, return false (and do nothing) + # for inherited permissions def update_role(new_role) + return false unless is_primary? self.transaction do self.role_id = new_role self.save! @@ -59,6 +62,7 @@ class Permission < ActiveRecord::Base permission.save! end end + true end def save_with_new_children self.transaction do diff --git a/src/app/services/permission_service.rb b/src/app/services/permission_service.rb new file mode 100644 index 0000000..2e02a69 --- /dev/null +++ b/src/app/services/permission_service.rb @@ -0,0 +1,102 @@ +# +# Copyright (C) 2009 Red Hat, Inc. +# Written by Scott Seago <sseago at redhat.com>, +# David Lutterkort <lutter at redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. +# Mid-level API: Business logic around individual permissions +module PermissionService + + include ApplicationService + + # Load the Permission with +id+ for viewing + # + # === Instance variables + # [<tt>@permission</tt>] stores the Permission with +id+ + # === Required permissions + # [<tt>Privilege::PERM_VIEW</tt>] on permission's Pool + def svc_show(id) + lookup(id,Privilege::PERM_VIEW) + end + + # Load the Permission with +id+ for editing + # + # === Instance variables + # [<tt>@permission</tt>] stores the Permission with +id+ + # === Required permissions + # [<tt>Privilege::PERM_SET</tt>] on permission's Pool + def svc_modify(id) + lookup(id,Privilege::PERM_SET) + end + + # Load a new Permission for creating + # + # === Instance variables + # [<tt>@permission</tt>] loads a new Permission object into memory + # === Required permissions + # [<tt>Privilege::PERM_SET</tt>] for the permission's Pool as specified by + # +pool_id+ + def svc_new(pool_id) + @permission = Permission.new( { :pool_id => pool_id}) + authorized!(Privilege::PERM_SET, at permission.pool) + end + + # Save a new Permission record + # + # === Instance variables + # [<tt>@permission</tt>] the newly saved Permission record + # === Required permissions + # [<tt>Privilege::PERM_SET</tt>] for the permission's Pool + def svc_create(perm_hash) + @permission = Permission.new(perm_hash) + authorized!(Privilege::PERM_SET, @permission.pool) + @permission.save_with_new_children + return "created User Permissions for #{@permission.uid}." + end + + # Destroys for the Permission with +id+ + # + # === Instance variables + # [<tt>@permission</tt>] stores the Permission with +id+ + # === Required permissions + # [<tt>Privilege::PERM_SET</tt>] for the Permission's Pool + def svc_destroy(id) + lookup(id,Privilege::PERM_SET) + @permission.destroy + return "Permission record was successfully deleted." + end + + # Updates the role for a user permission. + # + # === Instance variables + # [<tt>@permission</tt>] stores the Permission with +id+ + # === Required permissions + # [<tt>Privilege::PERM_SET</tt>] for the Permission's Pool + def svc_update_role(id, role_id) + lookup(id,Privilege::PERM_SET) + unless @permission.update_role(role_id) + raise ActionError.new("Inherited permissions cannot be modified directly.") + end + return "User Role updated for permission record" + end + + private + def lookup(id, priv) + @permission = Permission.find(id) + authorized!(priv, at permission.pool) + end + +end -- 1.6.0.6