Commit 82499a4cbfdd9605312322fea80b76f034230b1b

Authored by Andrey Kumanyaev
Committed by Dmitriy Zaporozhets
1 parent 8a86fe7b

Admin teams section added

app/controllers/admin/teams_controller.rb 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +class Admin::TeamsController < AdminController
  2 + before_filter :user_team,
  3 + only: [ :edit, :show, :update, :destroy,
  4 + :delegate_projects, :relegate_project,
  5 + :add_members, :remove_member ]
  6 +
  7 + def index
  8 + @teams = UserTeam.order('name ASC')
  9 + @teams = @teams.search(params[:name]) if params[:name].present?
  10 + @teams = @teams.page(params[:page]).per(20)
  11 + end
  12 +
  13 + def show
  14 + @projects = Project.scoped
  15 + @projects = @projects.without_team(@team) if @team.projects.any?
  16 + #@projects.reject!(&:empty_repo?)
  17 +
  18 + @users = User.active
  19 + @users = @users.not_in_team(@team) if @team.members.any?
  20 + @users = UserDecorator.decorate @users
  21 + end
  22 +
  23 + def new
  24 + @team = UserTeam.new
  25 + end
  26 +
  27 + def edit
  28 + end
  29 +
  30 + def create
  31 + @team = UserTeam.new(params[:user_team])
  32 + @team.path = @team.name.dup.parameterize if @team.name
  33 + @team.owner = current_user
  34 +
  35 + if @team.save
  36 + redirect_to admin_team_path(@team), notice: 'UserTeam was successfully created.'
  37 + else
  38 + render action: "new"
  39 + end
  40 + end
  41 +
  42 + def update
  43 + user_team_params = params[:user_team].dup
  44 + owner_id = user_team_params.delete(:owner_id)
  45 +
  46 + if owner_id
  47 + @team.owner = User.find(owner_id)
  48 + end
  49 +
  50 + if @team.update_attributes(user_team_params)
  51 + redirect_to admin_team_path(@team), notice: 'UserTeam was successfully updated.'
  52 + else
  53 + render action: "edit"
  54 + end
  55 + end
  56 +
  57 + def destroy
  58 + @team.destroy
  59 +
  60 + redirect_to admin_user_teams_path, notice: 'UserTeam was successfully deleted.'
  61 + end
  62 +
  63 + def delegate_projects
  64 + unless params[:project_ids].blank?
  65 + project_ids = params[:project_ids]
  66 + access = params[:greatest_project_access]
  67 + @team.assign_to_projects(project_ids, access)
  68 + end
  69 +
  70 + redirect_to admin_team_path(@team), notice: 'Projects was successfully added.'
  71 + end
  72 +
  73 + def relegate_project
  74 + project = params[:project_id]
  75 + @team.resign_from_project(project)
  76 +
  77 + redirect_to admin_team_path(@team), notice: 'Project was successfully removed.'
  78 + end
  79 +
  80 + def add_members
  81 + unless params[:user_ids].blank?
  82 + user_ids = params[:user_ids]
  83 + access = params[:default_project_access]
  84 + is_admin = params[:group_admin]
  85 + @team.add_members(user_ids, access, is_admin)
  86 + end
  87 +
  88 + redirect_to admin_team_path(@team), notice: 'Members was successfully added.'
  89 + end
  90 +
  91 + def remove_member
  92 + member = params[:member_id]
  93 + @team.remove_member(member)
  94 +
  95 + redirect_to admin_team_path(@team), notice: 'Member was successfully removed.'
  96 + end
  97 +
  98 + private
  99 +
  100 + def user_team
  101 + @team = UserTeam.find_by_path(params[:id])
  102 + end
  103 +
  104 +end
... ...
app/views/admin/teams/edit.html.haml 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +%h3.page_title Rename Team
  2 +%hr
  3 += form_for [:admin, @team] do |f|
  4 + - if @team.errors.any?
  5 + .alert-message.block-message.error
  6 + %span= @team.errors.full_messages.first
  7 + .clearfix.team_name_holder
  8 + = f.label :name do
  9 + Team name is
  10 + .input
  11 + = f.text_field :name, placeholder: "Example Team", class: "xxlarge"
  12 +
  13 +
  14 +
  15 + .clearfix.team_name_holder
  16 + = f.label :path do
  17 + %span.cred Team path is
  18 + .input
  19 + = f.text_field :path, placeholder: "example-team", class: "xxlarge danger"
  20 + %ul.cred
  21 + %li Changing team path can have unintended side effects.
  22 + %li Renaming team path will rename directory for all related projects
  23 + %li It will change web url for access team and team projects.
  24 + %li It will change the git path to repositories under this team.
  25 +
  26 + .form-actions
  27 + = f.submit 'Rename team', class: "btn danger"
  28 + = link_to 'Cancel', admin_teams_path, class: "btn cancel-btn"
