Commit fcccf762 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'remove/user_teams' of /home/git/repositories/gitlab/gitlabhq into 6-0-dev

parents 670aaaeb 1b3b90db
# Provides a base class for Admin controllers to subclass
#
# Automatically sets the layout and ensures an administrator is logged in
class Admin::Teams::ApplicationController < Admin::ApplicationController
private
def user_team
@team = UserTeam.find_by_path(params[:team_id])
end
end
class Admin::Teams::MembersController < Admin::Teams::ApplicationController
def new
@users = User.potential_team_members(user_team)
end
def create
unless params[:user_ids].blank?
user_ids = params[:user_ids]
access = params[:default_project_access]
is_admin = params[:group_admin]
user_team.add_members(user_ids, access, is_admin)
end
redirect_to admin_team_path(user_team), notice: 'Members were successfully added into Team of users.'
end
def edit
team_member
end
def update
options = {default_projects_access: params[:default_project_access], group_admin: params[:group_admin]}
if user_team.update_membership(team_member, options)
redirect_to admin_team_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
else
render :edit
end
end
def destroy
user_team.remove_member(team_member)
redirect_to admin_team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
end
protected
def team_member
@member ||= user_team.members.find_by_username(params[:id])
end
end
class Admin::Teams::ProjectsController < Admin::Teams::ApplicationController
def new
@projects = Project.scoped
@projects = @projects.without_team(user_team) if user_team.projects.any?
#@projects.reject!(&:empty_repo?)
end
def create
unless params[:project_ids].blank?
project_ids = params[:project_ids]
access = params[:greatest_project_access]
user_team.assign_to_projects(project_ids, access)
end
redirect_to admin_team_path(user_team), notice: 'Team of users was successfully assgned to projects.'
end
def edit
team_project
end
def update
if user_team.update_project_access(team_project, params[:greatest_project_access])
redirect_to admin_team_path(user_team), notice: 'Access was successfully updated.'
else
render :edit
end
end
def destroy
user_team.resign_from_project(team_project)
redirect_to admin_team_path(user_team), notice: 'Team of users was successfully reassigned from project.'
end
protected
def team_project
@project ||= user_team.projects.find_with_namespace(params[:id])
end
end
class Admin::TeamsController < Admin::ApplicationController
def index
@teams = UserTeam.order('name ASC')
@teams = @teams.search(params[:name]) if params[:name].present?
@teams = @teams.page(params[:page]).per(20)
end
def show
user_team
end
def new
@team = UserTeam.new
end
def edit
user_team
end
def create
@team = UserTeam.new(params[:user_team])
@team.path = @team.name.dup.parameterize if @team.name
@team.owner = current_user
if @team.save
redirect_to admin_team_path(@team), notice: 'Team of users was successfully created.'
else
render action: "new"
end
end
def update
user_team_params = params[:user_team].dup
owner_id = user_team_params.delete(:owner_id)
if owner_id
user_team.owner = User.find(owner_id)
end
if user_team.update_attributes(user_team_params)
redirect_to admin_team_path(user_team), notice: 'Team of users was successfully updated.'
else
render action: "edit"
end
end
def destroy
user_team.destroy
redirect_to admin_teams_path, notice: 'Team of users was successfully deleted.'
end
protected
def user_team
@team ||= UserTeam.find_by_path(params[:id])
end
end
......@@ -7,7 +7,6 @@ class DashboardController < ApplicationController
def show
@groups = current_user.authorized_groups.sort_by(&:human_name)
@has_authorized_projects = @projects.count > 0
@teams = current_user.authorized_teams
@projects_count = @projects.count
@projects = @projects.limit(20)
......
class Projects::TeamsController < Projects::ApplicationController
before_filter :authorize_admin_team_member!
def available
@teams = current_user.is_admin? ? UserTeam.scoped : current_user.user_teams
@teams = @teams.without_project(project)
unless @teams.any?
redirect_to project_team_index_path(project), notice: "No available teams for assigment."
end
end
def assign
unless params[:team_id].blank?
team = UserTeam.find(params[:team_id])
access = params[:greatest_project_access]
team.assign_to_project(project, access)
end
redirect_to project_team_index_path(project)
end
def resign
team = project.user_teams.find_by_path(params[:id])
team.resign_from_project(project)
redirect_to project_team_index_path(project)
end
protected
def user_team
@team ||= UserTeam.find_by_path(params[:id])
end
end
......@@ -6,7 +6,6 @@ class TeamMembersController < ProjectResourceController
def index
@group = @project.group
@users_projects = @project.users_projects.order('project_access DESC')
@assigned_teams = @project.user_team_project_relationships
end
def new
......
class Teams::ApplicationController < ApplicationController
layout 'user_team'
before_filter :authorize_manage_user_team!
protected
def user_team
@team ||= UserTeam.find_by_path(params[:team_id])
end
end
class Teams::MembersController < Teams::ApplicationController
skip_before_filter :authorize_manage_user_team!, only: [:index]
def index
@members = user_team.members
end
def new
@users = User.potential_team_members(user_team)
end
def create
unless params[:user_ids].blank?
user_ids = params[:user_ids].split(',')
access = params[:default_project_access]
is_admin = params[:group_admin]
user_team.add_members(user_ids, access, is_admin)
end
redirect_to team_members_path(user_team), notice: 'Members were successfully added into Team of users.'
end
def edit
team_member
end
def update
member_params = params[:team_member]
options = {
default_projects_access: member_params[:permission],
group_admin: member_params[:group_admin]
}
if user_team.update_membership(team_member, options)
redirect_to team_members_path(user_team), notice: "Membership for #{team_member.name} was successfully updated in Team of users."
else
render :edit
end
end
def destroy
user_team.remove_member(team_member)
redirect_to team_path(user_team), notice: "Member #{team_member.name} was successfully removed from Team of users."
end
protected
def team_member
@member ||= user_team.members.find_by_username(params[:id])
end
end
class Teams::ProjectsController < Teams::ApplicationController
def create
redirect_to :back if params[:project_ids].blank?
project_ids = params[:project_ids]
access = params[:greatest_project_access]
# Reject non-allowed projects
allowed_project_ids = current_user.owned_projects.map(&:id)
project_ids.select! { |id| allowed_project_ids.include?(id.to_i) }
# Assign projects to team
user_team.assign_to_projects(project_ids, access)
redirect_to edit_team_path(user_team), notice: 'Team of users was successfully assigned to projects.'
end
def edit
team_project
end
def update
if user_team.update_project_access(team_project, params[:greatest_project_access])
redirect_to edit_team_path(user_team), notice: 'Access was successfully updated.'
else
render :edit
end
end
def destroy
user_team.resign_from_project(team_project)
redirect_to team_projects_path(user_team), notice: 'Team of users was successfully reassigned from project.'
end
private
def team_project
@project ||= user_team.projects.find_with_namespace(params[:id])
end
end
class TeamsController < ApplicationController
# Authorize
before_filter :authorize_create_team!, only: [:new, :create]
before_filter :authorize_manage_user_team!, only: [:edit, :update]
before_filter :authorize_admin_user_team!, only: [:destroy]
before_filter :user_team, except: [:new, :create]
layout :determine_layout
before_filter :set_title, only: [:new, :create]
def show
projects
@events = Event.in_projects(user_team.project_ids).limit(20).offset(params[:offset] || 0)
end
def edit
projects
@avaliable_projects = current_user.owned_projects.without_team(user_team)
end
def update
if user_team.update_attributes(params[:user_team])
redirect_to team_path(user_team)
else
render action: :edit
end
end
def destroy
user_team.destroy
redirect_to dashboard_path
end
def new
@team = UserTeam.new
end
def create
@team = UserTeam.new(params[:user_team])
@team.owner = current_user unless params[:owner]
@team.path = @team.name.dup.parameterize if @team.name
if @team.save
# Add current user as Master to the team
@team.add_members([current_user.id], UsersProject::MASTER, true)
redirect_to team_path(@team)
else
render action: :new
end
end
# Get authored or assigned open merge requests
def merge_requests
projects
@merge_requests = MergeRequest.of_user_team(user_team)
@merge_requests = FilterContext.new(@merge_requests, params).execute
@merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end
# Get only assigned issues
def issues
projects
@issues = Issue.of_user_team(user_team)
@issues = FilterContext.new(@issues, params).execute
@issues = @issues.recent.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project)
end
protected
def projects
@projects ||= user_team.projects.sorted_by_activity
end
def user_team
@team ||= current_user.authorized_teams.find_by_path(params[:id])
end
def set_title
@title = 'New Team'
end
def determine_layout
if [:new, :create].include?(action_name.to_sym)
'navless'
else
'user_team'
end
end
end
......@@ -92,7 +92,6 @@ module ApplicationHelper
def search_autocomplete_source
projects = current_user.authorized_projects.map { |p| { label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } }
groups = current_user.authorized_groups.map { |group| { label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } }
teams = current_user.authorized_teams.map { |team| { label: "team: #{simple_sanitize(team.name)}", url: team_path(team) } }
default_nav = [
{ label: "My Profile", url: profile_path },
......@@ -128,7 +127,7 @@ module ApplicationHelper
]
end
[groups, teams, projects, default_nav, project_nav, help_nav].flatten.to_json
[groups, projects, default_nav, project_nav, help_nav].flatten.to_json
end
def emoji_autocomplete_source
......
module UserTeamsHelper
def team_filter_path(entity, options={})
exist_opts = {
status: params[:status],
project_id: params[:project_id],
}
options = exist_opts.merge(options)
case entity
when 'issue' then
issues_team_path(@team, options)
when 'merge_request'
merge_requests_team_path(@team, options)
end
end
def grouped_user_team_members(team)
team.user_team_user_relationships.sort_by(&:permission).reverse.group_by(&:permission)
end
def remove_from_user_team_message(team, member)
"You are going to remove #{member.name} from #{team.name}. Are you sure?"
end
end
......@@ -11,7 +11,6 @@ class Ability
when "PersonalSnippet" then personal_snippet_abilities(user, subject)
when "MergeRequest" then merge_request_abilities(user, subject)
when "Group", "Namespace" then group_abilities(user, subject)
when "UserTeam" then user_team_abilities(user, subject)
else []
end.concat(global_abilities(user))
end
......@@ -19,7 +18,6 @@ class Ability
def global_abilities(user)
rules = []
rules << :create_group if user.can_create_group
rules << :create_team if user.can_create_team
rules
end
......@@ -146,21 +144,6 @@ class Ability
rules.flatten
end
def user_team_abilities user, team
rules = []
# Only group owner and administrators can manage team
if user.admin? || team.owner == user || team.admin?(user)
rules << [ :manage_user_team ]
end
if team.owner == user || user.admin?
rules << [ :admin_user_team ]
end
rules.flatten
end
[:issue, :note, :project_snippet, :personal_snippet, :merge_request].each do |name|
define_method "#{name}_abilities" do |user, subject|
if subject.author == user
......
......@@ -75,13 +75,6 @@ class User < ActiveRecord::Base
has_many :users_groups, dependent: :destroy
has_many :groups, through: :users_groups
# Teams
has_many :own_teams, dependent: :destroy, class_name: "UserTeam", foreign_key: :owner_id
has_many :user_team_user_relationships, dependent: :destroy
has_many :user_teams, through: :user_team_user_relationships
has_many :user_team_project_relationships, through: :user_teams
has_many :team_projects, through: :user_team_project_relationships
# Projects
has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet"
has_many :users_projects, dependent: :destroy
......@@ -235,10 +228,6 @@ class User < ActiveRecord::Base
own_groups
end
def owned_teams
own_teams
end
# Groups user has access to
def authorized_groups
@group_ids ||= (groups.pluck(:id) + own_groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
......@@ -252,15 +241,6 @@ class User < ActiveRecord::Base
Project.where(id: @project_ids)
end
def authorized_teams
if admin?
UserTeam.scoped
else
@team_ids ||= (user_teams.pluck(:id) + own_teams.pluck(:id)).uniq
UserTeam.where(id: @team_ids)
end
end
# Team membership in authorized projects
def tm_in_authorized_projects
UsersProject.where(project_id: authorized_projects.map(&:id), user_id: self.id)
......
......@@ -49,10 +49,6 @@
.span4
%h4 Stats
%hr
%p
Teams
%span.light.pull-right
= UserTeam.count
%p
Forks
%span.light.pull-right
......
%h3.page_title Edit Team
%hr
= form_for @team, url: admin_team_path(@team), method: :put do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix.team_name_holder
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Example Team", class: "xxlarge"
.clearfix.team-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.clearfix.team_name_holder
= f.label :path do
%span.cred Team path is
.input
= f.text_field :path, placeholder: "example-team", class: "xxlarge danger"
%ul.cred
%li It will change web url for access team and team projects.
.form-actions
= f.submit 'Edit team', class: "btn btn-remove"
= link_to 'Cancel', admin_teams_path, class: "btn btn-cancel"
%h3.page_title
Teams (#{@teams.total_count})
%small
allow you to organize groups of people that have a common focus. Use teams to simplify the process of assigning roles to groups of people.
= link_to 'New Team', new_admin_team_path, class: "btn btn-small pull-right"
%br
= form_tag admin_teams_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "span6"
= submit_tag "Search", class: "btn submit btn-primary"
%hr
%ul.bordered-list
- @teams.each do |team|
%li
.clearfix
.pull-right.prepend-top-10
= link_to 'Edit', edit_admin_team_path(team), id: "edit_#{dom_id(team)}", class: "btn btn-small"
= link_to 'Destroy', admin_team_path(team), confirm: "REMOVE #{team.name}? Are you sure?", method: :delete, class: "btn btn-small btn-remove"
%h4
= link_to admin_team_path(team) do
%i.icon-group
= team.name
.clearfix.light.append-bottom-10
%span
%b Owner:
- if team.owner
= link_to team.owner.name, admin_user_path(team.owner)
- else
(deleted)
\|
%span
%b Users:
%span.badge= team.members.count
\|
%span
%b Projects:
%span.badge= team.projects.count
.clearfix
%p
= truncate team.description, length: 150
= paginate @teams, theme: "gitlab"
= form_tag admin_team_member_path(@team, @member), method: :put do
-if @member.errors.any?
.alert.alert-error
%ul
- @member.errors.full_messages.each do |msg|
%li= msg
.clearfix
%label Default access for Team projects:
.input
= select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
.clearfix
%label Team admin?
.input
= check_box_tag :group_admin, true, @team.admin?(@member)
%br
.actions
= submit_tag 'Save', class: "btn btn-primary"
= link_to 'Cancel', :back, class: "btn"
%h3
Edit access #{@member.name} in #{@team.name} team
%hr
%table.zebra-striped
%tr
%td User:
%td= @member.name
%tr
%td Team:
%td= @team.name
%tr
%td Since:
%td= member_since(@team, @member).stamp("Nov 11, 2010")
= render 'form'
%h3.page_title
New members for
= link_to @team.name, admin_team_path(@team)
team
%hr
= form_tag admin_team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= label_tag :user_ids do
Users to add
.input
= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name_with_username), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
.clearfix.group-description-holder
= label_tag :default_project_access do
Default permission in projects
.input
= select_tag :default_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
.clearfix
= label_tag :group_admin do
Is team admin
.input
= check_box_tag :group_admin
.clearfix.form-actions
= submit_tag 'Add users into team', class: "btn btn-primary", id: :add_members_to_team
= link_to 'Cancel', :back, class: "btn"
%h3.page_title New Team
%hr
= form_for @team, url: admin_teams_path do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
.clearfix.team-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.form-actions
= f.submit 'Create team', class: "btn btn-create"
%hr
.padded
%ul
%li All created teams are public (users can view who enter into team and which project are assigned for this team)
%li People within a team see only projects they have access to
%li You will be able to assign existing projects for team
= form_tag admin_team_project_path(@team, @project), method: :put do
-if @project.errors.any?
.alert.alert-error
%ul
- @project.errors.full_messages.each do |msg|
%li= msg
.clearfix
%label Max access for Team members:
.input
= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
%br
.actions
= submit_tag 'Save', class: "btn btn-primary"
= link_to 'Cancel', :back, class: "btn"
%h3
Edit max access in #{@project.name} for #{@team.name} team
%hr
%table.zebra-striped
%tr
%td Project:
%td= @project.name
%tr
%td Team:
%td= @team.name
%tr
%td Since:
%td= assigned_since(@team, @project).stamp("Nov 11, 2010")
= render 'form'
%h3.page_title
Team: #{@team.name}
%hr
= form_tag admin_team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post do
%h6 Choose Projects you want to assign:
.clearfix
= label_tag :project_ids, "Projects"
.input
= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
%h6 Choose greatest user acces for your team in this projects:
.clearfix
= label_tag :greatest_project_access, "Greatest Access"
.input
= select_tag :greatest_project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3" }
.form-actions
= submit_tag 'Add team to projects', class: "btn btn-create", id: :assign_projects_to_team
%h3.page_title
Team: #{@team.name}
= link_to edit_admin_team_path(@team), class: "btn btn-small pull-right" do
%i.icon-edit
Edit
%hr
.row
.span6
.ui-box
%h5.title
Team info:
%ul.well-list
%li
%span.light Name:
%strong= @team.name
%li
%span.light Path:
%strong
= @team.path
%li
%span.light Description:
%strong
= @team.description
%li
%span.light Owned by:
%strong
- if @team.owner
= link_to @team.owner.name, admin_user_path(@team.owner)
- else
(deleted)
.pull-right
= link_to "#", class: "btn btn-small change-owner-link" do
%i.icon-edit
Change owner
%li.change-owner-holder.hide.bgred
.form-holder
%strong.cred New Owner:
= form_for @team, url: admin_team_path(@team) do |f|
= users_select_tag(:"user_team[owner_id]")
.prepend-top-10
= f.submit 'Change Owner', class: "btn btn-remove"
= link_to "Cancel", "#", class: "btn change-owner-cancel-link"
%li
%span.light Created at:
%strong
= @team.created_at.stamp("March 1, 1999")
.span6
.ui-box
%h5.title
Members (#{@team.members.count})
.pull-right
= link_to 'Add members', new_admin_team_member_path(@team), class: "btn btn-small", id: :add_members_to_team
%ul.well-list#members_list
- @team.members.each do |member|
%li.member{ class: "user_#{member.id}"}
= link_to [:admin, member] do
%strong
= member.name
.pull-right
%span.light
= @team.human_default_projects_access(member)
- if @team.admin?(member)
%span.label.label-info Admin
&nbsp;
= link_to 'Edit', edit_admin_team_member_path(@team, member), class: "btn btn-small"
&nbsp;
= link_to 'Remove', admin_team_member_path(@team, member), confirm: 'Remove member from team. Are you sure?', method: :delete, class: "btn btn-remove btn-small", id: "remove_member_#{member.id}"
.ui-box
%h5.title
Projects (#{@team.projects.count})
.pull-right
= link_to 'Add projects', new_admin_team_project_path(@team), class: "btn btn-small", id: :assign_projects_to_team
%ul.well-list#projects_list
- @team.projects.each do |project|
%li.project
= link_to [:admin, project] do
%strong
= project.name_with_namespace
.pull-right
%span.light
= @team.human_max_project_access(project)
&nbsp;
= link_to 'Edit', edit_admin_team_project_path(@team, project), class: "btn btn-small"
&nbsp;
= link_to 'Relegate', admin_team_project_path(@team, project), confirm: 'Remove project from team. Are you sure?', method: :delete, class: "btn btn-remove small", id: "relegate_project_#{project.id}"
......@@ -93,13 +93,6 @@
%li
%strong= link_to group.name, admin_group_path(group)
- if @admin_user.owned_teams.present?
.ui-box
%h5.title Owned teams:
%ul.well-list
- @admin_user.owned_teams.each do |team|
%li
%strong= link_to team.name, admin_team_path(team)
.span6
......
......@@ -3,16 +3,12 @@
= link_to 'Projects', '#projects', 'data-toggle' => 'tab', id: 'sidebar-projects-tab'
%li
= link_to 'Groups', '#groups', 'data-toggle' => 'tab', id: 'sidebar-groups-tab'
%li
= link_to 'Teams', '#teams', 'data-toggle' => 'tab', id: 'sidebar-teams-tab'
.tab-content
.tab-pane.active#projects
= render "projects", projects: @projects
.tab-pane#groups
= render "groups", groups: @groups
.tab-pane#teams
= render "teams", teams: @teams
.prepend-top-20
%span.rss-icon
......
......@@ -4,8 +4,6 @@
%i.icon-home
= nav_link(controller: :projects) do
= link_to "Projects", admin_projects_path
= nav_link(controller: :teams) do
= link_to "Teams", admin_teams_path
= nav_link(controller: :groups) do
= link_to "Groups", admin_groups_path
= nav_link(controller: :users) do
......
......@@ -67,12 +67,6 @@
Need a group for several dependent projects?
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_team?
%li
%p
Want to share a team between projects?
= link_to new_team_path, class: "btn btn-tiny" do
Create a team
- unless current_user.projects_limit_left > 100
%fieldset
%legend
......
......@@ -40,12 +40,6 @@
Need a group for several dependent projects?
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_team?
.clearfix
.input.light
Want to share a project between team?
= link_to new_team_path, class: "btn btn-tiny" do
Create a team
.save-project-loader.hide
%center
......
= render "projects/settings_nav"
%h3.page_title
= "Assign project to team of users"
%hr
%p.slead
Read more about assign to team of users #{link_to "here", '#', class: 'vlink'}.
= form_tag assign_project_teams_path(@project), method: 'post' do
%p.slead Choose Team of users you want to assign:
.padded
= label_tag :team_id, "Team"
.input= select_tag(:team_id, options_from_collection_for_select(@teams, :id, :name), prompt: "Select team", class: "chosen xxlarge", required: true)
%p.slead Choose greatest user acces in team you want to assign:
.padded
= label_tag :team_ids, "Permission"
.input= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen span3" }
.actions
= submit_tag 'Assign', class: "btn btn-create"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
......@@ -6,8 +6,6 @@
%span.pull-right
= link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do
Import team from another project
= link_to available_project_teams_path(@project), class: "btn btn-small grouped", title: "Assign project to team of users" do
Assign project to Team of users
= link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
New Team Member
......
= form_tag team_filter_path(entity), method: 'get' do
%fieldset.dashboard-search-filter
= search_field_tag "search", params[:search], { placeholder: 'Search', class: 'search-text-input' }
= button_tag type: 'submit', class: 'btn' do
%i.icon-search
%fieldset
%legend Status:
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if !params[:status])}
= link_to team_filter_path(entity, status: nil) do
Open
%li{class: ("active" if params[:status] == 'closed')}
= link_to team_filter_path(entity, status: 'closed') do
Closed
%li{class: ("active" if params[:status] == 'all')}
= link_to team_filter_path(entity, status: 'all') do
All
%fieldset
%legend Projects:
%ul.nav.nav-pills.nav-stacked
- @projects.each do |project|
- unless entities_per_project(project, entity).zero?
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to team_filter_path(entity, project_id: project.id) do
= project.name_with_namespace
%small.pull-right= entities_per_project(project, entity)
%fieldset
%hr
= link_to "Reset", team_filter_path(entity), class: 'btn pull-right'
.ui-box
%h5.title
Projects
%small
(#{projects.count})
- if can? current_user, :manage_user_team, @team
%span.pull-right
= link_to edit_team_path(@team), class: "btn btn-tiny info" do
%i.icon-plus
Assign Project
%ul.well-list
- if projects.blank?
%p.nothing_here_message This team has no projects yet
- projects.each do |project|
%li
= link_to project_path(project), class: dom_class(project) do
%strong.well-title= truncate(project.name_with_namespace, length: 40)
%span.arrow
&rarr;
%span.last_activity
%strong Last activity:
%span= project_last_activity(project)
.row
.span3
%ul.nav.nav-pills.nav-stacked
%li.active
= link_to 'Projects', '#tab-projects', 'data-toggle' => 'tab'
%li
= link_to 'Edit Team', '#tab-edit', 'data-toggle' => 'tab'
- if can? current_user, :admin_user_team, @team
%li
= link_to 'Remove', '#tab-remove', 'data-toggle' => 'tab'
.span9
.tab-content
.tab-pane.active#tab-projects
.ui-box.projects-table
%h5.title Projects
%ul.well-list
- @projects.each do |project|
%li
- if project.public
%i.icon-share
- else
%i.icon-lock.cgreen
= link_to project.name_with_namespace, project
.pull-right
= link_to 'Edit max access', edit_team_project_path(@team, project), class: "btn btn-small"
= link_to 'Relegate', team_project_path(@team, project), confirm: 'Remove project from team and move to global namespace. Are you sure?', method: :delete, class: "btn btn-remove small"
.form-holder
= form_tag team_projects_path(@team), id: "assign_projects", class: "bulk_import", method: :post do
%table.headless
%tr
%td= select_tag :project_ids, options_from_collection_for_select(@avaliable_projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span4'
%td= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles), {class: "project-access-select chosen" }
%td= submit_tag 'Add Project', class: "btn btn-create", id: :assign_projects_to_team
.tab-pane#tab-edit
.ui-box
%h5.title Edit Team
%div.form-holder
= form_for @team, url: team_path(@team) do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xlarge left"
.clearfix.team-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xlarge js-gfm-input", rows: 4
.clearfix
= f.label :path do
Team path is
.input
= f.text_field :path, placeholder: "opensource", class: "xlarge left"
.form-actions
= f.submit 'Save team changes', class: "btn btn-primary"
.tab-pane#tab-remove
.ui-box.ui-box-danger
%h5.title Remove team
.ui-box-body
%p
Remove of team will cause removing members access to projects.
%p
%strong Removed team can not be restored!
= link_to 'Remove team', team_path(@team), method: :delete, confirm: "You are sure?", class: "btn btn-remove btn-small"
%h3.page_title
Issues
%small (in Team projects assigned to Team members)
%small.pull-right #{@issues.total_count} issues
%hr
.row
.span3
= render 'filter', entity: 'issue'
.span9
- if @issues.any?
- @issues.group_by(&:project).each do |group|
%div.ui-box
- @project = group[0]
%h5.title
= link_to_project @project
%ul.well-list.issues-list
- group[1].each do |issue|
= render issue
%hr
= paginate @issues, theme: "gitlab"
- else
%p.nothing_here_message Nothing to show here
= form_tag admin_team_member_path(@team, @member), method: :put do
-if @member.errors.any?
.alert.alert-error
%ul
- @member.errors.full_messages.each do |msg|
%li= msg
.clearfix
%label Default access for Team projects:
.input
= select_tag :default_project_access, options_for_select(UserTeam.access_roles, @team.default_projects_access(@member)), class: "project-access-select chosen span3"
.clearfix
%label Team admin?
.input
= check_box_tag :group_admin, true, @team.admin?(@member)
%br
.actions
= submit_tag 'Save', class: "btn btn-save"
= link_to 'Cancel', :back, class: "btn"
- user = member.user
- allow_admin = can? current_user, :manage_user_team, @team
%li{id: dom_id(member), class: "team_member_row user_#{user.id}"}
.row
.span3
= link_to user_path(user.username), title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 40), class: "avatar s32"
= link_to user_path(user.username), title: user.name, class: "dark" do
%strong= truncate(user.name, lenght: 40)
%br
%small.cgray= user.username
.span5.pull-right
- if allow_admin
.pull-left
= form_for(member, as: :team_member, url: team_member_path(@team, user)) do |f|
= label_tag :group_admin do
= f.check_box :group_admin, class: 'trigger-submit'
%span Admin access
&nbsp;
= f.select :permission, options_for_select(UsersProject.access_roles, @team.default_projects_access(user)), {}, class: "span2 trigger-submit"
.pull-right
- if current_user == user
%span.label.label-success This is you!
- if @team.owner == user
%span.label.label-info Owner
- elsif user.blocked?
%span.label.label-error Blocked
- elsif allow_admin
= link_to team_member_path(@team, user), confirm: remove_from_user_team_message(@team, user), method: :delete, class: "btn-tiny btn btn-remove", title: "Remove from team" do
%i.icon-minus.icon-white
- grouped_user_team_members(team).each do |access, members|
- access_key = Project.access_options.key(access)
- next if params[:type].present? && params[:type] != access_key.tableize
.ui-box
%h5.title
= access_key.pluralize
%small= members.size
%ul.well-list.team-members
- members.sort_by(&:user_name).each do |member|
= render 'teams/members/member', member: member
%h3.page_title
Edit access #{@member.name} in #{@team.name} team
%hr
%table.zebra-striped
%tr
%td User:
%td= @member.name
%tr
%td Team:
%td= @team.name
%tr
%td Since:
%td= member_since(@team, @member).stamp("Nov 11, 2010")
= render 'form'
%h3.page_title
Team Members
(#{@members.count})
%small
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
- if can? current_user, :manage_user_team, @team
%span.pull-right
= link_to new_team_member_path(@team), class: "btn btn-primary small grouped", title: "New Team Member" do
New Team Member
%hr
.row
.span3
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if !params[:type])}
= link_to team_members_path(@team, type: nil) do
All
%li{class: ("active" if params[:type] == 'masters')}
= link_to team_members_path(@team, type: 'masters') do
Masters
%li{class: ("active" if params[:type] == 'developers')}
= link_to team_members_path(@team, type: 'developers') do
Developers
%li{class: ("active" if params[:type] == 'reporters')}
= link_to team_members_path(@team, type: 'reporters') do
Reporters
%li{class: ("active" if params[:type] == 'guests')}
= link_to team_members_path(@team, type: 'guests') do
Guests
.span9
.clearfix
%div.team-table
= render "teams/members/team", team: @team
%h3.page_title
Team: #{@team.name}
%hr
= form_tag team_members_path(@team), id: "team_members", class: "bulk_import", method: :post do
%h6 1. Choose people you want in the team
.clearfix
= label_tag :user_ids, "People"
.input
= users_select_tag(:user_ids, multiple: true)
%h6 2. Set access level for them
.clearfix
= label_tag :project_access, "Project Access"
.input= select_tag :default_project_access, options_for_select(Project.access_options), class: "project-access-select chosen"
.clearfix
= label_tag :group_admin do
%span Team Admin?
.input= check_box_tag :group_admin
.actions
= submit_tag 'Add users', class: "btn btn-create", id: :add_members_to_team
= link_to "Cancel", team_members_path(@team), class: "btn btn-cancel"
%h3.page_title
Merge Requests
%small (authored by or assigned to Team members)
%small.pull-right #{@merge_requests.total_count} merge requests
%hr
.row
.span3
= render 'filter', entity: 'merge_request'
.span9
- if @merge_requests.any?
- @merge_requests.group_by(&:project).each do |group|
.ui-box
- @project = group[0]
%h5.title
= link_to_project @project
%ul.well-list
- group[1].each do |merge_request|
= render(partial: 'merge_requests/merge_request', locals: {merge_request: merge_request})
%hr
= paginate @merge_requests, theme: "gitlab"
- else
%h3.nothing_here_message Nothing to show here
= form_for @team, url: teams_path do |f|
- if @team.errors.any?
.alert.alert-error
%span= @team.errors.full_messages.first
.clearfix
= f.label :name do
Team name is
.input
= f.text_field :name, placeholder: "Ex. Ruby Developers", class: "xxlarge left"
.clearfix.team-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.clearfix
.input
%ul
%li All created teams are public (users can view who enter into team and which project are assigned for this team)
%li People within a team see only projects they have access to
%li You will be able to assign existing projects for team
.form-actions
= f.submit 'Create team', class: "btn btn-create"
- if current_user.can_create_group?
.clearfix
.input.light
Need a group for several dependent projects?
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
- if current_user.can_create_project?
.clearfix
.input.light
Want to create a project?
= link_to new_project_path, class: "btn btn-tiny" do
Create a project
= form_tag team_project_path(@team, @project), method: :put do
-if @project.errors.any?
.alert.alert-error
%ul
- @project.errors.full_messages.each do |msg|
%li= msg
.clearfix
%label Max access for Team members:
.input
= select_tag :greatest_project_access, options_for_select(UserTeam.access_roles, @team.max_project_access(@project)), class: "project-access-select chosen span3"
%br
.actions
= submit_tag 'Save', class: "btn btn-save"
= link_to 'Cancel', :back, class: "btn btn-cancel"
%h3.page_title
Edit max access in #{link_to @project.name_with_namespace, @project} for #{link_to(@team.name, team_path(@team))} team
%hr
= render 'form'
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "Team feed - #{@team.name}"
xml.link :href => team_url(@team, :atom), :rel => "self", :type => "application/atom+xml"
xml.link :href => team_url(@team), :rel => "alternate", :type => "text/html"
xml.id projects_url
xml.updated @events.maximum(:updated_at).strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
if event.proper?
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link :href => event_link
xml.title truncate(event_title, :length => 80)
xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary event_title
end
end
end
end
.dashboard
.activities.span8
= link_to dashboard_path, class: 'btn btn-tiny' do
&larr; To dashboard
&nbsp;
%span.cgray Events and projects are filtered in scope of team
%hr
- if @events.any?
.content_list
- else
%p.nothing_here_message Projects activity will be displayed here
.loading.hide
.side.span4
- if @team.description.present?
.description-block
= @team.description
= render "projects", projects: @projects
.prepend-top-20
= link_to team_path(@team, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
%strong
%i.icon-rss
News Feed
%hr
= render 'shared/promo'
:plain
Pager.append(#{@events.count}, "#{escape_javascript(render(@events))}");
......@@ -155,20 +155,6 @@ Gitlab::Application.routes.draw do
resources :users_groups, only: [:create, :update, :destroy]
end
#
# Teams Area
#
resources :teams, constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} do
member do
get :issues
get :merge_requests
end
scope module: :teams do
resources :members, only: [:index, :new, :create, :edit, :update, :destroy]
resources :projects, only: [:index, :new, :create, :edit, :update, :destroy], constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }
end
end
resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations }
......@@ -307,18 +293,6 @@ Gitlab::Application.routes.draw do
end
end
scope module: :projects do
resources :teams, only: [] do
collection do
get :available
post :assign
end
member do
delete :resign
end
end
end
resources :notes, only: [:index, :create, :destroy] do
collection do
post :preview
......
Feature: Admin Teams
Background:
Given I sign in as an admin
And Create gitlab user "John"
Scenario: Create a team
When I visit admin teams page
And I click new team link
And submit form with new team info
Then I should be redirected to team page
And I should see newly created team
Scenario: Add user to team
When I visit admin teams page
When I have clean "HardCoders" team
And I visit "HardCoders" team page
When I click to "Add members" link
When I select user "John" from user list as "Developer"
And submit form with new team member info
Then I should see "John" in teams members list as "Developer"
Scenario: Assign team to existing project
When I visit admin teams page
When I have "HardCoders" team with "John" member with "Developer" role
When I have "Shop" project
And I visit "HardCoders" team page
Then I should see empty projects table
When I click to "Add projects" link
When I select project "Shop" with max access "Reporter"
And submit form with new team project info
Then I should see "Shop" project in projects list
When I visit "Shop" project admin page
Then I should see "John" user with role "Reporter" in team table
Scenario: Add user to team with ptojects
When I visit admin teams page
When I have "HardCoders" team with "John" member with "Developer" role
And "HardCoders" team assigned to "Shop" project with "Developer" max role access
When I have gitlab user "Jimm"
And I visit "HardCoders" team page
Then I should see members table without "Jimm" member
When I click to "Add members" link
When I select user "Jimm" ub team members list as "Master"
And submit form with new team member info
Then I should see "Jimm" in teams members list as "Master"
Scenario: Remove member from team
Given I have users team "HardCoders"
And gitlab user "John" is a member "HardCoders" team
And gitlab user "Jimm" is a member "HardCoders" team
And "HardCoders" team is assigned to "Shop" project
When I visit admin teams page
When I visit "HardCoders" team admin page
Then I shoould see "John" in members list
And I should see "Jimm" in members list
And I should see "Shop" in projects list
When I click on remove "Jimm" user link
Then I should be redirected to "HardCoders" team admin page
And I should not to see "Jimm" user in members list
Scenario: Remove project from team
Given I have users team "HardCoders"
And gitlab user "John" is a member "HardCoders" team
And gitlab user "Jimm" is a member "HardCoders" team
And "HardCoders" team is assigned to "Shop" project
When I visit admin teams page
When I visit "HardCoders" team admin page
Then I should see "Shop" project in projects list
When I click on "Relegate" link on "Shop" project
Then I should see projects liston team page without "Shop" project
class AdminTeams < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedActiveTab
include SharedAdmin
And 'I have own project' do
create :project
end
And 'Create gitlab user "John"' do
@user = create(:user, name: "John")
end
And 'I click new team link' do
click_link "New Team"
end
And 'submit form with new team info' do
fill_in 'user_team_name', with: 'gitlab'
fill_in 'user_team_description', with: 'description'
click_button 'Create team'
end
Then 'I should be redirected to team page' do
current_path.should == admin_team_path(UserTeam.last)
end
And 'I should see newly created team' do
page.should have_content "Team: gitlab"
page.should have_content "description"
end
When 'I visit admin teams page' do
visit admin_teams_path
end
When 'I have clean "HardCoders" team' do
@team = create :user_team, name: "HardCoders", owner: current_user
end
And 'I visit "HardCoders" team page' do
visit admin_team_path(UserTeam.find_by_name("HardCoders"))
end
Then 'I should see only me in members table' do
members_list = find("#members_list .member")
members_list.should have_content(current_user.name)
members_list.should have_content(current_user.username)
end
When 'I select user "John" from user list as "Developer"' do
@user ||= User.find_by_name("John")
within "#team_members" do
select "#{@user.name} (#{@user.username})", from: "user_ids"
select "Developer", from: "default_project_access"
end
end
And 'submit form with new team member info' do
click_button 'add_members_to_team'
end
Then 'I should see "John" in teams members list as "Developer"' do
@user ||= User.find_by_name("John")
find_in_list("#members_list .member", @user).must_equal true
end
When 'I visit "John" user admin page' do
pending 'step not implemented'
end
Then 'I should see "HardCoders" team in teams table' do
pending 'step not implemented'
end
When 'I have "HardCoders" team with "John" member with "Developer" role' do
@team = create :user_team, name: "HardCoders", owner: current_user
@user ||= User.find_by_name("John")
@team.add_member(@user, UserTeam.access_roles["Developer"], group_admin: false)
end
When 'I have "Shop" project' do
@project = create :project, name: "Shop"
end
Then 'I should see empty projects table' do
page.should have_content "Projects (0)"
end
When 'I select project "Shop" with max access "Reporter"' do
@project ||= Project.find_by_name("Shop")
within "#assign_projects" do
select @project.name, from: "project_ids"
select "Reporter", from: "greatest_project_access"
end
end
And 'submit form with new team project info' do
click_button 'assign_projects_to_team'
end
Then 'I should see "Shop" project in projects list' do
project = Project.find_by_name("Shop")
find_in_list("#projects_list .project", project).must_equal true
end
When 'I visit "Shop" project admin page' do
project = Project.find_by_name("Shop")
visit admin_project_path(project)
end
And '"HardCoders" team assigned to "Shop" project with "Developer" max role access' do
@team = UserTeam.find_by_name("HardCoders")
@project = create :project, name: "Shop"
@team.assign_to_project(@project, UserTeam.access_roles["Developer"])
end
When 'I have gitlab user "Jimm"' do
create :user, name: "Jimm"
end
Then 'I should see members table without "Jimm" member' do
user = User.find_by_name("Jimm")
find_in_list("#members_list .member", user).must_equal false
end
When 'I select user "Jimm" ub team members list as "Master"' do
user = User.find_by_name("Jimm")
within "#team_members" do
select "#{user.name} (#{user.username})", from: "user_ids"
select "Developer", from: "default_project_access"
end
end
Then 'I should see "Jimm" in teams members list as "Master"' do
user = User.find_by_name("Jimm")
find_in_list("#members_list .member", user).must_equal true
end
Given 'I have users team "HardCoders"' do
@team = create :user_team, name: "HardCoders"
end
And 'gitlab user "John" is a member "HardCoders" team' do
@team = UserTeam.find_by_name("HardCoders")
@user = User.find_by_name("John")
@user = create :user, name: "John" unless @user
@team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
end
And 'gitlab user "Jimm" is a member "HardCoders" team' do
@team = UserTeam.find_by_name("HardCoders")
@user = User.find_by_name("Jimm")
@user = create :user, name: "Jimm" unless @user
@team.add_member(@user, UserTeam.access_roles["Master"], group_admin: false)
end
And '"HardCoders" team is assigned to "Shop" project' do
@team = UserTeam.find_by_name("HardCoders")
@project = create :project, name: "Shop"
@team.assign_to_project(@project, UserTeam.access_roles["Developer"])
end
When 'I visit "HardCoders" team admin page' do
visit admin_team_path(UserTeam.find_by_name("HardCoders"))
end
Then 'I shoould see "John" in members list' do
user = User.find_by_name("John")
find_in_list("#members_list .member", user).must_equal true
end
And 'I should see "Jimm" in members list' do
user = User.find_by_name("Jimm")
find_in_list("#members_list .member", user).must_equal true
end
And 'I should see "Shop" in projects list' do
project = Project.find_by_name("Shop")
find_in_list("#projects_list .project", project).must_equal true
end
When 'I click on remove "Jimm" user link' do
user = User.find_by_name("Jimm")
click_link "remove_member_#{user.id}"
end
Then 'I should be redirected to "HardCoders" team admin page' do
current_path.should == admin_team_path(UserTeam.find_by_name("HardCoders"))
end
And 'I should not to see "Jimm" user in members list' do
user = User.find_by_name("Jimm")
find_in_list("#members_list .member", user).must_equal false
end
When 'I click on "Relegate" link on "Shop" project' do
project = Project.find_by_name("Shop")
click_link "relegate_project_#{project.id}"
end
Then 'I should see projects liston team page without "Shop" project' do
project = Project.find_by_name("Shop")
find_in_list("#projects_list .project", project).must_equal false
end
Then 'I should see "John" user with role "Reporter" in team table' do
user = User.find_by_name("John")
find_in_list(".team_members", user).must_equal true
end
When 'I click to "Add members" link' do
click_link "Add members"
end
When 'I click to "Add projects" link' do
click_link "Add projects"
end
protected
def current_team
@team ||= Team.first
end
def find_in_list(selector, item)
members_list = all(selector)
entered = false
members_list.each do |member_item|
entered = true if member_item.has_content?(item.name)
end
entered
end
end
class Userteams < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
include Select2Helper
When 'I do not have teams with me' do
UserTeam.with_member(current_user).destroy_all
end
Then 'I should see dashboard page without teams info block' do
page.has_no_css?(".teams-box").must_equal true
end
When 'I have teams with my membership' do
team = create :user_team, owner: current_user
team.add_member(current_user, UserTeam.access_roles["Master"], true)
end
Then 'I should see dashboard page with teams information block' do
page.should have_css(".teams-box")
end
When 'exist user teams' do
team = create :user_team
team.add_member(current_user, UserTeam.access_roles["Master"], true)
end
And 'I click on "All teams" link' do
click_link("All Teams")
end
Then 'I should see "All teams" page' do
current_path.should == teams_path
end
And 'I should see exist teams in teams list' do
team = UserTeam.last
find_in_list(".teams_list tr", team).must_equal true
end
When 'I click to "New team" link' do
click_link("New Team")
end
And 'I submit form with new team info' do
fill_in 'name', with: 'gitlab'
fill_in 'user_team_description', with: 'team description'
click_button 'Create team'
end
And 'I should see newly created team' do
page.should have_content "gitlab"
page.should have_content "team description"
end
Then 'I should be redirected to new team page' do
team = UserTeam.last
current_path.should == team_path(team)
end
When 'I have teams with projects and members' do
team = create :user_team, owner: current_user
@project = create :project
team.add_member(current_user, UserTeam.access_roles["Master"], true)
team.assign_to_project(@project, UserTeam.access_roles["Master"])
@event = create(:closed_issue_event, project: @project)
end
When 'I visit team page' do
visit team_path(UserTeam.last)
end
Then 'I should see projects list' do
within(".side .ui-box") do
page.should have_content(@project.name)
end
end
And 'project from team has issues assigned to me' do
team = UserTeam.last
team.projects.each do |project|
project.issues << create(:issue, assignee: current_user)
end
end
When 'I visit team issues page' do
team = UserTeam.last
visit issues_team_path(team)
end
Then 'I should see issues from this team assigned to me' do
team = UserTeam.last
team.projects.each do |project|
project.issues.assigned_to(current_user).each do |issue|
page.should have_content issue.title
end
end
end
Given 'I have team with projects and members' do
team = create :user_team, owner: current_user
project = create :project
user = create :user
team.add_member(current_user, UserTeam.access_roles["Master"], true)
team.add_member(user, UserTeam.access_roles["Developer"], false)
team.assign_to_project(project, UserTeam.access_roles["Master"])
end
Given 'project from team has issues assigned to teams members' do
team = UserTeam.last
team.projects.each do |project|
team.members.each do |member|
project.issues << create(:issue, assignee: member)
end
end
end
Then 'I should see issues from this team assigned to teams members' do
team = UserTeam.last
team.projects.each do |project|
team.members.each do |member|
project.issues.assigned_to(member).each do |issue|
page.should have_content issue.title
end
end
end
end
Given 'project from team has merge requests assigned to me' do
team = UserTeam.last
team.projects.each do |project|
create(:merge_request, assignee: current_user, project: project)
end
end
When 'I visit team merge requests page' do
team = UserTeam.last
visit merge_requests_team_path(team)
end
Then 'I should see merge requests from this team assigned to me' do
team = UserTeam.last
team.projects.each do |project|
project.merge_requests.each do |merge_request|
page.should have_content merge_request.title
end
end
end
Given 'project from team has merge requests assigned to team members' do
team = UserTeam.last
team.projects.each do |project|
member = team.members.sample
create(:merge_request, assignee: member, project: project)
end
end
Given 'I have new user "John"' do
create :user, name: "John"
end
When 'I visit team people page' do
team = UserTeam.last
visit team_members_path(team)
end
And 'I select user "John" from list with role "Reporter"' do
user = User.find_by_name("John")
select2(user.id, from: "#user_ids", multiple: true)
within "#team_members" do
select "Reporter", from: "default_project_access"
end
click_button "Add"
end
Then 'I should see user "John" in team list' do
user = User.find_by_name("John")
team_members_list = find(".team-table")
team_members_list.should have_content user.name
end
And 'I have my own project without teams' do
@project = create :project, namespace: current_user.namespace
end
And 'I visit my team page' do
team = UserTeam.where(owner_id: current_user.id).last
visit team_path(team)
end
When 'I click on link "Assign Project"' do
click_link "Assign Project"
end
Then 'I should see form with my own project in available projects list' do
projects_select = find("#project_ids")
projects_select.should have_content(@project.name)
end
When 'I submit form with selected project and max access' do
within "#assign_projects" do
select @project.name_with_namespace, from: "project_ids"
select "Reporter", from: "greatest_project_access"
end
click_button "Add"
end
Then 'I should see my own project in team projects list' do
projects = find(".projects-table")
projects.should have_content(@project.name)
end
When 'I click link "New Team Member"' do
click_link "New Team Member"
end
protected
def current_team
@user_team ||= UserTeam.first
end
def project
current_team.projects.first
end
def assigned_to_user key, user
project.send(key).where(assignee_id: user)
end
def find_in_list(selector, item)
members_list = all(selector)
entered = false
members_list.each do |member_item|
entered = true if member_item.has_content?(item.name)
end
entered
end
end
Feature: UserTeams
Background:
Given I sign in as a user
And I own project "Shop"
And project "Shop" has push event
Scenario: I should see teams info block
When I have teams with my membership
And I visit dashboard page
Then I should see dashboard page with teams information block
Scenario: I should can create new team
When I have teams with my membership
And I visit dashboard page
When I click to "New team" link
And I submit form with new team info
Then I should be redirected to new team page
Then I should see newly created team
Scenario: I should see team dashboard list
When I have teams with projects and members
When I visit team page
Then I should see projects list
Scenario: I should see team issues list
Given I have team with projects and members
And project from team has issues assigned to me
When I visit team issues page
Then I should see issues from this team assigned to me
Scenario: I should see teams members issues list
Given I have team with projects and members
Given project from team has issues assigned to teams members
When I visit team issues page
Then I should see issues from this team assigned to teams members
Scenario: I should see team merge requests list
Given I have team with projects and members
Given project from team has merge requests assigned to me
When I visit team merge requests page
Then I should see merge requests from this team assigned to me
Scenario: I should see teams members merge requests list
Given I have team with projects and members
Given project from team has merge requests assigned to team members
When I visit team merge requests page
Then I should see merge requests from this team assigned to me
@javascript
Scenario: I should add user to projects in Team
Given I have team with projects and members
Given I have new user "John"
When I visit team people page
When I click link "New Team Member"
And I select user "John" from list with role "Reporter"
Then I should see user "John" in team list
Scenario: I should assign my team to my own project
Given I have team with projects and members
And I have my own project without teams
And I visit my team page
When I click on link "Assign Project"
Then I should see form with my own project in available projects list
When I submit form with selected project and max access
Then I should see my own project in team projects list
......@@ -35,7 +35,6 @@ module API
mount Notes
mount Internal
mount SystemHooks
mount UserTeams
mount ProjectSnippets
mount DeployKeys
mount ProjectHooks
......
......@@ -99,10 +99,6 @@ module API
expose :id, :title, :key, :created_at
end
class UserTeam < Grape::Entity
expose :id, :name, :path, :owner_id
end
class MergeRequest < Grape::Entity
expose :id, :target_branch, :source_branch, :project_id, :title, :state
expose :author, :assignee, using: Entities::UserBasic
......
module API
# user_teams API
class UserTeams < Grape::API
before { authenticate! }
resource :user_teams do
helpers do
def handle_team_member_errors(errors)
if errors[:permission].any?
render_api_error!(errors[:permission], 422)
end
not_found!
end
def validate_access_level?(level)
[UsersProject::GUEST, UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER].include? level.to_i
end
end
# Get a user_teams list
#
# Example Request:
# GET /user_teams
get do
if current_user.admin
@user_teams = paginate UserTeam
else
@user_teams = paginate current_user.user_teams
end
present @user_teams, with: Entities::UserTeam
end
# Create user_team. Available only for admin
#
# Parameters:
# name (required) - The name of the user_team
# path (required) - The path of the user_team
# Example Request:
# POST /user_teams
post do
authenticated_as_admin!
required_attributes! [:name, :path]
attrs = attributes_for_keys [:name, :path]
@user_team = UserTeam.new(attrs)
@user_team.owner = current_user
if @user_team.save
present @user_team, with: Entities::UserTeam
else
not_found!
end
end
# Get a single user_team
#
# Parameters:
# id (required) - The ID of a user_team
# Example Request:
# GET /user_teams/:id
get ":id" do
@user_team = UserTeam.find(params[:id])
if current_user.admin or current_user.user_teams.include? @user_team
present @user_team, with: Entities::UserTeam
else
not_found!
end
end
# Get user_team members
#
# Parameters:
# id (required) - The ID of a user_team
# Example Request:
# GET /user_teams/:id/members
get ":id/members" do
@user_team = UserTeam.find(params[:id])
if current_user.admin or current_user.user_teams.include? @user_team
@members = paginate @user_team.members
present @members, with: Entities::TeamMember, user_team: @user_team
else
not_found!
end
end
# Add a new user_team member
#
# Parameters:
# id (required) - The ID of a user_team
# user_id (required) - The ID of a user
# access_level (required) - Project access level
# Example Request:
# POST /user_teams/:id/members
post ":id/members" do
authenticated_as_admin!
required_attributes! [:user_id, :access_level]
if not validate_access_level?(params[:access_level])
render_api_error!("Wrong access level", 422)
end
@user_team = UserTeam.find(params[:id])
if @user_team
team_member = @user_team.user_team_user_relationships.find_by_user_id(params[:user_id])
# Not existing member
if team_member.nil?
@user_team.add_member(params[:user_id], params[:access_level], false)
team_member = @user_team.user_team_user_relationships.find_by_user_id(params[:user_id])
if team_member.nil?
render_api_error!("Error creating membership", 500)
else
@member = team_member.user
present @member, with: Entities::TeamMember, user_team: @user_team
end
else
render_api_error!("Already exists", 409)
end
else
not_found!
end
end
# Get a single team member from user_team
#
# Parameters:
# id (required) - The ID of a user_team
# user_id (required) - The ID of a team member
# Example Request:
# GET /user_teams/:id/members/:user_id
get ":id/members/:user_id" do
@user_team = UserTeam.find(params[:id])
if current_user.admin or current_user.user_teams.include? @user_team
team_member = @user_team.user_team_user_relationships.find_by_user_id(params[:user_id])
unless team_member.nil?
present team_member.user, with: Entities::TeamMember, user_team: @user_team
else
not_found!
end
else
not_found!
end
end
# Remove a team member from user_team
#
# Parameters:
# id (required) - The ID of a user_team
# user_id (required) - The ID of a team member
# Example Request:
# DELETE /user_teams/:id/members/:user_id
delete ":id/members/:user_id" do
authenticated_as_admin!
@user_team = UserTeam.find(params[:id])
if @user_team
team_member = @user_team.user_team_user_relationships.find_by_user_id(params[:user_id])
unless team_member.nil?
team_member.destroy
else
not_found!
end
else
not_found!
end
end
# Get to user_team assigned projects
#
# Parameters:
# id (required) - The ID of a user_team
# Example Request:
# GET /user_teams/:id/projects
get ":id/projects" do
@user_team = UserTeam.find(params[:id])
if current_user.admin or current_user.user_teams.include? @user_team
@projects = paginate @user_team.projects
present @projects, with: Entities::TeamProject, user_team: @user_team
else
not_found!
end
end
# Add a new user_team project
#
# Parameters:
# id (required) - The ID of a user_team
# project_id (required) - The ID of a project
# greatest_access_level (required) - Project access level
# Example Request:
# POST /user_teams/:id/projects
post ":id/projects" do
authenticated_as_admin!
required_attributes! [:project_id, :greatest_access_level]
if not validate_access_level?(params[:greatest_access_level])
render_api_error!("Wrong greatest_access_level", 422)
end
@user_team = UserTeam.find(params[:id])
if @user_team
team_project = @user_team.user_team_project_relationships.find_by_project_id(params[:project_id])
# No existing project
if team_project.nil?
@user_team.assign_to_projects([params[:project_id]], params[:greatest_access_level])
team_project = @user_team.user_team_project_relationships.find_by_project_id(params[:project_id])
if team_project.nil?
render_api_error!("Error creating project assignment", 500)
else
@project = team_project.project
present @project, with: Entities::TeamProject, user_team: @user_team
end
else
render_api_error!("Already exists", 409)
end
else
not_found!
end
end
# Show a single team project from user_team
#
# Parameters:
# id (required) - The ID of a user_team
# project_id (required) - The ID of a project assigned to the team
# Example Request:
# GET /user_teams/:id/projects/:project_id
get ":id/projects/:project_id" do
@user_team = UserTeam.find(params[:id])
if current_user.admin or current_user.user_teams.include? @user_team
team_project = @user_team.user_team_project_relationships.find_by_project_id(params[:project_id])
unless team_project.nil?
present team_project.project, with: Entities::TeamProject, user_team: @user_team
else
not_found!
end
else
not_found!
end
end
# Remove a team project from user_team
#
# Parameters:
# id (required) - The ID of a user_team
# project_id (required) - The ID of a project assigned to the team
# Example Request:
# DELETE /user_teams/:id/projects/:project_id
delete ":id/projects/:project_id" do
authenticated_as_admin!
@user_team = UserTeam.find(params[:id])
if @user_team
team_project = @user_team.user_team_project_relationships.find_by_project_id(params[:project_id])
unless team_project.nil?
team_project.destroy
else
not_found!
end
else
not_found!
end
end
end
end
end
# UserTeamManager class
#
# Used for manage User teams with project repositories
module Gitlab
class UserTeamManager
class << self
def assign(team, project, access)
project = Project.find(project) unless project.is_a? Project
searched_project = team.user_team_project_relationships.find_by_project_id(project.id)
unless searched_project.present?
team.user_team_project_relationships.create(project_id: project.id, greatest_access: access)
update_team_users_access_in_project(team, project, :added)
end
end
def resign(team, project)
project = Project.find(project) unless project.is_a? Project
team.user_team_project_relationships.with_project(project).destroy_all
update_team_users_access_in_project(team, project, :updated)
end
def update_team_user_membership(team, member, options)
updates = {}
if options[:default_projects_access].present?
default_projects_access = options[:default_projects_access].to_s
if default_projects_access != team.default_projects_access(member).to_s
updates[:permission] = default_projects_access
end
end
if options[:group_admin].present?
group_admin = options[:group_admin].to_s == "1" ? true : false
if group_admin != team.admin?(member)
updates[:group_admin] = group_admin
end
end
return true if updates.blank?
user_team_relationship = team.user_team_user_relationships.find_by_user_id(member)
return false unless user_team_relationship.update_attributes(updates)
rebuild_project_permissions_to_member(team, member) if updates[:permission]
true
end
def update_project_greates_access(team, project, permission)
project_relation = team.user_team_project_relationships.find_by_project_id(project)
if permission != team.max_project_access(project)
if project_relation.update_attributes(greatest_access: permission)
update_team_users_access_in_project(team, project, :updated)
true
else
false
end
else
true
end
end
def rebuild_project_permissions_to_member(team, member)
team.projects.each do |project|
update_team_user_access_in_project(team, member, project, :updated)
end
end
def update_team_users_access_in_project(team, project, action)
members = team.members
members.each do |member|
update_team_user_access_in_project(team, member, project, action)
end
end
def update_team_user_access_in_project(team, user, project, action)
granted_access = max_teams_member_permission_in_project(user, project, action)
project_team_user = UsersProject.find_by_user_id_and_project_id(user.id, project.id)
if granted_access.zero?
project_team_user.destroy if project_team_user.present?
return
end
if project_team_user.present?
project_team_user.update_attributes(project_access: granted_access)
else
project.team << [user, granted_access]
end
end
def max_teams_member_permission_in_project(user, project, action = nil, teams = nil)
result_access = 0
teams ||= project.user_teams.with_member(user)
if action && (action == :added)
result_access = project.users_projects.with_user(user).first.project_access if project.users_projects.with_user(user).any?
end
if teams.any?
teams.each do |team|
granted_access = max_team_member_permission_in_project(team, user, project)
result_access = [granted_access, result_access].max
end
end
result_access
end
def max_team_member_permission_in_project(team, user, project)
member_access = team.default_projects_access(user)
team_access = team.user_team_project_relationships.find_by_project_id(project.id).greatest_access
[team_access, member_access].min
end
def add_member_into_team(team, user, access, admin)
user = User.find(user) unless user.is_a? User
team.user_team_user_relationships.create(user_id: user.id, permission: access, group_admin: admin)
team.projects.each do |project|
update_team_user_access_in_project(team, user, project, :added)
end
end
def remove_member_from_team(team, user)
user = User.find(user) unless user.is_a? User
team.user_team_user_relationships.with_user(user).destroy_all
other_teams = []
team.projects.each do |project|
other_teams << project.user_teams.with_member(user)
end
other_teams.uniq
unless other_teams.any?
UsersProject.in_projects(team.projects).with_user(user).destroy_all
end
end
end
end
end
# == Schema Information
#
# Table name: user_team_project_relationships
#
# id :integer not null, primary key
# project_id :integer
# user_team_id :integer
# greatest_access :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :user_team_project_relationship do
project
user_team
greatest_access { UsersProject::MASTER }
end
end
# == Schema Information
#
# Table name: user_team_user_relationships
#
# id :integer not null, primary key
# user_id :integer
# user_team_id :integer
# group_admin :boolean
# permission :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :user_team_user_relationship do
user
user_team
group_admin false
permission { UsersProject::MASTER }
end
end
# == Schema Information
#
# Table name: user_teams
#
# id :integer not null, primary key
# name :string(255)
# path :string(255)
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255) default(""), not null
#
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :user_team do
sequence(:name) { |n| "team#{n}" }
sequence(:description) { |n| "team_description#{n}" }
path { name.downcase.gsub(/\s/, '_') }
owner
end
end
require 'spec_helper'
describe Gitlab::UserTeamManager do
before do
@user = create :user
@project = create :project, creator: @user
@master = create :user
@developer = create :user
@reporter = create :user
@project.team << [@master, :master]
@project.team << [@developer, :developer]
@project.team << [@reporter, :reporter]
@team = create :user_team, owner: @user
@team.add_members([@master.id, @developer.id, @reporter.id], UsersProject::DEVELOPER, false)
end
it "should assign team to project with correct permissions result" do
@team.assign_to_project(@project, UsersProject::MASTER)
@project.users_projects.find_by_user_id(@master).project_access.should == UsersProject::MASTER
@project.users_projects.find_by_user_id(@developer).project_access.should == UsersProject::DEVELOPER
@project.users_projects.find_by_user_id(@reporter).project_access.should == UsersProject::DEVELOPER
end
end
......@@ -148,23 +148,6 @@ describe User do
it { @user.owned_groups.should == [@group] }
end
describe 'teams' do
before do
ActiveRecord::Base.observers.enable(:user_observer)
@admin = create :user, admin: true
@user1 = create :user
@user2 = create :user
@team = create :user_team, owner: @user1
end
it { @admin.authorized_teams.should == [@team] }
it { @user1.authorized_teams.should == [@team] }
it { @user2.authorized_teams.should be_empty }
it { @admin.should be_can(:manage_user_team, @team) }
it { @user1.should be_can(:manage_user_team, @team) }
it { @user2.should_not be_can(:manage_user_team, @team) }
end
describe 'namespaced' do
before do
ActiveRecord::Base.observers.enable(:user_observer)
......
# == Schema Information
#
# Table name: user_team_project_relationships
#
# id :integer not null, primary key
# project_id :integer
# user_team_id :integer
# greatest_access :integer
# created_at :datetime not null
# updated_at :datetime not null
#
require 'spec_helper'
describe UserTeamProjectRelationship do
pending "add some examples to (or delete) #{__FILE__}"
end
# == Schema Information
#
# Table name: user_teams
#
# id :integer not null, primary key
# name :string(255)
# path :string(255)
# owner_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# description :string(255) default(""), not null
#
require 'spec_helper'
describe UserTeam do
let(:team) { FactoryGirl.create :user_team }
context ".add_member" do
let(:user) { FactoryGirl.create :user }
it "should work" do
team.add_member(user, UsersProject::DEVELOPER, false)
team.members.should include(user)
end
end
context ".remove_member" do
let(:user) { FactoryGirl.create :user }
before { team.add_member(user, UsersProject::DEVELOPER, false) }
it "should work" do
team.remove_member(user)
team.members.should_not include(user)
end
end
end
# == Schema Information
#
# Table name: user_team_user_relationships
#
# id :integer not null, primary key
# user_id :integer
# user_team_id :integer
# group_admin :boolean
# permission :integer
# created_at :datetime not null
# updated_at :datetime not null
#
require 'spec_helper'
describe UserTeamUserRelationship do
pending "add some examples to (or delete) #{__FILE__}"
end
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment