obsolete.ChilliProject/app/models/principal.rb

139 lines
4.5 KiB
Ruby

#-- encoding: UTF-8
#-- copyright
# ChiliProject is a project management system.
#
# Copyright (C) 2010-2013 the ChiliProject Team
#
# 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; either version 2
# of the License, or (at your option) any later version.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
class Principal < ActiveRecord::Base
set_table_name "#{table_name_prefix}users#{table_name_suffix}"
has_many :members, :foreign_key => 'user_id', :dependent => :destroy
has_many :memberships, :class_name => 'Member', :foreign_key => 'user_id', :include => [ :project, :roles ], :conditions => "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}", :order => "#{Project.table_name}.name"
has_many :projects, :through => :memberships
# Groups and active users
named_scope :active, :conditions => "#{Principal.table_name}.type='Group' OR (#{Principal.table_name}.type='User' AND #{Principal.table_name}.status = 1)"
named_scope :like, lambda {|q|
s = "%#{q.to_s.strip.downcase}%"
{:conditions => ["LOWER(login) LIKE :s OR LOWER(firstname) LIKE :s OR LOWER(lastname) LIKE :s OR LOWER(mail) LIKE :s", {:s => s}],
:order => 'type, login, lastname, firstname, mail'
}
}
before_create :set_default_empty_values
def to_liquid
PrincipalDrop.new(self)
end
def name(formatter = nil)
to_s
end
def <=>(principal)
if self.class.name == principal.class.name
self.to_s.downcase <=> principal.to_s.downcase
else
# groups after users
principal.class.name <=> self.class.name
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)
def set_default_empty_values
self.login ||= ''
self.hashed_password ||= ''
self.firstname ||= ''
self.lastname ||= ''
self.mail ||= ''
true
end
end