[Ovirt-devel] [PATCH server 05/10] PermissionController now uses the service layer

Scott Seago sseago at redhat.com
Tue May 19 14:23:12 UTC 2009


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




More information about the ovirt-devel mailing list