2011-10-29 16:19:11 +04:00
|
|
|
#-- encoding: UTF-8
|
2011-05-30 00:11:52 +04:00
|
|
|
#-- copyright
|
|
|
|
# ChiliProject is a project management system.
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2012-01-03 23:36:40 +04:00
|
|
|
# Copyright (C) 2010-2012 the ChiliProject Team
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2011-05-30 00:11:52 +04:00
|
|
|
# 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.
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2011-05-30 00:11:52 +04:00
|
|
|
# See doc/COPYRIGHT.rdoc for more details.
|
|
|
|
#++
|
|
|
|
|
2009-09-20 18:06:57 +04:00
|
|
|
class Principal < ActiveRecord::Base
|
2010-04-17 16:14:52 +04:00
|
|
|
set_table_name "#{table_name_prefix}users#{table_name_suffix}"
|
2009-09-20 18:06:57 +04:00
|
|
|
|
|
|
|
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)"
|
2011-05-30 22:52:25 +04:00
|
|
|
|
|
|
|
named_scope :like, lambda {|q|
|
2009-09-20 18:06:57 +04:00
|
|
|
s = "%#{q.to_s.strip.downcase}%"
|
2009-12-12 09:18:45 +03:00
|
|
|
{:conditions => ["LOWER(login) LIKE :s OR LOWER(firstname) LIKE :s OR LOWER(lastname) LIKE :s OR LOWER(mail) LIKE :s", {:s => s}],
|
2009-12-12 09:18:40 +03:00
|
|
|
:order => 'type, login, lastname, firstname, mail'
|
2009-09-20 18:06:57 +04:00
|
|
|
}
|
|
|
|
}
|
2011-05-30 22:52:25 +04:00
|
|
|
|
2010-01-30 13:24:23 +03:00
|
|
|
before_create :set_default_empty_values
|
2010-09-10 22:46:23 +04:00
|
|
|
|
2011-04-27 00:17:18 +04:00
|
|
|
def to_liquid
|
|
|
|
PrincipalDrop.new(self)
|
|
|
|
end
|
|
|
|
|
2010-09-10 22:46:23 +04:00
|
|
|
def name(formatter = nil)
|
|
|
|
to_s
|
|
|
|
end
|
|
|
|
|
2009-09-20 18:06:57 +04:00
|
|
|
def <=>(principal)
|
2009-12-12 14:20:26 +03:00
|
|
|
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
|
2009-09-20 18:06:57 +04:00
|
|
|
end
|
2011-05-30 22:52:25 +04:00
|
|
|
|
2011-04-19 22:33:53 +04:00
|
|
|
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
|
|
|
|
|
2010-01-30 13:24:23 +03:00
|
|
|
protected
|
2011-05-30 22:52:25 +04:00
|
|
|
|
2010-01-30 13:24:23 +03:00
|
|
|
# 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
|
2009-09-20 18:06:57 +04:00
|
|
|
end
|