summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/admin/groups_controller.rb9
-rw-r--r--app/controllers/groups_controller.rb7
-rw-r--r--app/models/group.rb6
-rw-r--r--app/models/project.rb5
-rw-r--r--app/models/users_project.rb2
-rw-r--r--app/views/admin/groups/show.html.haml61
-rw-r--r--app/views/groups/_new_group_member.html.haml18
-rw-r--r--app/views/groups/people.html.haml4
-rw-r--r--config/routes.rb2
-rw-r--r--features/admin/groups.feature7
-rw-r--r--features/group/group.feature6
-rw-r--r--features/steps/admin/admin_groups.rb38
-rw-r--r--features/steps/group/group.rb20
-rw-r--r--features/steps/shared/paths.rb4
-rw-r--r--lib/gitlab/regex.rb4
15 files changed, 173 insertions, 20 deletions
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index a492e66611f..54c69138a3a 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -1,5 +1,5 @@
class Admin::GroupsController < AdminController
- before_filter :group, only: [:edit, :show, :update, :destroy, :project_update]
+ before_filter :group, only: [:edit, :show, :update, :destroy, :project_update, :project_teams_update]
def index
@groups = Group.order('name ASC')
@@ -12,6 +12,8 @@ class Admin::GroupsController < AdminController
@projects = @projects.not_in_group(@group) if @group.projects.present?
@projects = @projects.all
@projects.reject!(&:empty_repo?)
+
+ @users = User.active
end
def new
@@ -65,6 +67,11 @@ class Admin::GroupsController < AdminController
redirect_to :back, notice: 'Group was successfully updated.'
end
+ def project_teams_update
+ @group.add_users_to_project_teams(params[:user_ids], params[:project_access])
+ redirect_to [:admin, @group], notice: 'Users was successfully added.'
+ end
+
def destroy
@group.destroy
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index c82edb4c168..6646b10ca48 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -53,9 +53,16 @@ class GroupsController < ApplicationController
if @project
@team_member = @project.users_projects.new
+ else
+ @team_member = UsersProject.new
end
end
+ def team_members
+ @group.add_users_to_project_teams(params[:user_ids], params[:project_access])
+ redirect_to people_group_path(@group), notice: 'Users was successfully added.'
+ end
+
protected
def group
diff --git a/app/models/group.rb b/app/models/group.rb
index b668f5560ab..5022fcf48f6 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -12,6 +12,12 @@
#
class Group < Namespace
+ def add_users_to_project_teams(user_ids, project_access)
+ projects.each do |project|
+ project.add_users_ids_to_team(user_ids, project_access)
+ end
+ end
+
def users
users = User.joins(:users_projects).where(users_projects: {project_id: project_ids})
users = users << owner
diff --git a/app/models/project.rb b/app/models/project.rb
index c2986707667..bfab009e94a 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -64,7 +64,9 @@ class Project < ActiveRecord::Base
# Validations
validates :owner, presence: true
validates :description, length: { within: 0..2000 }
- validates :name, presence: true, length: { within: 0..255 }
+ validates :name, presence: true, length: { within: 0..255 },
+ format: { with: Gitlab::Regex.project_name_regex,
+ message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :path, presence: true, length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
@@ -80,6 +82,7 @@ class Project < ActiveRecord::Base
scope :public_only, where(private_flag: false)
scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.projects.map(&:id) ) }
scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
+ scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
diff --git a/app/models/users_project.rb b/app/models/users_project.rb
index 3d76a4df037..34377aa5e66 100644
--- a/app/models/users_project.rb
+++ b/app/models/users_project.rb
@@ -33,6 +33,8 @@ class UsersProject < ActiveRecord::Base
delegate :name, :email, to: :user, prefix: true
+ scope :in_project, ->(project) { where(project_id: project.id) }
+
class << self
def import_team(source_project, target_project)
UsersProject.without_repository_callback do
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 41f6d9b3516..d289d9d50c2 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -44,25 +44,56 @@
%div
= f.submit 'Change Owner', class: "btn danger"
= link_to "Cancel", "#", class: "btn change-owner-cancel-link"
-%fieldset
- %legend Projects (#{@group.projects.count})
- %table
- %thead
+
+- if @group.projects.any?
+ %fieldset
+ %legend Projects (#{@group.projects.count})
+ %table
+ %thead
+ %tr
+ %th Project name
+ %th Path
+ %th Users
+ %th.cred Danger Zone!
+ - @group.projects.each do |project|
+ %tr
+ %td
+ = link_to project.name_with_namespace, [:admin, project]
+ %td
+ %span.monospace= project.path_with_namespace + ".git"
+ %td= project.users.count
+ %td.bgred
+ = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+
+ = form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
+ %table.zebra-striped
+ %thead
+ %tr
+ %th Users
+ %th Project Access:
+
+ - @group.users.each do |u|
+ %tr{class: "user_#{u.id}"}
+ %td.name= link_to u.name, admin_user_path(u)
+ %td.projects_access
+ - u.projects.in_namespace(@group).each do |project|
+ - u_p = u.users_projects.in_project(project).first
+ %span
+ = project.name
+ = link_to "(#{ u_p.project_access_human })", edit_admin_team_member_path(u_p)
%tr
- %th Project name
- %th Path
- %th Users
- %th.cred Danger Zone!
- - @group.projects.each do |project|
+ %td.input= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+ %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
+
%tr
+ %td= submit_tag 'Add user to projects in group', class: "btn primary"
%td
- = link_to project.name_with_namespace, [:admin, project]
- %td
- %span.monospace= project.path_with_namespace + ".git"
- %td= project.users.count
- %td.bgred
- = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
+ Read more about project permissions
+ %strong= link_to "here", help_permissions_path, class: "vlink"
+- else
+ %fieldset
+ %legend Group is empty
= form_tag project_update_admin_group_path(@group), class: "bulk_import", method: :put do
%fieldset
diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml
new file mode 100644
index 00000000000..75023057512
--- /dev/null
+++ b/app/views/groups/_new_group_member.html.haml
@@ -0,0 +1,18 @@
+= form_for @team_member, as: :team_member, url: team_members_group_path(@group) do |f|
+ %fieldset
+ %legend= "New Team member(s) for projects in #{@group.name}"
+
+ %h6 1. Choose people you want in the team
+ .clearfix
+ = f.label :user_ids, "People"
+ .input= select_tag(:user_ids, options_from_collection_for_select(User.active, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
+
+ %h6 2. Set access level for them
+ .clearfix
+ = f.label :project_access, "Project Access"
+ .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
+
+ .form-actions
+ = hidden_field_tag :redirect_to, people_group_path(@group)
+ = f.submit 'Add', class: "btn save-btn"
+
diff --git a/app/views/groups/people.html.haml b/app/views/groups/people.html.haml
index be3dd7a4d78..091f68756c3 100644
--- a/app/views/groups/people.html.haml
+++ b/app/views/groups/people.html.haml
@@ -2,8 +2,8 @@
.span3
= render 'people_filter'
.span9
- - if @project && can?(current_user, :manage_group, @group)
- = render "new_member"
+ - if can?(current_user, :manage_group, @group)
+ = render (@project ? "new_member" : "new_group_member")
.ui-box
%h5
Team
diff --git a/config/routes.rb b/config/routes.rb
index 4317962f607..4a02bd9f809 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -47,6 +47,7 @@ Gitlab::Application.routes.draw do
resources :groups, constraints: { id: /[^\/]+/ } do
member do
put :project_update
+ put :project_teams_update
delete :remove_project
end
end
@@ -102,6 +103,7 @@ Gitlab::Application.routes.draw do
get :merge_requests
get :search
get :people
+ post :team_members
end
end
diff --git a/features/admin/groups.feature b/features/admin/groups.feature
index e5eab8e6ecb..28f35e3a831 100644
--- a/features/admin/groups.feature
+++ b/features/admin/groups.feature
@@ -1,6 +1,8 @@
Feature: Admin Groups
Background:
Given I sign in as an admin
+ And I have group with projects
+ And Create gitlab user "John"
And I visit admin groups page
Scenario: Create a group
@@ -8,3 +10,8 @@ Feature: Admin Groups
And submit form with new group info
Then I should be redirected to group page
And I should see newly created group
+
+ Scenario: Add user into projects in group
+ When I visit admin group page
+ When I select user "John" from user list as "Reporter"
+ Then I should see "John" in team list in every project as "Reporter"
diff --git a/features/group/group.feature b/features/group/group.feature
index 07308112270..580f7e44002 100644
--- a/features/group/group.feature
+++ b/features/group/group.feature
@@ -17,3 +17,9 @@ Feature: Groups
Given project from group has merge requests assigned to me
When I visit group merge requests page
Then I should see merge requests from this group assigned to me
+
+ Scenario: I should add user to projects in Group
+ Given I have new user "John"
+ When I visit group people page
+ And I select user "John" from list with role "Reporter"
+ Then I should see user "John" in team list
diff --git a/features/steps/admin/admin_groups.rb b/features/steps/admin/admin_groups.rb
index 5386f473320..0271348eb1d 100644
--- a/features/steps/admin/admin_groups.rb
+++ b/features/steps/admin/admin_groups.rb
@@ -3,10 +3,26 @@ class AdminGroups < Spinach::FeatureSteps
include SharedPaths
include SharedActiveTab
+ When 'I visit admin group page' do
+ visit admin_group_path(current_group)
+ end
+
When 'I click new group link' do
click_link "New Group"
end
+ And 'I have group with projects' do
+ @group = create(:group)
+ @project = create(:project, group: @group)
+ @event = create(:closed_issue_event, project: @project)
+
+ @project.add_access current_user, :admin
+ end
+
+ And 'Create gitlab user "John"' do
+ create(:user, :name => "John")
+ end
+
And 'submit form with new group info' do
fill_in 'group_name', :with => 'gitlab'
click_button "Create group"
@@ -19,5 +35,27 @@ class AdminGroups < Spinach::FeatureSteps
Then 'I should be redirected to group page' do
current_path.should == admin_group_path(Group.last)
end
+
+ When 'I select user "John" from user list as "Reporter"' do
+ user = User.find_by_name("John")
+ within "#new_team_member" do
+ select user.name, :from => "user_ids"
+ select "Reporter", :from => "project_access"
+ end
+ click_button "Add user to projects in group"
+ end
+
+ Then 'I should see "John" in team list in every project as "Reporter"' do
+ user = User.find_by_name("John")
+ projects_with_access = find(".user_#{user.id} .projects_access")
+ projects_with_access.should have_link("Reporter")
+ end
+
+ protected
+
+ def current_group
+ @group ||= Group.first
+ end
+
end
diff --git a/features/steps/group/group.rb b/features/steps/group/group.rb
index 4de260ec33e..02a1dd13505 100644
--- a/features/steps/group/group.rb
+++ b/features/steps/group/group.rb
@@ -9,7 +9,7 @@ class Groups < Spinach::FeatureSteps
end
And 'I have group with projects' do
- @group = create(:group)
+ @group = create(:group, owner: current_user)
@project = create(:project, group: @group)
@event = create(:closed_issue_event, project: @project)
@@ -32,6 +32,24 @@ class Groups < Spinach::FeatureSteps
end
end
+ Given 'I have new user "John"' do
+ create(:user, name: "John")
+ end
+
+ And 'I select user "John" from list with role "Reporter"' do
+ user = User.find_by_name("John")
+ within "#new_team_member" do
+ select user.name, :from => "user_ids"
+ select "Reporter", :from => "project_access"
+ end
+ click_button "Add"
+ end
+
+ Then 'I should see user "John" in team list' do
+ projects_with_access = find(".ui-box .well-list")
+ projects_with_access.should have_content("John")
+ end
+
Given 'project from group has issues assigned to me' do
create :issue,
project: project,
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index a12576288df..bd43ba6b3dc 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -21,6 +21,10 @@ module SharedPaths
visit merge_requests_group_path(current_group)
end
+ When 'I visit group people page' do
+ visit people_group_path(current_group)
+ end
+
# ----------------------------------------
# Dashboard
# ----------------------------------------
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index a3f38b1c360..e0fb47da17b 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -6,6 +6,10 @@ module Gitlab
default_regex
end
+ def project_name_regex
+ default_regex
+ end
+
def path_regex
default_regex
end