diff --git a/app/models/principal.rb b/app/models/principal.rb index 3c390bb2..ada2cfaa 100644 --- a/app/models/principal.rb +++ b/app/models/principal.rb @@ -48,6 +48,82 @@ class Principal < ActiveRecord::Base end end + def active? + true + end + + def logged? + true # TODO: should all principals default to logged or not? + end + + # Return true if the user is allowed to do the specified action on a specific context + # Action can be: + # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') + # * a permission Symbol (eg. :edit_project) + # Context can be: + # * a project : returns true if user is allowed to do the specified action on this project + # * a group of projects : returns true if user is allowed on every project + # * nil with options[:global] set : check if user has at least one role allowed for this action, + # or falls back to Non Member / Anonymous permissions depending if the user is logged + def allowed_to?(action, context, options={}) + if context && context.is_a?(Project) + # No action allowed on archived projects + return false unless context.active? + # No action allowed on disabled modules + return false unless context.allows_to?(action) + # Admin users are authorized for anything else + return true if admin? + + roles = roles_for_project(context) + return false unless roles + roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)} + + elsif context && context.is_a?(Array) + # Authorize if user is authorized on every element of the array + context.map do |project| + allowed_to?(action,project,options) + end.inject do |memo,allowed| + memo && allowed + end + elsif options[:global] + # Admin users are always authorized + return true if admin? + + # authorize if user has at least one role that has this permission + roles = memberships.collect {|m| m.roles}.flatten.uniq + roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action)) + else + false + end + end + + # Is the user allowed to do the specified action on any project? + # See allowed_to? for the actions and valid options. + def allowed_to_globally?(action, options) + allowed_to?(action, nil, options.reverse_merge(:global => true)) + end + + # Return user's roles for project + def roles_for_project(project) + roles = [] + # No role on archived projects + return roles unless project && project.active? + if logged? + # Find project membership + membership = memberships.detect {|m| m.project_id == project.id} + if membership + roles = membership.roles + else + @role_non_member ||= Role.non_member + roles << @role_non_member + end + else + @role_anonymous ||= Role.anonymous + roles << @role_anonymous + end + roles + end + protected # Make sure we don't try to insert NULL values (see #4632) diff --git a/app/models/user.rb b/app/models/user.rb index 49a9bf4f..63296e8b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -345,27 +345,6 @@ class User < Principal !logged? end - # Return user's roles for project - def roles_for_project(project) - roles = [] - # No role on archived projects - return roles unless project && project.active? - if logged? - # Find project membership - membership = memberships.detect {|m| m.project_id == project.id} - if membership - roles = membership.roles - else - @role_non_member ||= Role.non_member - roles << @role_non_member - end - else - @role_anonymous ||= Role.anonymous - roles << @role_anonymous - end - roles - end - # Return true if the user is a member of project def member_of?(project) !roles_for_project(project).detect {|role| role.member?}.nil? @@ -388,53 +367,6 @@ class User < Principal @projects_by_role end - # Return true if the user is allowed to do the specified action on a specific context - # Action can be: - # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') - # * a permission Symbol (eg. :edit_project) - # Context can be: - # * a project : returns true if user is allowed to do the specified action on this project - # * a group of projects : returns true if user is allowed on every project - # * nil with options[:global] set : check if user has at least one role allowed for this action, - # or falls back to Non Member / Anonymous permissions depending if the user is logged - def allowed_to?(action, context, options={}) - if context && context.is_a?(Project) - # No action allowed on archived projects - return false unless context.active? - # No action allowed on disabled modules - return false unless context.allows_to?(action) - # Admin users are authorized for anything else - return true if admin? - - roles = roles_for_project(context) - return false unless roles - roles.detect {|role| (context.is_public? || role.member?) && role.allowed_to?(action)} - - elsif context && context.is_a?(Array) - # Authorize if user is authorized on every element of the array - context.map do |project| - allowed_to?(action,project,options) - end.inject do |memo,allowed| - memo && allowed - end - elsif options[:global] - # Admin users are always authorized - return true if admin? - - # authorize if user has at least one role that has this permission - roles = memberships.collect {|m| m.roles}.flatten.uniq - roles.detect {|r| r.allowed_to?(action)} || (self.logged? ? Role.non_member.allowed_to?(action) : Role.anonymous.allowed_to?(action)) - else - false - end - end - - # Is the user allowed to do the specified action on any project? - # See allowed_to? for the actions and valid options. - def allowed_to_globally?(action, options) - allowed_to?(action, nil, options.reverse_merge(:global => true)) - end - safe_attributes 'login', 'firstname', 'lastname',