summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorJames Lopez <james.lopez@vodafone.com>2015-11-03 11:11:56 +0000
committerJames Lopez <james.lopez@vodafone.com>2015-11-03 11:11:56 +0000
commit1b14bc59570a625365fef232f8c57919f76b3e2a (patch)
treeb1c125a96e844aedfc183ff3874bd74871f0c7af /app
parent6aa9c21ac0e3f4860f9021718900326ea0575151 (diff)
downloadgitlab-ce-1b14bc59570a625365fef232f8c57919f76b3e2a.tar.gz
refactored permissions and added update_project_member ability logic. Also refactored owner methods to a concern.
Diffstat (limited to 'app')
-rw-r--r--app/models/ability.rb18
-rw-r--r--app/models/concerns/has_owners.rb31
-rw-r--r--app/models/group.rb22
-rw-r--r--app/models/member.rb8
-rw-r--r--app/models/project.rb2
5 files changed, 57 insertions, 24 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb
index b72178fa126..5beead0b75d 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -15,6 +15,7 @@ class Ability
when "Group" then group_abilities(user, subject)
when "Namespace" then namespace_abilities(user, subject)
when "GroupMember" then group_member_abilities(user, subject)
+ when "ProjectMember" then project_member_abilities(user, subject)
else []
end.concat(global_abilities(user))
end
@@ -316,6 +317,23 @@ class Ability
rules
end
+ def project_member_abilities(user, subject)
+ rules = []
+ target_user = subject.user
+ project = subject.project
+ can_manage = project_abilities(user, project).include?(:admin_project_member)
+
+ if can_manage && (user != target_user)
+ rules << :update_project_member
+ rules << :destroy_project_member
+ end
+
+ if !project.last_owner?(user) && (can_manage || (user == target_user))
+ rules << :destroy_project_member
+ end
+ rules
+ end
+
def abilities
@abilities ||= begin
abilities = Six.new
diff --git a/app/models/concerns/has_owners.rb b/app/models/concerns/has_owners.rb
new file mode 100644
index 00000000000..735b2071721
--- /dev/null
+++ b/app/models/concerns/has_owners.rb
@@ -0,0 +1,31 @@
+# == Owners concern
+#
+# Contains owners functionality for groups
+#
+module HasOwners
+ extend ActiveSupport::Concern
+
+ def owners
+ @owners ||= my_members.owners.includes(:user).map(&:user)
+ end
+
+ def my_members
+ raise NotImplementedError, "Expected my_members to be defined in #{self.class.name}"
+ end
+
+ def add_owner(user, current_user = nil)
+ add_user(user, Gitlab::Access::OWNER, current_user)
+ end
+
+ def has_owner?(user)
+ owners.include?(user)
+ end
+
+ def has_master?(user)
+ members.masters.where(user_id: user).any?
+ end
+
+ def last_owner?(user)
+ has_owner?(user) && owners.size == 1
+ end
+end
diff --git a/app/models/group.rb b/app/models/group.rb
index 465c22d23ac..c9806f6fd6f 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -19,8 +19,10 @@ require 'file_size_validator'
class Group < Namespace
include Gitlab::ConfigHelper
include Referable
+ include HasOwners
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
+ alias_method :my_members, :group_members
has_many :users, through: :group_members
validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? }
@@ -63,10 +65,6 @@ class Group < Namespace
end
end
- def owners
- @owners ||= group_members.owners.includes(:user).map(&:user)
- end
-
def add_users(user_ids, access_level, current_user = nil)
user_ids.each do |user_id|
Member.add_user(self.group_members, user_id, access_level, current_user)
@@ -93,22 +91,6 @@ class Group < Namespace
add_user(user, Gitlab::Access::MASTER, current_user)
end
- def add_owner(user, current_user = nil)
- add_user(user, Gitlab::Access::OWNER, current_user)
- end
-
- def has_owner?(user)
- owners.include?(user)
- end
-
- def has_master?(user)
- members.masters.where(user_id: user).any?
- end
-
- def last_owner?(user)
- has_owner?(user) && owners.size == 1
- end
-
def members
group_members
end
diff --git a/app/models/member.rb b/app/models/member.rb
index 4651c8fff37..c565ee6bbce 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -82,8 +82,7 @@ class Member < ActiveRecord::Base
member.invite_email = user
end
- project = members.first.respond_to?(:project)? members.first.project : nil
- if can_update_member?(current_user, member, project)
+ if can_update_member?(current_user, member)
member.created_by ||= current_user
member.access_level = access_level
@@ -93,9 +92,10 @@ class Member < ActiveRecord::Base
private
- def can_update_member?(current_user, member, project)
+ def can_update_member?(current_user, member)
!current_user || current_user.can?(:update_group_member, member) ||
- (project && current_user.can?(:admin_project_member, project))
+ (member.respond_to?(:project) &&
+ current_user.can?(:update_project_member, member))
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 74b89aad499..79b7a6457d7 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -41,6 +41,7 @@ class Project < ActiveRecord::Base
include Sortable
include AfterCommitQueue
include CaseSensitivity
+ include HasOwners
extend Gitlab::ConfigHelper
extend Enumerize
@@ -114,6 +115,7 @@ class Project < ActiveRecord::Base
has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy
has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
+ alias_method :my_members, :project_members
has_many :users, through: :project_members
has_many :deploy_keys_projects, dependent: :destroy
has_many :deploy_keys, through: :deploy_keys_projects