Commit 65b9768ccfbdc3de682d66430601cf3af1b2a2f8
1 parent
edd2143d
Exists in
master
and in
4 other branches
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
Showing
12 changed files
with
32 additions
and
66 deletions
Show diff stats
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 < Namespace | @@ -16,14 +16,12 @@ class Group < 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 < Namespace | @@ -36,20 +34,19 @@ class Group < 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 < ActiveRecord::Base | @@ -20,7 +20,7 @@ class Namespace < 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 < ActiveRecord::Base | @@ -249,10 +249,10 @@ class Project < 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 < ActiveRecord::Base | @@ -276,10 +276,6 @@ class Project < 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 < ActiveRecord::Base | @@ -135,7 +135,7 @@ class User < 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 |