Commit 65b9768ccfbdc3de682d66430601cf3af1b2a2f8

Authored by Dmitriy Zaporozhets
1 parent edd2143d

Group ownership completely based on users_groups relation now

Before we have only owner_id to determine group owner
With multiple owners per group we should get rid of owner_id in group.
So from now @group.owner will always be nil but
@group.owners return an actual array of users who can admin this group
app/controllers/admin/groups_controller.rb
@@ -20,9 +20,9 @@ class Admin::GroupsController < Admin::ApplicationController @@ -20,9 +20,9 @@ class Admin::GroupsController < Admin::ApplicationController
20 def create 20 def create
21 @group = Group.new(params[:group]) 21 @group = Group.new(params[:group])
22 @group.path = @group.name.dup.parameterize if @group.name 22 @group.path = @group.name.dup.parameterize if @group.name
23 - @group.owner = current_user  
24 23
25 if @group.save 24 if @group.save
  25 + @group.add_owner(current_user)
26 redirect_to [:admin, @group], notice: 'Group was successfully created.' 26 redirect_to [:admin, @group], notice: 'Group was successfully created.'
27 else 27 else
28 render "new" 28 render "new"
@@ -30,14 +30,7 @@ class Admin::GroupsController < Admin::ApplicationController @@ -30,14 +30,7 @@ class Admin::GroupsController < Admin::ApplicationController
30 end 30 end
31 31
32 def update 32 def update
33 - group_params = params[:group].dup  
34 - owner_id =group_params.delete(:owner_id)  
35 -  
36 - if owner_id  
37 - @group.change_owner(User.find(owner_id))  
38 - end  
39 -  
40 - if @group.update_attributes(group_params) 33 + if @group.update_attributes(params[:group])
41 redirect_to [:admin, @group], notice: 'Group was successfully updated.' 34 redirect_to [:admin, @group], notice: 'Group was successfully updated.'
42 else 35 else
43 render "edit" 36 render "edit"
app/controllers/groups_controller.rb
@@ -21,9 +21,9 @@ class GroupsController < ApplicationController @@ -21,9 +21,9 @@ class GroupsController < ApplicationController
21 def create 21 def create
22 @group = Group.new(params[:group]) 22 @group = Group.new(params[:group])
23 @group.path = @group.name.dup.parameterize if @group.name 23 @group.path = @group.name.dup.parameterize if @group.name
24 - @group.owner = current_user  
25 24
26 if @group.save 25 if @group.save
  26 + @group.add_owner(current_user)
27 redirect_to @group, notice: 'Group was successfully created.' 27 redirect_to @group, notice: 'Group was successfully created.'
28 else 28 else
29 render action: "new" 29 render action: "new"
app/controllers/profiles/groups_controller.rb
@@ -8,8 +8,8 @@ class Profiles::GroupsController < ApplicationController @@ -8,8 +8,8 @@ class Profiles::GroupsController < ApplicationController
8 def leave 8 def leave
9 @users_group = group.users_groups.where(user_id: current_user.id).first 9 @users_group = group.users_groups.where(user_id: current_user.id).first
10 10
11 - if group.owner == current_user  
12 - redirect_to(profile_groups_path, alert: "You can't leave group. You must transfer it to another owner before leaving.") 11 + if group.last_owner?(current_user)
  12 + redirect_to(profile_groups_path, alert: "You can't leave group. You must add at least one more owner to it.")