... ...
app/views/admin/teams/index.html.haml 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +%h3.page_title
  2 + Teams
  3 + %small
  4 + simple Teams description
  5 +
  6 + = link_to 'New Team', new_admin_team_path, class: "btn small right"
  7 + %br
  8 +
  9 += form_tag admin_teams_path, method: :get, class: 'form-inline' do
  10 + = text_field_tag :name, params[:name], class: "xlarge"
  11 + = submit_tag "Search", class: "btn submit primary"
  12 +
  13 +%table
  14 + %thead
  15 + %tr
  16 + %th
  17 + Name
  18 + %i.icon-sort-down
  19 + %th Path
  20 + %th Projects
  21 + %th Members
  22 + %th Owner
  23 + %th.cred Danger Zone!
  24 +
  25 + - @teams.each do |team|
  26 + %tr
  27 + %td
  28 + %strong= link_to team.name, admin_team_path(team)
  29 + %td= team.path
  30 + %td= team.projects.count
  31 + %td= team.members.count
  32 + %td
  33 + = link_to team.owner.name, admin_user_path(team.owner_id)
  34 + %td.bgred
  35 + = link_to 'Rename', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn small"
  36 + = link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn small danger"
  37 += paginate @teams, theme: "admin"
... ...
app/views/admin/teams/new.html.haml 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +%h3.page_title New Team
  2 +%hr
  3 += form_for @team, url: admin_teams_path do |f|
  4 + - if @team.errors.any?
  5 + .alert-message.block-message.error
  6 + %span= @team.errors.full_messages.first
  7 + .clearfix
  8 + = f.label :name do
  9 + Team name is
  10 + .input
  11 + = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
  12 + &nbsp;
  13 + = f.submit 'Create team', class: "btn primary"
  14 + %hr
  15 + .padded
  16 + %ul
  17 + %li Team is kind of directory for several projects
  18 + %li All created teams are private
  19 + %li People within a team see only projects they have access to
  20 + %li All projects of team will be stored in team directory
  21 + %li You will be able to move existing projects into team
