diff options
Diffstat (limited to 'app/models/user.rb')
-rw-r--r-- | app/models/user.rb | 167 |
1 files changed, 163 insertions, 4 deletions
diff --git a/app/models/user.rb b/app/models/user.rb index 1bc070f040d..55d75892fc4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -34,8 +34,6 @@ # class User < ActiveRecord::Base - include Account - devise :database_authenticatable, :token_authenticatable, :lockable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable @@ -51,7 +49,6 @@ class User < ActiveRecord::Base has_many :groups, class_name: "Group", foreign_key: :owner_id has_many :keys, dependent: :destroy - has_many :projects, through: :users_projects has_many :users_projects, dependent: :destroy has_many :issues, foreign_key: :author_id, dependent: :destroy has_many :notes, foreign_key: :author_id, dependent: :destroy @@ -70,6 +67,8 @@ class User < ActiveRecord::Base message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } + validate :namespace_uniq, if: ->(user) { user.username_changed? } + before_validation :generate_password, on: :create before_save :ensure_authentication_token alias_attribute :private_token, :authentication_token @@ -77,11 +76,14 @@ class User < ActiveRecord::Base delegate :path, to: :namespace, allow_nil: true, prefix: true # Scopes - scope :not_in_project, ->(project) { where("id not in (:ids)", ids: project.users.map(&:id) ) } scope :admins, where(admin: true) scope :blocked, where(blocked: true) scope :active, where(blocked: false) + scope :alphabetically, order('name ASC') + # + # Class methods + # class << self def filter filter_name case filter_name @@ -93,6 +95,14 @@ class User < ActiveRecord::Base end end + def not_in_project(project) + if project.users.present? + where("id not in (:ids)", ids: project.users.map(&:id) ) + else + scoped + end + end + def without_projects where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') end @@ -118,9 +128,158 @@ class User < ActiveRecord::Base end end + # + # Instance methods + # def generate_password if self.force_random_password self.password = self.password_confirmation = Devise.friendly_token.first(8) end end + + def namespace_uniq + namespace_name = self.username + if Namespace.find_by_path(namespace_name) + self.errors.add :username, "already exist" + end + end + + # Namespaces user has access to + def namespaces + namespaces = [] + + # Add user account namespace + namespaces << self.namespace if self.namespace + + # Add groups you can manage + namespaces += if admin + Group.all + else + groups.all + end + namespaces + end + + # Groups where user is an owner + def owned_groups + groups + end + + # Groups user has access to + def authorized_groups + @authorized_groups ||= begin + groups = Group.where(id: self.authorized_projects.pluck(:namespace_id)).all + groups = groups + self.groups + groups.uniq + end + end + + + # Projects user has access to + def authorized_projects + project_ids = users_projects.pluck(:project_id) + project_ids = project_ids | owned_projects.pluck(:id) + Project.where(id: project_ids) + end + + # Projects in user namespace + def personal_projects + Project.personal(self) + end + + # Projects where user is an owner + def owned_projects + Project.where("(projects.namespace_id IN (:namespaces)) OR + (projects.namespace_id IS NULL AND projects.creator_id = :user_id)", + namespaces: namespaces.map(&:id), user_id: self.id) + end + + # Team membership in personal projects + def tm_in_personal_projects + UsersProject.where(project_id: personal_projects.map(&:id), user_id: self.id) + end + + # Returns a string for use as a Gitolite user identifier + # + # Note that Gitolite 2.x requires the following pattern for users: + # + # ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$ + def identifier + # Replace non-word chars with underscores, then make sure it starts with + # valid chars + email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '') + end + + def is_admin? + admin + end + + def require_ssh_key? + keys.count == 0 + end + + def can_create_project? + projects_limit > personal_projects.count + end + + def can_create_group? + is_admin? + end + + def abilities + @abilities ||= begin + abilities = Six.new + abilities << Ability + abilities + end + end + + def can? action, subject + abilities.allowed?(self, action, subject) + end + + def first_name + name.split.first unless name.blank? + end + + def cared_merge_requests + MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id) + end + + # Remove user from all projects and + # set blocked attribute to true + def block + users_projects.find_each do |membership| + return false unless membership.destroy + end + + self.blocked = true + save + end + + def projects_limit_percent + return 100 if projects_limit.zero? + (personal_projects.count.to_f / projects_limit) * 100 + end + + def recent_push project_id = nil + # Get push events not earlier than 2 hours ago + events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours) + events = events.where(project_id: project_id) if project_id + + # Take only latest one + events = events.recent.limit(1).first + end + + def projects_sorted_by_activity + authorized_projects.sorted_by_activity + end + + def several_namespaces? + namespaces.size > 1 + end + + def namespace_id + namespace.try :id + end end |