13 else 13 else
14 @users_group.destroy 14 @users_group.destroy
15 redirect_to(profile_groups_path, info: "You left #{group.name} group.") 15 redirect_to(profile_groups_path, info: "You left #{group.name} group.")
app/models/ability.rb
@@ -79,7 +79,7 @@ class Ability @@ -79,7 +79,7 @@ class Ability
79 rules << project_admin_rules 79 rules << project_admin_rules
80 end 80 end
81 81
82 - if project.group && project.group.owners.include?(user) 82 + if project.group && project.group.has_owner?(user)
83 rules << project_admin_rules 83 rules << project_admin_rules
84 end 84 end
85 85
@@ -159,7 +159,7 @@ class Ability @@ -159,7 +159,7 @@ class Ability
159 end 159 end
160 160
161 # Only group owner and administrators can manage group 161 # Only group owner and administrators can manage group
162 - if group.owners.include?(user) || user.admin? 162 + if group.has_owner?(user) || user.admin?
163 rules << [ 163 rules << [
164 :manage_group, 164 :manage_group,
165 :manage_namespace 165 :manage_namespace
app/models/group.rb
@@ -16,14 +16,12 @@ class Group &lt; Namespace @@ -16,14 +16,12 @@ class Group &lt; Namespace
16 has_many :users_groups, dependent: :destroy 16 has_many :users_groups, dependent: :destroy
17 has_many :users, through: :users_groups 17 has_many :users, through: :users_groups
18 18
19 - after_create :add_owner  
20 -  
21 def human_name 19 def human_name
22 name 20 name
23 end 21 end
24 22
25 def owners 23 def owners
26 - @owners ||= (users_groups.owners.map(&:user) << owner).uniq 24 + @owners ||= users_groups.owners.map(&:user)
27 end 25 end
28 26
29 def add_users(user_ids, group_access) 27 def add_users(user_ids, group_access)
@@ -36,20 +34,19 @@ class Group &lt; Namespace @@ -36,20 +34,19 @@ class Group &lt; Namespace
36 self.users_groups.create(user_id: user.id, group_access: group_access) 34 self.users_groups.create(user_id: user.id, group_access: group_access)
37 end 35 end
38 36
39 - def change_owner(user)  
40 - self.owner = user  
41 - membership = users_groups.where(user_id: user.id).first 37 + def add_owner(user)
  38 + self.add_user(user, UsersGroup::OWNER)
  39 + end
42 40
43 - if membership  
44 - membership.update_attributes(group_access: UsersGroup::OWNER)  
45 - else  
46 - add_owner  
47 - end 41 + def has_owner?(user)
  42 + owners.include?(user)
48 end 43 end
49 44
50 - private 45 + def last_owner?(user)
  46 + has_owner?(user) && owners.size == 1
  47 + end
51 48
52 - def add_owner  
53 - self.add_users([owner.id], UsersGroup::OWNER) 49 + def members
  50 + users_groups
54 end 51 end
55 end 52 end
app/models/namespace.rb
@@ -20,7 +20,7 @@ class Namespace &lt; ActiveRecord::Base @@ -20,7 +20,7 @@ class Namespace &lt; ActiveRecord::Base
20 has_many :projects, dependent: :destroy 20 has_many :projects, dependent: :destroy
21 belongs_to :owner, class_name: "User" 21 belongs_to :owner, class_name: "User"
22 22
23 - validates :owner, presence: true 23 + validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
24 validates :name, presence: true, uniqueness: true, 24 validates :name, presence: true, uniqueness: true,
25 length: { within: 0..255 }, 25 length: { within: 0..255 },
26 format: { with: Gitlab::Regex.name_regex, 26 format: { with: Gitlab::Regex.name_regex,
app/models/project.rb
@@ -249,10 +249,10 @@ class Project &lt; ActiveRecord::Base @@ -249,10 +249,10 @@ class Project &lt; ActiveRecord::Base
249 end 249 end
250 250
251 def owner 251 def owner
252 - if namespace  
253 - namespace_owner 252 + if group
  253 + group
254 else 254 else
255 - creator 255 + namespace.try(:owner)
256 end 256 end
257 end 257 end
258 258
@@ -276,10 +276,6 @@ class Project &lt; ActiveRecord::Base @@ -276,10 +276,6 @@ class Project &lt; ActiveRecord::Base
276 end 276 end
277 end 277 end
278 278
279 - def namespace_owner  
280 - namespace.try(:owner)  
281 - end  
282 -  
283 def path_with_namespace 279 def path_with_namespace
284 if namespace 280 if namespace
285 namespace.path + '/' + path 281 namespace.path + '/' + path
app/models/user.rb
@@ -135,7 +135,7 @@ class User &lt; ActiveRecord::Base @@ -135,7 +135,7 @@ class User &lt; ActiveRecord::Base
135 # Remove user from all groups 135 # Remove user from all groups
136 user.users_groups.find_each do |membership| 136 user.users_groups.find_each do |membership|
137 # skip owned resources 137 # skip owned resources
138 - next if membership.group.owners.include?(user) 138 + next if membership.group.last_owner?(user)
139 139
140 return false unless membership.destroy 140 return false unless membership.destroy
141 end 141 end
app/services/system_hooks_service.rb
@@ -23,13 +23,15 @@ class SystemHooksService @@ -23,13 +23,15 @@ class SystemHooksService
23 23
24 case model 24 case model
25 when Project 25 when Project
  26 + owner = model.owner
  27 +
26 data.merge!({ 28 data.merge!({
27 name: model.name, 29 name: model.name,
28 path: model.path, 30 path: model.path,
29 path_with_namespace: model.path_with_namespace, 31 path_with_namespace: model.path_with_namespace,
30 project_id: model.id, 32 project_id: model.id,
31 - owner_name: model.owner.name,  
32 - owner_email: model.owner.email 33 + owner_name: owner.name,
  34 + owner_email: owner.respond_to?(:email) ? owner.email : nil
33 }) 35 })
34 when User 36 when User
35 data.merge!({ 37 data.merge!({
app/views/admin/groups/index.html.haml
@@ -31,11 +31,8 @@ @@ -31,11 +31,8 @@
31 31
32 .clearfix.light.append-bottom-10 32 .clearfix.light.append-bottom-10
33 %span 33 %span
34 - %b Owner:  
35 - - if group.owner  
36 - = link_to group.owner_name, admin_user_path(group.owner)  
37 - - else  
38 - (deleted) 34 + %b Members:
  35 + %span.badge= group.members.size
39 \| 36 \|
40 %span 37 %span
41 %b Projects: 38 %b Projects:
app/views/admin/groups/show.html.haml
@@ -25,26 +25,6 @@ @@ -25,26 +25,6 @@
25 = @group.description 25 = @group.description
26 26
27 %li 27 %li
28 - %span.light Owned by:  
29 - %strong  
30 - - if @group.owner  
31 - = link_to @group.owner_name, admin_user_path(@group.owner)  
32 - - else  
33 - (deleted)  
34 - .pull-right  
35 - = link_to "#", class: "btn btn-small change-owner-link" do  
36 - %i.icon-edit  
37 - Change owner  
38 - %li.change-owner-holder.hide.bgred  
39 - .form-holder  
40 - %strong.cred New Owner:  
41 - = form_for [:admin, @group] do |f|  
42 - = users_select_tag(:"group[owner_id]")  
43 - .prepend-top-10  
44 - = f.submit 'Change Owner', class: "btn btn-remove"  
45 - = link_to "Cancel", "#", class: "btn change-owner-cancel-link"  
46 -  
47 - %li  
48 %span.light Created at: 28 %span.light Created at:
49 %strong 29 %strong
50 = @group.created_at.stamp("March 1, 1999") 30 = @group.created_at.stamp("March 1, 1999")
@@ -92,4 +72,5 @@ @@ -92,4 +72,5 @@
92 = link_to user.name, admin_user_path(user) 72 = link_to user.name, admin_user_path(user)
93 %span.pull-right.light 73 %span.pull-right.light
94 = member.human_access 74 = member.human_access
95 - 75 + = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
  76 + %i.icon-minus.icon-white
app/views/admin/projects/show.html.haml
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 %span.light Owned by: 25 %span.light Owned by:
26 %strong 26 %strong
27 - if @project.owner 27 - if @project.owner
28 - = link_to @project.owner_name, admin_user_path(@project.owner) 28 + = link_to @project.owner_name, [:admin, @project.owner]
29 - else 29 - else
30 (deleted) 30 (deleted)
31 31