... ...
app/views/admin/teams/show.html.haml 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +%h3.page_title
  2 + Team: #{@team.name}
  3 +
  4 +%br
  5 +%table.zebra-striped
  6 + %thead
  7 + %tr
  8 + %th Team
  9 + %th
  10 + %tr
  11 + %td
  12 + %b
  13 + Name:
  14 + %td
  15 + = @team.name
  16 + &nbsp;
  17 + = link_to edit_admin_team_path(@team), class: "btn btn-small right" do
  18 + %i.icon-edit
  19 + Rename
  20 + %tr
  21 + %td
  22 + %b
  23 + Owner:
  24 + %td
  25 + = @team.owner.name
  26 + .right
  27 + = link_to "#", class: "btn btn-small change-owner-link" do
  28 + %i.icon-edit
  29 + Change owner
  30 +
  31 + %tr.change-owner-holder.hide
  32 + %td.bgred
  33 + %b.cred
  34 + New Owner:
  35 + %td.bgred
  36 + = form_for @team, url: admin_team_path(@team) do |f|
  37 + = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
  38 + %div
  39 + = f.submit 'Change Owner', class: "btn danger"
  40 + = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
  41 +
  42 +%fieldset
  43 + %legend Members (#{@team.members.count})
  44 + = form_tag add_members_admin_team_path(@team), id: "team_members", class: "bulk_import", method: :post do
  45 + %table#members_list
  46 + %thead
  47 + %tr
  48 + %th User name
  49 + %th Default project access
  50 + %th Team access
  51 + %th.cred Danger Zone!
  52 + - @team.members.each do |member|
  53 + %tr.member
  54 + %td
  55 + = link_to [:admin, member] do
  56 + = member.name
  57 + %small= "(#{member.email})"
  58 + %td= @team.human_default_projects_access(member)
  59 + %td= @team.admin?(member) ? "Admin" : "Member"
  60 + %td.bgred
  61 + = link_to 'Remove', remove_member_admin_team_path(@team, member_id: member.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
  62 + %tr
  63 + %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_email), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
  64 + %td= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
  65 + %td
  66 + %span= check_box_tag :group_admin
  67 + %span Admin?
  68 + %td= submit_tag 'Add', class: "btn primary", id: :add_members_to_team
  69 +
  70 +%fieldset
  71 + %legend Projects (#{@team.projects.count})
  72 + = form_tag delegate_projects_admin_team_path(@team), id: "assign_projects", class: "bulk_import", method: :post do
  73 + %table#projects_list
  74 + %thead
  75 + %tr
  76 + %th Project name
  77 + %th Max access
  78 + %th.cred Danger Zone!
  79 + - @team.projects.each do |project|
  80 + %tr.project
  81 + %td
  82 + = link_to project.name_with_namespace, [:admin, project]
  83 + %td
  84 + %span= @team.human_max_project_access(project)
  85 + %td.bgred
  86 + = link_to 'Relegate', relegate_project_admin_team_path(@team, project_id: project.id), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
  87 + %tr
  88 + %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
  89 + %td= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
  90 + %td= submit_tag 'Add', class: "btn primary", id: :assign_projects_to_team
  91 +
  92 +:javascript
  93 + $(function(){
  94 + var modal = $('.change-owner-holder');
  95 + $('.change-owner-link').bind("click", function(){
  96 + $(this).hide();
  97 + modal.show();
  98 + });
  99 + $('.change-owner-cancel-link').bind("click", function(){
  100 + modal.hide();
  101 + $('.change-owner-link').show();
  102 + })
  103 + })
  104 +
... ...
app/views/layouts/admin.html.haml
... ... @@ -10,6 +10,8 @@
10 10 = link_to "Stats", admin_root_path
11 11 = nav_link(controller: :projects) do
12 12 = link_to "Projects", admin_projects_path
  13 + = nav_link(controller: :teams) do
  14 + = link_to "Teams", admin_teams_path
13 15 = nav_link(controller: :groups) do
14 16 = link_to "Groups", admin_groups_path
15 17 = nav_link(controller: :users) do
... ...
config/routes.rb
... ... @@ -69,6 +69,14 @@ Gitlab::Application.routes.draw do
69 69 put :team_update
70 70 end
71 71 end
  72 + resources :teams do #, constraints: { id: /[^\/]+/ } do end
  73 + member do
  74 + post :delegate_projects
  75 + delete :relegate_project
  76 + post :add_members
  77 + delete :remove_member
  78 + end
  79 + end
72 80 resources :team_members, only: [:edit, :update, :destroy]
73 81 resources :hooks, only: [:index, :create, :destroy] do
74 82 get :test
... ...
features/admin/teams.feature 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +Feature: Admin Teams
  2 + Background:
  3 + Given I sign in as an admin
  4 + #And there are projects in system
  5 + #And system has users
  6 + #And I have own project
  7 + And Create gitlab user "John"
  8 +
  9 + Scenario: Create a team
  10 + When I visit admin teams page
  11 + And I click new team link
  12 + And submit form with new team info
  13 + Then I should be redirected to team page
  14 + And I should see newly created team
  15 +
  16 + Scenario: Add user to team
  17 + When I visit admin teams page
  18 + When I have clean "HardCoders" team
  19 + And I visit "HardCoders" team page
  20 + #Then I should see only me in members table
  21 + When I select user "John" from user list as "Developer"
  22 + And submit form with new team member info
  23 + Then I should see "John" in teams members list as "Developer"
  24 + When I visit "John" user admin page
  25 + Then I should see "HardCoders" team in teams table
  26 +
  27 + Scenario: Assign team to existing project
  28 + When I visit admin teams page
  29 + When I have "HardCoders" team with "John" member with "Developer" role
  30 + When I have "Shop" project
  31 + And I visit "HardCoders" team page
  32 + Then I should see empty projects table
  33 + When I select project "Shop" with max access "Reporter"
  34 + And submit form with new team project info
  35 + Then I should see "Shop" project in projects list
  36 + When I visit "Shop" project admin page
  37 + Then I should see "John" user with role "Reporter" in team table
  38 +
  39 + Scenario: Add user to team with ptojects
  40 + When I visit admin teams page
  41 + When I have "HardCoders" team with "John" member with "Developer" role
  42 + And "HardCoders" team assigned to "Shop" project with "Developer" max role access
  43 + When I have gitlab user "Jimm"
  44 + And I visit "HardCoders" team page
  45 + Then I should see members table without "Jimm" member
  46 + When I select user "Jimm" ub team members list as "Master"
  47 + And submit form with new team member info
  48 + Then I should see "Jimm" in teams members list as "Master"
  49 +
  50 + Scenario: Remove member from team
  51 + Given I have users team "HardCoders"
  52 + And gitlab user "John" is a member "HardCoders" team
  53 + And gitlab user "Jimm" is a member "HardCoders" team
  54 + And "HardCoders" team is assigned to "Shop" project
  55 + When I visit admin teams page
  56 + When I visit "HardCoders" team admin page
  57 + Then I shoould see "John" in members list
  58 + And I should see "Jimm" in members list
  59 + And I should see "Shop" in projects list
  60 + When I click on remove "Jimm" user link
  61 + Then I should be redirected to "HardCoders" team admin page
  62 + And I should not to see "Jimm" user in members list
  63 +
  64 + Scenario: Remove project from team
  65 + Given I have users team "HardCoders"
  66 + And gitlab user "John" is a member "HardCoders" team
  67 + And gitlab user "Jimm" is a member "HardCoders" team
  68 + And "HardCoders" team is assigned to "Shop" project
  69 + When I visit admin teams page
  70 + When I visit "HardCoders" team admin page
  71 + Then I should see "Shop" project in projects list
  72 + When I click on "Relegate" link on "Shop" project
  73 + Then I should see projects liston team page without "Shop" project
... ...
features/steps/admin/admin_teams.rb 0 → 100644
... ... @@ -0,0 +1,222 @@
  1 +class AdminTeams < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedPaths
  4 + include SharedActiveTab
  5 + include SharedAdmin
  6 +
  7 + And 'I have own project' do
  8 + create :project
  9 + end
  10 +
  11 + And 'Create gitlab user "John"' do
  12 + @user = create(:user, :name => "John")
  13 + end
  14 +
  15 + And 'I click new team link' do
  16 + click_link "New Team"
  17 + end
  18 +
  19 + And 'submit form with new team info' do
  20 + fill_in 'user_team_name', with: 'gitlab'
  21 + click_button 'Create team'
  22 + end
  23 +
  24 + Then 'I should be redirected to team page' do
  25 + current_path.should == admin_team_path(UserTeam.last)
  26 + end
  27 +
  28 + And 'I should see newly created team' do
  29 + page.should have_content "Team: gitlab"
  30 + end
  31 +
  32 + When 'I visit admin teams page' do
  33 + visit admin_teams_path
  34 + end
  35 +
  36 + When 'I have clean "HardCoders" team' do
  37 + @team = create :user_team, name: "HardCoders", owner: current_user
  38 + end
  39 +
  40 + And 'I visit "HardCoders" team page' do
  41 + visit admin_team_path(UserTeam.find_by_name("HardCoders"))
  42 + end
  43 +
  44 + Then 'I should see only me in members table' do
  45 + members_list = find("#members_list .member")
  46 + members_list.should have_content(current_user.name)
  47 + members_list.should have_content(current_user.email)
  48 + end
  49 +
  50 + When 'I select user "John" from user list as "Developer"' do
  51 + @user ||= User.find_by_name("John")
  52 + within "#team_members" do
  53 + select user.name, :from => "user_ids"
  54 + select "Developer", :from => "default_project_access"
  55 + end
  56 + end
  57 +
  58 + And 'submit form with new team member info' do
  59 + click_button 'add_members_to_team'
  60 + end
  61 +
  62 + Then 'I should see "John" in teams members list as "Developer"' do
  63 + @user ||= User.find_by_name("John")
  64 + find_in_list("#members_list .member", user).must_equal true
  65 + end
  66 +
  67 + When 'I visit "John" user admin page' do
  68 + pending 'step not implemented'
  69 + end
  70 +
  71 + Then 'I should see "HardCoders" team in teams table' do
  72 + pending 'step not implemented'
  73 + end
  74 +
  75 + When 'I have "HardCoders" team with "John" member with "Developer" role' do
  76 + @team = create :user_team, name: "HardCoders", owner: current_user
  77 + @user ||= User.find_by_name("John")
  78 + @team.add_member(@user, UserTeam.access_roles["Developer"], group_admin: false)
  79 + end
  80 +
  81 + When 'I have "Shop" project' do
  82 + @project = create :project, name: "Shop"
  83 + end
  84 +
  85 + Then 'I should see empty projects table' do
  86 + projects_list = find("#projects_list")
  87 + projects_list.has_content?("Relegate").must_equal false
  88 + end
  89 +
  90 + When 'I select project "Shop" with max access "Reporter"' do
  91 + @project ||= Project.find_by_name("Shop")
  92 + within "#assign_projects" do
  93 + select @project.name, :from => "project_ids"
  94 + select "Reporter", :from => "greatest_project_access"
  95 + end
  96 +
  97 + end
  98 +
  99 + And 'submit form with new team project info' do
  100 + click_button 'assign_projects_to_team'
  101 + end
  102 +
  103 + Then 'I should see "Shop" project in projects list' do
  104 + project = Project.find_by_name("Shop")
  105 + find_in_list("#projects_list .project", project).must_equal true
  106 + end
  107 +
  108 + When 'I visit "Shop" project admin page' do
  109 + project = Project.find_by_name("Shop")
  110 + visit admin_project_path(project)
  111 + end
  112 +
  113 + And '"HardCoders" team assigned to "Shop" project with "Developer" max role access' do
  114 + @team = UserTeam.find_by_name("HardCoders")
  115 + @project = create :project, name: "Shop"
  116 + @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
  117 + end
  118 +
  119 + When 'I have gitlab user "Jimm"' do
  120 + create :user, name: "Jimm"
  121 + end
  122 +
  123 + Then 'I should see members table without "Jimm" member' do
  124 + user = User.find_by_name("Jimm")
  125 + find_in_list("#members_list .member", user).must_equal false
  126 + end
  127 +
  128 + When 'I select user "Jimm" ub team members list as "Master"' do
  129 + user = User.find_by_name("Jimm")
  130 + within "#team_members" do
  131 + select user.name, :from => "user_ids"
  132 + select "Developer", :from => "default_project_access"
  133 + end
  134 + end
  135 +
  136 + Then 'I should see "Jimm" in teams members list as "Master"' do
  137 + user = User.find_by_name("Jimm")
  138 + find_in_list("#members_list .member", user).must_equal true
  139 + end
  140 +
  141 + Given 'I have users team "HardCoders"' do
  142 + @team = create :user_team, name: "HardCoders"
  143 + end
  144 +
  145 + And 'gitlab user "John" is a member "HardCoders" team' do
  146 + @team = UserTeam.find_by_name("HardCoders")
  147 + @user = User.find_by_name("John")
  148 + @user = create :user, name: "John" unless @user
  149 + @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
  150 + end
  151 +
  152 + And 'gitlab user "Jimm" is a member "HardCoders" team' do
  153 + @team = UserTeam.find_by_name("HardCoders")
  154 + @user = User.find_by_name("Jimm")
  155 + @user = create :user, name: "Jimm" unless @user
  156 + @team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
  157 + end
  158 +
  159 + And '"HardCoders" team is assigned to "Shop" project' do
  160 + @team = UserTeam.find_by_name("HardCoders")
  161 + @project = create :project, name: "Shop"
  162 + @team.assign_to_project(@project, UserTeam.access_roles["Developer"])
  163 + end
  164 +
  165 + When 'I visit "HardCoders" team admin page' do
  166 + visit admin_team_path(UserTeam.find_by_name("HardCoders"))
  167 + end
  168 +
  169 + Then 'I shoould see "John" in members list' do
  170 + user = User.find_by_name("John")
  171 + find_in_list("#members_list .member", user).must_equal true
  172 + end
  173 +
  174 + And 'I should see "Jimm" in members list' do
  175 + user = User.find_by_name("Jimm")
  176 + find_in_list("#members_list .member", user).must_equal true
  177 + end
  178 +
  179 + And 'I should see "Shop" in projects list' do
  180 +
  181 + end
  182 +
  183 + When 'I click on remove "Jimm" user link' do
  184 +
  185 + end
  186 +
  187 + Then 'I should be redirected to "HardCoders" team admin page' do
  188 + current_path.should admin_team_peth(UserTeam.find_by_name("HardCoders"))
  189 + end
  190 +
  191 + And 'I should not to see "Jimm" user in members list' do
  192 +
  193 + end
  194 +
  195 + When 'I click on "Relegate" link on "Shop" project' do
  196 +
  197 + end
  198 +
  199 + Then 'I should see projects liston team page without "Shop" project' do
  200 +
  201 + end
  202 +
  203 + Then 'I should see "John" user with role "Reporter" in team table' do
  204 + user = User.find_by_name("John")
  205 + find_in_list(".team_members", user).must_equal true
  206 + end
  207 +
  208 + protected
  209 +
  210 + def current_team
  211 + @team ||= Team.first
  212 + end
  213 +
  214 + def find_in_list(selector, item)
  215 + members_list = all(selector)
  216 + entered = false
  217 + members_list.each do |member_item|
  218 + entered = true if member_item.has_content?(item.name)
  219 + end
  220 + entered
  221 + end
  222 +end
... ...
features/steps/shared/paths.rb
... ... @@ -105,6 +105,10 @@ module SharedPaths
105 105 visit admin_groups_path
106 106 end
107 107  
  108 + When 'I visit admin teams page' do
  109 + visit admin_teams_path
  110 + end
  111 +
108 112 # ----------------------------------------
109 113 # Generic Project
110 114 # ----------------------------------------
... ...