Changeset 153

Show
Ignore:
Timestamp:
11/28/05 07:00:51 (3 years ago)
Author:
lazyatom
Message:

Merged from branches r152; pre-release

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/user_engine/README

    r97 r153  
    11= UserEngine: Login + Roles 
    22 
    3 The UserEngine extends the LoginEngine with a very, *very* simple implemntation of RBAC - role based access control. As well as the 'User' object, the UserEngine provides Permission objects, and Role objects. Each User can have many Roles, and each Role is assoociated with many Permissions. A Permission is simple a controller/action pair. A Role which is associated with some permission has access to that specific controller/action, i.e. and Role associated with the Permission object "user/home" will be allowed to call that action.  
     3The UserEngine extends the LoginEngine with a very, *very* simple implementation of RBAC - role based access control. As well as the 'User' object, the UserEngine provides Permission objects, and Role objects. Each User can have many Roles, and each Role is associated with many Permissions. A Permission is simple a controller/action pair. A Role which is associated with some permission has access to that specific controller/action, i.e. and Role associated with the Permission object "user/home" will be allowed to call that action.  
     4 
     5 
     6=== Not the One True RBAC system 
     7 
     8We'll make this point at the beginning, so there can be no doubt - this is *not* a full permission system. The UserEngine only controls which users have the right to hit which controller/action pairs. It will not control access to data at all, so for instance you cannot use it to give users the ability to edit only a subset of your data object (unless that subset is controlled via different controller actions). 
     9 
    410 
    511 
    612= Installing 
    713 
    8 0. Create your Rails application, set up your databases, grab the Engines plugin and the LoginEngine, and install them. 
    9  
    10 1. Install the UserEngine into your vendor/plugins directory 
    11  
    12 2. Modify your Engines.start call in config/environment.rb - if you have specifically specified which Engines to start, ensure that you add :user (or :user_engine). The important point here is to note that the UserEngine must be started *after* the LoginEngine, since it will override a small amount of the behaviour in the latter. The end of your environment.rb file should look something like this: 
    13  
    14                   Engines.start :login, :user 
    15  
    16          or 
    17  
    18                   Engines.start :login 
    19                   Engines.start :user 
    20  
    21          or simply: 
    22  
    23                   Engines.start # note that this use assumes that you haven't renamed the user_engine 
    24                                 # to anything which would come before 'login_engine' alphabetically 
    25  
    26  
    27 3. Edit your application.rb file so it looks something like the following (note the new <tt>include UserEngine</tt> and the changed +before_filter+): 
    28  
    29                         class ApplicationController < ActionController::Base 
    30                           include LoginEngine 
    31                           include UserEngine 
    32    
    33                           helper :user 
    34                           model :user 
    35    
    36                           before_filter :authorize_action 
    37                         end 
    38  
    39 4. Edit your application_helper.rb file: 
    40  
    41         module ApplicationHelper 
    42           include LoginEngine 
    43           include UserEngine 
    44         end 
    45  
    46 5. Since the UserEngine overrides some of the default behaviour in the LoginEngine, if you have made your own modifications within your app directory, you'll probably want to examine these changes to make sure that your own customisations will still operate as expected. You'll need to look at the following: 
     141. Create your Rails application, set up your databases, grab the Engines plugin and the LoginEngine, and install them. 
     15 
     162. Install the UserEngine into your vendor/plugins directory 
     17 
     183. Modify your Engines.start call in config/environment.rb - if you have specifically specified which Engines to start, ensure that you add :user (or :user_engine). The important point here is to note that the UserEngine must be started *after* the LoginEngine, since it will override a small amount of the behaviour in the latter. The end of your environment.rb file should look something like this: 
     19 
     20    Engines.start :login, :user 
     21 
     22  or 
     23 
     24    Engines.start :login 
     25    Engines.start :user 
     26 
     27  or simply: 
     28 
     29    Engines.start # note that this use assumes that you haven't renamed the user_engine 
     30                  # to anything which would come before 'login_engine' alphabetically 
     31 
     32 
     334. Edit your application.rb file so it looks something like the following (note the new <tt>include UserEngine</tt> and the changed +before_filter+): 
     34 
     35    class ApplicationController < ActionController::Base 
     36      include LoginEngine 
     37      include UserEngine 
     38 
     39      helper :user 
     40      model :user 
     41 
     42      before_filter :authorize_action 
     43    end 
     44 
     455. Edit your application_helper.rb file: 
     46 
     47    module ApplicationHelper 
     48      include LoginEngine 
     49      include UserEngine 
     50    end 
     51 
     526. Perform any configuration you might need. You'll probably want to set these values in environment.rb (before the call to Engines.start): 
     53 
     54    module UserEngine 
     55      config :admin_login, "the login name for your administrator user" 
     56      config :admin_email, "an email address for your administrator" 
     57      config :admin_password, "your initial admin password" 
     58    end 
     59 
     607. Initialize the database tables. You must ensure that the tables for the LoginEngine are present since this engine builds on top of them. You will probably get a warning if this is your first installation of the User Engine, indicating that you don't have an Admin role - that's fine, we'll be creating it later. You can either use the engine migrations by calling: 
     61 
     62    rake engine_migrate 
     63 
     64  to move all engines to their latest versions, or 
     65 
     66    rake engine_migrate ENGINE=user 
     67 
     68  to migrate only this engine. Alternatively, if you just want to load the full schema information for the User and LoginEngines, run 
     69 
     70    rake import_user_engine_schema 
     71 
     728. Run the rake task to install the default Roles and administrator user. This will also create a new user with the Admin role - the default login (if you didn't set it in step 6) is 'admin' and the password is 'testing'. Make sure you change it!: 
     73 
     74    rake bootstrap 
     75 
     769. The UserEngine includes a method to check whether or not the system roles created above are still intact. You should typically call this each time the server starts, by placing the following call at the bottom of your environment.rb: 
     77 
     78    UserEngine.check_system_roles 
     79 
     8010. The UserEngine provides a default stylesheet and a small javascript helper file (used in the Role#edit action), so you'll probably want to include the former and almost certainly the latter in your application's layout. Add the following lines: 
     81 
     82    <%= engine_stylesheet "user" %> 
     83    <%= engine_javascript "user" %> 
     84 
     8511. Remove any existing sessions (since they might interfere with the login process), and start the server and log using your administrator login and password (if you didn't set one explicitly in your configuration, the defaults are 'admin'/'testing' - make sure you change them!) and go to http://localhost:3000/user/list to see a list of all the users. From there you can create new users, view roles & permissions, and play around... 
     86 
     8712. Since the UserEngine overrides some of the default behaviour in the LoginEngine, if you have made your own modifications within your app directory, you'll probably want to examine these changes to make sure that your own customisations will still operate as expected. You'll need to look at the following: 
    4788 
    4889* The UserEngine's models/user.rb model will override the default given in LoginEngine. If you have your own app/models/user.rb file, you'll need to include UserEngine::AuthorizedUser in your file. 
    4990* The UserController#edit action has been overriden to know about Roles. See user_engine/app/user_controller.rb for details. 
    5091* Many new methods for administrating users, roles and permissions have been provided - again, see user_engine/app/user_controller.rb. 
    51 * If you have overriden any User views, look at the corresponding views in the UserEngine to see if there are any changes you wish to include in your own versions. 
    52  
    53 6. Perform any configuration you might need. You'll probably want to set these values in environment.rb (before the call to Engines.start): 
    54  
    55         module UserEngine 
    56                 config :admin_name, "the login name for your administrator user" 
    57                 config :admin_email, "an email address for your administrator" 
    58         end 
    59  
    60 7. Run the rake task to install the default Roles and administrator user: 
    61  
    62   rake bootstrap 
    63  
    64 8. Start the server and log in - go to http://localhost:3000/user/list to see a list of all the users... 
     92* If you have overridden any User views, look at the corresponding views in the UserEngine to see if there are any changes you wish to include in your own versions. 
     93 
     94 
     95 
     96 
     97 
     98 
     99= Configuration 
     100 
     101A number of configuration parameters are available to allow to you control 
     102how the data is stored, should you be unhappy with the defaults. These are 
     103outlined below. You should almost certainly customize the <tt>:admin_email</tt> 
     104value in your environment.rb file, i.e.: 
     105 
     106  module LoginEngine 
     107    config :salt, 'your salt value' 
     108  end 
     109  module UserEngine 
     110    config :admin_email, 'admin@megacorp.com' 
     111  end 
     112  Engines.start :login, :user 
     113 
     114 
     115=== Configuration Options 
     116 
     117+role_table+:: the name of the table to store Role objects in. Defaults to  
     118               "roles" (or "role" if you have disabled pluralization.) 
     119+permission_table+:: the name of the table to store Permission objects 
     120                     in. Defaults to "permissions" (or "permission" if 
     121                     you have disabled pluralization.) 
     122+user_role_table+:: the join table for users and roles. Defaults to  
     123                    <user_table>_<role_table>. (User table is specified in 
     124                    the LoginEngine configuration). 
     125+permission_role_table+:: the join table for roles and permissions. Defaults 
     126                          to <permission_table>_<role_table>. 
     127+guest_role_name+:: the name for the Guest Role. Defaults to "Guest". 
     128+user_role_name+:: the name for the User Role. Defaults to "User". 
     129+admin_role_name+:: the name for the Admin Role. Defaults to "Admin". 
     130+admin_login+:: the login ID for the initial Admin user. Defaults to "admin". 
     131+admin_email+:: the email address of the site administrator. Defaults to 
     132                "admin@your.company". 
     133+login_page+:: a Hash describing where the login page. Defaults to 
     134               {:controller => 'user', :action => 'login'} 
     135+steath+:: a boolean flag to indicate whether or not the system should 
     136           display helpful messages about authorized roles when they are 
     137           denied access to an action, or if it should simply deny the 
     138           user access without revealing which roles can access that action. 
     139           Defaults to false (i.e. DO show helpful messages).                
     140                
     141                
     142= Usage 
     143 
     144=== Users 
     145Once you have logged in as an administrator, you can go to /user/list to get a list of all users. Here you can also create new users (/user/new) and edit the details of the users in your system. 
     146 
     147If you edit a user (/user/edit_user/+id+), you can now not only change user details and passwords, but also specify which roles the user has. 
     148 
     149=== Roles 
     150 
     151Three distinct Role objects are initially created when you bootstrap the UserEngine 
     152 
     153* Guest, with permissions to login, signup and retrieve forgotten passwords 
     154* User, with permissions to logout, to to /user/home, change passwords and edit their own information 
     155* Admin, with permissions to edit all users, list users, edit all roles, edit permissions, and so on. 
     156 
     157New roles can easily be created at /role/new, where you can select exactly which permissions this role should have. A similar interface is presented in /role/edit/+id+. For instance, if you have a ReportController with the actions +view+ and +edit+, you might create two new Roles - 'ReportViewer' and ReportEditor'. The only permissions the ReportViewer has will be report/view, and the only permission assigned to ReportEditor is similarly report/edit. You can now assign the ReportViewer role to as many users as will need to be able to view reports, but only give the ReportEditor to users who should also be able to edit reports. 
     158 
     159It's worth noting that this point that if a user has the ability to edit other users (/user/edit_user), they will be able to assign Roles (including the Admin role) to anyone they please. Similarly, users who can edit roles (/role/edit) can add any permissions at all to any Role within the system. Therefore you (as the system administrator) must be *very* careful about allowing these permissions on any role other than Admin. 
     160 
     161In general, you should not give normal users *any* permissions other than the default ones, and permissions to any controllers specific to *your* application. 
     162 
     163=== Permissions 
     164 
     165While you can create permissions using the regular scaffold-style interface, it is better to avoid manually creating them if possible. Instead, a method is provided for automatically scanning your controllers and ensuring that there exists a Permission object for each controller-action pair. This method is <tt>Permission.sychronize_controllers</tt> (or just <tt>Permission.sync</tt> as a shorthand), and can be called either from the console, or as a rake task: 
     166 
     167  rake sync_permissions 
     168   
     169It may be worth noting that currently this method will deliberately *never* delete any permission objects from your system, even if the method is no longer present. 
     170 
     171== Helper methods 
     172 
     173The UserEngine provides several helpers which understand permissions and roles, to be used in your views. The two most important are outlined below. 
     174 
     175=== link_if_authorized(controller, action) 
     176 
     177<tt>link_if_authorized</tt> will produce a link to an action *only* if the currently logged-in user has permission to perform the given action. It can be passed options to show the text (without a link) if the user is not authorized, or to wrap the text in another HTML element (i.e an li element) if a link is to be produced. 
     178 
     179=== authorized?(controller, action) 
     180 
     181<tt>authorized?</tt> will simply return true or false to reflect the current user's authorization for the given action. This method can also take a block, which will only be performed if the user is authorized for the given action. In this manner you can control the display chunks of HTML or certain processing based on the permissions of the current user. 
     182 
     183 
     184= LICENSE 
     185 
     186Copyright (c) 2005 James Adam 
     187 
     188This is the MIT license, the license Ruby on Rails itself is licensed  
     189under. 
     190 
     191Permission is hereby granted, free of charge, to any person obtaining  
     192a copy of this software and associated documentation files (the  
     193"Software"), to deal in the Software without restriction, including  
     194without limitation the rights to use, copy, modify, merge, publish,  
     195distribute, sublicense, and/or sell copies of the Software, and to permit 
     196persons to whom the Software is furnished to do so, subject to the  
     197following conditions: 
     198 
     199The above copyright notice and this permission notice shall be included  
     200in all copies or substantial portions of the Software. 
     201 
     202THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     203OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     204MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     205IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     206CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     207TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     208OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
  • plugins/user_engine/app/controllers/permission_controller.rb

    r97 r153  
     1# Copyright (c) 2005 James Adam 
     2# 
     3# This is the MIT license, the license Ruby on Rails itself is licensed  
     4# under. 
     5# 
     6# Permission is hereby granted, free of charge, to any person obtaining  
     7# a copy of this software and associated documentation files (the  
     8# "Software"), to deal in the Software without restriction, including  
     9# without limitation the rights to use, copy, modify, merge, publish,  
     10# distribute, sublicense, and/or sell copies of the Software, and to permit 
     11# persons to whom the Software is furnished to do so, subject to the  
     12# following conditions: 
     13# 
     14# The above copyright notice and this permission notice shall be included  
     15# in all copies or substantial portions of the Software. 
     16# 
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     19# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     20# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     21# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     22# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     23# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
     24 
     25 
     26# The PermissionController provides methods for manipulating Permission 
     27# objects from the web interface. 
    128class PermissionController < ApplicationController 
    229 
    330  # We shouldn't accept GET requests that modify data. 
    4   verify :method => :post, :only => %w(create update destroy) 
     31  verify :method => :post, :only => %w(destroy) 
    532 
    6  
     33  # Will redirect to the list view 
    734  def index 
    835    redirect_to :action => "list" 
    936  end 
    1037 
     38  # Displays a paginated list of all Permission objects 
    1139  def list 
    1240    @content_columns = Permission.content_columns 
    13     @permission_pages, @permissions = paginate :permission, :per_page => 15 
     41    @permission_pages, @permissions = paginate :permission, :order => 'id', :per_page => 15 
    1442  end 
    1543 
     44  # Displays a single Permission object, by the id given. 
    1645  def show 
    1746    if (@permission = find_permission(params[:id])) 
     
    2251  end 
    2352 
     53  # Creates a new Permission object. Note that this is not the recommended 
     54  # way of creating Permission objects - instead you should use  
     55  # Permission.sync to add them automatically from your application 
    2456  def new 
    25     @permission = Permission.new 
    26   end 
    27  
    28   def create 
    29     @permission = Permission.new(@params[:permission]) 
    30     if @permission.save 
    31       flash[:notice] = 'Permission was successfully created.' 
    32       redirect_to :action => 'list' 
    33     else 
    34       render_action 'new' 
     57    case request.method 
     58      when :get 
     59        @permission = Permission.new 
     60      when :post 
     61        @permission = Permission.new(@params[:permission]) 
     62        if @permission.save 
     63          flash[:notice] = 'Permission was successfully created.' 
     64          redirect_to :action => 'list' 
     65        else 
     66          render_action 'new' 
     67        end       
    3568    end 
    3669  end 
    3770 
     71  # Edits a Permission object 
    3872  def edit 
    39     if (@permission = find_permission(params[:id])).nil? 
    40       redirect_back_or_default :action => 'list' 
     73    case request.method 
     74      when :get 
     75        if (@permission = find_permission(params[:id])).nil? 
     76          redirect_back_or_default :action => 'list' 
     77        end 
     78      when :post 
     79        if (@permission = find_permission(params[:id])) 
     80          if @permission.update_attributes(@params[:permission]) 
     81            flash[:notice] = 'Permission was successfully updated.' 
     82            redirect_to :action => 'show', :id => @permission 
     83          else 
     84            render_action 'edit' 
     85          end 
     86        else 
     87          redirect_back_or_default :action => 'list' 
     88        end               
    4189    end 
    4290  end 
    4391 
    44   def update 
    45     if (@permission = find_permission(params[:id])) 
    46       if @permission.update_attributes(@params[:permission]) 
    47         flash[:notice] = 'Permission was successfully updated.' 
    48         redirect_to :action => 'show', :id => @permission 
    49       else 
    50         render_action 'edit' 
    51       end 
    52     else 
    53       redirect_back_or_default :action => 'list' 
    54     end       
    55   end 
    56  
     92  # Destroys a Permission Object 
    5793  def destroy 
    5894    if (@permission = find_permission(params[:id])) 
    5995      @permission.destroy 
     96      flash[:notice] = "Permission '#{@permission.path}' deleted." 
    6097      redirect_to :action => 'list' 
    6198    else 
     
    64101  end 
    65102   
    66   private 
     103  protected 
     104    # A helper method to find Permission objects by ID, and insert 
     105    # appropriate error messages into the flash if it couldn't be 
     106    # found. 
    67107    def find_permission(id) 
    68108      begin 
  • plugins/user_engine/app/controllers/role_controller.rb

    r97 r153  
     1# Copyright (c) 2005 James Adam 
     2# 
     3# This is the MIT license, the license Ruby on Rails itself is licensed  
     4# under. 
     5# 
     6# Permission is hereby granted, free of charge, to any person obtaining  
     7# a copy of this software and associated documentation files (the  
     8# "Software"), to deal in the Software without restriction, including  
     9# without limitation the rights to use, copy, modify, merge, publish,  
     10# distribute, sublicense, and/or sell copies of the Software, and to permit 
     11# persons to whom the Software is furnished to do so, subject to the  
     12# following conditions: 
     13# 
     14# The above copyright notice and this permission notice shall be included  
     15# in all copies or substantial portions of the Software. 
     16# 
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     19# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     20# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     21# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     22# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     23# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
     24 
     25 
     26 
     27# The RoleController allows Role objects to be manipulated via the 
     28# web interface 
    129class RoleController < ApplicationController 
    230 
    331  # We shouldn't accept GET requests that modify data. 
    4   verify :method => :post, :only => %w(create update destroy) 
     32  verify :method => :post, :only => %w(destroy) 
    533   
     34  # Redirects to the list action 
    635  def index 
    736    redirect_to :action => 'list' 
    837  end 
    938 
     39  # Displays a paginated list of Role objects 
    1040  def list 
    1141    @content_columns = Role.content_columns 
     
    1343  end 
    1444 
     45  # Displays a single Role object by given id. 
    1546  def show 
    1647    if (@role = find_role(params[:id])) 
     
    3061  end 
    3162 
     63  # Creates a new Role object with the given parameters. 
    3264  def new 
    33     @role = Role.new 
    34   end 
    35  
    36   def create 
    37     @role = Role.new(params[:role]) 
    38     if @role.save 
    39       flash[:notice] = 'Role was successfully created.' 
    40       redirect_to :action => 'list' 
    41     else 
    42       render_action 'new' 
     65    case request.method 
     66      when :get 
     67        @role = Role.new 
     68      when :post 
     69        @role = Role.new(params[:role]) 
     70        if @role.save 
     71          flash[:notice] = 'Role was successfully created.' 
     72          redirect_to :action => 'list' 
     73        else 
     74          render_action 'new' 
     75        end       
    4376    end 
    4477  end 
    45  
     78   
     79  # Edit a Role object 
    4680  def edit 
    47     if (@role = find_role(params[:id])) 
    48       # load up the controllers 
    49       @all_permissions = Permission.find_all 
     81    case request.method 
     82      when :get 
     83        if (@role = find_role(params[:id])) 
     84          # load up the controllers 
     85          @all_permissions = Permission.find_all 
    5086     
    51       # split it up into controllers 
    52       @all_actions = {} 
    53       @all_permissions.each { |permission| 
    54         @all_actions[permission.controller] ||= [] 
    55         @all_actions[permission.controller] << permission 
    56       } 
    57     else 
    58       redirect_back_or_default :action => 'list' 
     87          # split it up into controllers 
     88          @all_actions = {} 
     89          @all_permissions.each { |permission| 
     90            @all_actions[permission.controller] ||= [] 
     91            @all_actions[permission.controller] << permission 
     92          } 
     93        else 
     94          redirect_back_or_default :action => 'list' 
     95        end 
     96      when :post 
     97        if (@role = find_role(params[:id])) 
     98          # update the action permissions 
     99          permission_keys = params.keys.select { |k| k =~ /^permissions_/ } 
     100          permissions = permission_keys.collect { |k| params[k] } 
     101           
     102          begin 
     103            permissions.collect! { |perm_id| Permission.find(perm_id) } 
     104     
     105            # just wipe them all and re-build 
     106            @role.permissions.clear 
     107     
     108            permissions.each { |perm| 
     109              if !@role.permissions.include?(perm) 
     110                @role.permissions << perm 
     111              end 
     112            } 
     113             
     114            # save the object     
     115            if @role.update_attributes(params[:role]) 
     116              flash[:notice] = 'Role was successfully updated.' 
     117              redirect_to :action => 'show', :id => @role 
     118            else 
     119              flash[:message] = 'The role could not be updated.' 
     120              render :action => 'edit' 
     121            end 
     122          rescue ActiveRecord::RecordNotFound => e 
     123            flash[:message] = 'Permission not found!' 
     124            render :action => 'edit' 
     125          end 
     126        else 
     127          redirect_back_or_default :action => 'list' 
     128        end        
    59129    end         
    60130  end 
    61131 
    62   def update 
    63     if (@role = find_role(params[:id])) 
    64       # update the action permissions 
    65       permission_keys = params.keys.select { |k| k =~ /^permissions_/ } 
    66       permissions = permission_keys.collect { |k| params[k] } 
    67       permissions.collect! { |perm_id| Permission.find(perm_id) } 
    68      
    69       # just wipe them all and re-build 
    70       @role.permissions.clear 
    71      
    72       permissions.each { |perm| 
    73         if !@role.permissions.include?(perm) 
    74           @role.permissions << perm 
    75         end 
    76       } 
    77      
    78       # save the object     
    79       if @role.update_attributes(params[:role]) 
    80         flash[:notice] = 'Role was successfully updated.' 
    81         redirect_to :action => 'show', :id => @role 
    82       else 
    83         render_action 'edit' 
    84       end 
    85     else 
    86       redirect_back_or_default :action => 'list' 
    87     end  
    88   end 
    89  
     132  # Destroy a given Role object 
    90133  def destroy 
    91134    if (@role = find_role(params[:id])) 
    92       @role.destroy 
    93       redirect_to :action => 'list' 
     135      begin 
     136        @role.destroy 
     137        flash[:notice] = "Role '#{@role.name}' has been deleted."  
     138        redirect_to :action => 'list' 
     139      rescue UserEngine::SystemProtectionError => e 
     140        flash[:message] = "Cannot destroy the system role '#{@role.name}'!" 
     141        redirect_to :action => 'list' 
     142      end 
    94143    else 
    95144      redirect_back_or_default :action => 'list' 
     
    97146  end 
    98147   
    99   private 
     148  protected 
    100149    # A convenience method to find a Role, and add any errors to the flash if 
    101150    # the Role is not found. 
  • plugins/user_engine/app/controllers/user_controller.rb

    r97 r153  
     1# Copyright (c) 2005 James Adam 
     2# 
     3# This is the MIT license, the license Ruby on Rails itself is licensed  
     4# under. 
     5# 
     6# Permission is hereby granted, free of charge, to any person obtaining  
     7# a copy of this software and associated documentation files (the  
     8# "Software"), to deal in the Software without restriction, including  
     9# without limitation the rights to use, copy, modify, merge, publish,  
     10# distribute, sublicense, and/or sell copies of the Software, and to permit 
     11# persons to whom the Software is furnished to do so, subject to the  
     12# following conditions: 
     13# 
     14# The above copyright notice and this permission notice shall be included  
     15# in all copies or substantial portions of the Software. 
     16# 
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     19# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     20# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     21# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     22# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     23# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
     24 
     25 
     26 
     27# The UserEngine UserController overrides the UserController from the 
     28# LoginEngine to give user management methods (list, edit_user, etc) 
    129class UserController < ApplicationController 
     30   
    231  # Ensure that these methods CANNOT be called via a GET request 
    332  verify :method => :post, :only => %w(edit_roles change_password_for_user delete_user) 
    433 
     34  # Displays a paginated list of Users 
    535  def list 
    636    @content_columns = user_content_columns_to_display     
     
    2050    if (@user = find_user(params[:id])) 
    2151      @all_roles = Role.find_all.select { |r| r.name != UserEngine.config(:guest_role_name) } 
    22       if request.method == :get 
    23         render :action => "edit" 
    24       else 
    25         @user.attributes = params[:user].delete_if { |k,v| not LoginEngine.config(:changeable_fields).include?(k) } 
    26         if @user.save 
    27           flash.now[:notice] = "Your details have been updated" 
    28         else 
    29           flash.now[:warning] = "Your details could not be updated!" 
    30         end 
    31         render :action => "edit" 
     52      case request.method 
     53        when :get 
     54        when :post 
     55          @user.attributes = params[:user].delete_if { |k,v| not LoginEngine.config(:changeable_fields).include?(k) } 
     56          if @user.save 
     57            flash.now[:notice] = "Details for user '#{@user.login}' have been updated" 
     58          else 
     59            flash.now[:warning] = "Details could not be updated!" 
     60          end 
    3261      end 
    3362    else 
     
    3665  end 
    3766   
     67  # Edit the roles for a given User object. 
    3868  # A user typically shouldn't be allowed to edit their own roles, since they could 
    3969  # assign themselves as Admins and then do anything. Therefore, keep this method 
     
    5080 
    5181          @user.save 
    52           flash[:notice] = "Roles updated for user '#{@user.login}'
     82          flash[:notice] = "Roles updated for user '#{@user.login}'.
    5383        end 
    5484      rescue 
    55         flash[:warning] = 'Your roles could not be edited at this time. Please retry.' 
     85        flash[:warning] = 'Roles could not be edited at this time. Please retry.' 
    5686      ensure 
    5787        redirect_to :back 
     
    6595  def change_password_for_user 
    6696    if (@user = find_user(params[:id])) 
    67       change_password_for(@user) 
    68     else 
    69       redirect_back_or_default :action => 'list' 
    70     end  
     97      do_change_password_for(@user) 
     98      flash[:notice] = "Password for user '#{@user.login}' has been updated." 
     99    end 
     100    redirect_back_or_default :action => 'list' 
    71101  end 
    72102 
    73   # Delete a user 
     103  # Delete an arbitrary user 
    74104  def delete_user 
    75105    if (@user = find_user(params[:id])) 
    76106      do_delete_user(@user) 
     107      flash[:notice] = "User '#{@user.login}' has been deleted." 
    77108    end 
    78     redirect_back_or_default :action => 'list' 
     109    redirect_to :action => 'list' 
    79110  end 
    80111 
     
    89120  end 
    90121 
    91    
     122  # Create a new User, skipping any verification by email. 
    92123  def new 
    93     if request.method == :get 
    94       @user = User.new 
    95       render 
    96       return true 
    97     else 
    98  
    99       @user = User.new(params[:user]) 
    100       begin 
    101         User.transaction(@user) do 
    102           @user.new_password = true 
    103           @user.verified = 1 # skip verification, because we are ADMIN! 
    104           if @user.save 
    105             flash[:notice] = 'User creation successful.' 
    106             redirect_to :back 
     124    case request.method 
     125      when :get 
     126        @user = User.new 
     127        render 
     128        return true 
     129      when :post 
     130        @user = User.new(params[:user]) 
     131        begin 
     132          User.transaction(@user) do 
     133            @user.new_password = true 
     134            @user.verified = 1 # skip verification, because we are ADMIN! 
     135            if @user.save 
     136              flash[:notice] = 'User creation successful.' 
     137              redirect_to :action => 'list' 
     138            end 
    107139          end 
     140        rescue Exception => e 
     141          flash.now[:notice] = nil 
     142          flash.now[:warning] = 'Error creating account: confirmation email not sent' 
     143          logger.error e 
    108144        end 
    109       rescue Exception => e 
    110         flash.now[:notice] = nil 
    111         flash.now[:warning] = 'Error creating account: confirmation email not sent' 
    112         logger.error e 
    113       end 
    114145    end 
    115146  end 
    116147 
    117148 
    118   private 
     149  protected 
     150    # A convenience method we can use to control the columns of the User object that 
     151    # we might ever to see, and hide all other ones. 
    119152    def user_content_columns_to_display 
    120153      # we don't want people to see the passwords (even though they) 
    121154      # are hashed up... 
    122       @content_columns = User.content_columns 
    123       @content_columns.delete_if { |c| ["salted_password", "salt", "security_token", "token_expiry"].include?(c.name) } 
     155      desired_columns = ["salted_password", "salt", "security_token", "token_expiry"] 
     156      User.content_columns.delete_if { |c| desired_columns.include?(c.name) } 
    124157    end 
    125158     
     
    130163        User.find(id) 
    131164      rescue ActiveRecord::RecordNotFound 
    132         flash[:message] = "There is no used with ID ##{id}" 
     165        flash[:message] = "There is no user with ID ##{id}" 
    133166        nil 
    134167      end 
  • plugins/user_engine/app/models/permission.rb

    r97 r153  
    1 #-------------------------------------------------------------------------- 
     1# Copyright (c) 2005 James Adam 
     2
     3# This is the MIT license, the license Ruby on Rails itself is licensed  
     4# under. 
     5
     6# Permission is hereby granted, free of charge, to any person obtaining  
     7# a copy of this software and associated documentation files (the  
     8# "Software"), to deal in the Software without restriction, including  
     9# without limitation the rights to use, copy, modify, merge, publish,  
     10# distribute, sublicense, and/or sell copies of the Software, and to permit 
     11# persons to whom the Software is furnished to do so, subject to the  
     12# following conditions: 
     13
     14# The above copyright notice and this permission notice shall be included  
     15# in all copies or substantial portions of the Software. 
     16
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     19# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     20# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     21# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     22# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     23# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
     24 
     25 
     26 
    227# The Permission class is simply a database representation of each 
    328# controller/action pair. The association between a Role and a Permission 
    429# instance indicates that such a Role is authorised to call the 
    530# controller/action pair which that Permission represents. 
    6 #-------------------------------------------------------------------------- 
    731class Permission < ActiveRecord::Base 
     32   
    833  set_table_name UserEngine.config(:permission_table) 
    934  has_and_belongs_to_many :roles, :join_table => UserEngine.config(:permission_role_table) 
    10    
     35 
     36  validates_presence_of :controller, :action 
     37 
     38  #-- 
     39  # Class methods 
     40  #++ 
    1141  class << self  
     42     
    1243    # Ensure that the table has one entry for each controller/action pair 
    1344    def synchronize_with_controllers 
     
    2253      # outside of the framework environment...? 
    2354      controller_files += Dir[Engines.config(:root) + "/**/app/controllers/**/*_controller.rb"] 
    24      
    25       # TODO: plugins. difficult because there's no fixed path... 
    2655     
    2756      # we need to load all the controllers... 
     
    4069    end 
    4170 
    42     #def self.sync() self.synchronize_with_controllers end # alias 
     71    #-- 
     72    # A shorthand alias 
     73    #++ 
    4374    alias :sync :synchronize_with_controllers 
    4475   
    4576  end 
    4677   
    47   # def controller 
    48   #   raise Exception.new("Empty path in Permission ##{id}!") if path.empty? 
    49   #   @controller ||= path.split("/")[0..-2].join("/") 
    50   # end 
    51    
    52   # def action 
    53   #   raise Exception.new("Empty path in Permission ##{id}!") if path.empty? 
    54   #   @action ||= path.split("/").last 
    55   # end 
    56    
     78  # Returns the full path which this Permission object represents 
    5779  def path 
    5880    [controller, action].join("/") 
  • plugins/user_engine/app/models/role.rb

    r97 r153  
    1 #-------------------------------------------------------------------------- 
     1# Copyright (c) 2005 James Adam 
     2
     3# This is the MIT license, the license Ruby on Rails itself is licensed  
     4# under. 
     5
     6# Permission is hereby granted, free of charge, to any person obtaining  
     7# a copy of this software and associated documentation files (the  
     8# "Software"), to deal in the Software without restriction, including  
     9# without limitation the rights to use, copy, modify, merge, publish,  
     10# distribute, sublicense, and/or sell copies of the Software, and to permit 
     11# persons to whom the Software is furnished to do so, subject to the  
     12# following conditions: 
     13
     14# The above copyright notice and this permission notice shall be included  
     15# in all copies or substantial portions of the Software. 
     16
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
     18# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
     19# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  
     20# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  
     21# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  
     22# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
     23# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
     24 
     25 
     26 
    227# The Role class represents an abstract set of allowable behaviours within 
    328# an application. Each Role is associated with a number of Permissions (or 
    429# controller/action objects), and such associations indicate what actions 
    530# users using this application are allowed to perform. 
    6 #-------------------------------------------------------------------------- 
    731class Role < ActiveRecord::Base 
    832  has_and_belongs_to_many :users, :class_name => "User", :join_table => UserEngine.config(:user_role_table) 
    933  has_and_belongs_to_many :permissions, :join_table => UserEngine.config(:permission_role_table) 
     34 
     35  validates_length_of :name, :minimum => 3 
     36  validates_uniqueness_of :name 
     37   
     38  # there can only be one omnipotent role. 
     39  def validate_on_create 
     40    if self.omnipotent? && Role.find_by_omnipotent(1) 
     41      errors.add_to_base("There can only be one omnipotent role.") 
     42    end