Merge branch 'feature/users_groups' into 6-0-dev

This commit is contained in:
Dmitriy Zaporozhets 2013-06-18 19:34:32 +03:00
commit 30d2d2381f
41 changed files with 406 additions and 262 deletions

View file

@ -32,6 +32,8 @@ class Dispatcher
new Wall(project_id)
when 'teams:members:index'
new TeamMembers()
when 'groups:people'
new GroupMembers()
switch path.first()
when 'admin' then new Admin()

View file

@ -0,0 +1,6 @@
class GroupMembers
constructor: ->
$('li.users_group').bind 'ajax:success', ->
$(this).fadeOut()
@GroupMembers = GroupMembers

View file

@ -16,6 +16,12 @@
color: #888;
}
&.unstyled {
&:hover {
background: none;
}
}
&.smoke { background-color: #f5f5f5; }
&:hover {

View file

@ -66,14 +66,12 @@ class Admin::GroupsController < Admin::ApplicationController
end
def project_teams_update
@group.add_users_to_project_teams(params[:user_ids].split(','), params[:project_access])
@group.add_users(params[:user_ids].split(','), params[:group_access])
redirect_to [:admin, @group], notice: 'Users were successfully added.'
end
def destroy
@group.truncate_teams
@group.destroy
redirect_to admin_groups_path, notice: 'Group was successfully deleted.'

View file

@ -34,11 +34,12 @@ class DashboardController < ApplicationController
@projects
end
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.page(params[:page]).per(30)
@labels = Project.where(id: @projects.map(&:id)).tags_on(:labels)
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.page(params[:page]).per(30)
end
# Get authored or assigned open merge requests

View file

@ -10,7 +10,7 @@ class GraphsController < ProjectResourceController
format.js do
@repo = @project.repository
@stats = Gitlab::Git::GitStats.new(@repo.raw, @repo.root_ref)
@log = @stats.parsed_log.to_json
@log = @stats.parsed_log.to_json rescue []
end
end
end

View file

@ -1,6 +1,6 @@
class GroupsController < ApplicationController
respond_to :html
before_filter :group, except: [:new, :create]
before_filter :group, except: [:new, :create, :people]
# Authorize
before_filter :authorize_read_group!, except: [:new, :create]
@ -63,19 +63,8 @@ class GroupsController < ApplicationController
def people
@project = group.projects.find(params[:project_id]) if params[:project_id]
@users = @project ? @project.users : group.users
@users.sort_by!(&:name)
if @project
@team_member = @project.users_projects.new
else
@team_member = UsersProject.new
end
end
def team_members
@group.add_users_to_project_teams(params[:user_ids].split(','), params[:project_access])
redirect_to people_group_path(@group), notice: 'Users were successfully added.'
@members = group.users_groups.order('group_access DESC')
@users_group = UsersGroup.new
end
def edit
@ -83,7 +72,7 @@ class GroupsController < ApplicationController
def update
group_params = params[:group].dup
owner_id =group_params.delete(:owner_id)
owner_id = group_params.delete(:owner_id)
if owner_id
@group.owner = User.find(owner_id)

View file

@ -23,7 +23,7 @@ class IssuesController < ProjectResourceController
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
@assignee = @project.users.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
respond_to do |format|

View file

@ -4,10 +4,8 @@ class TeamMembersController < ProjectResourceController
before_filter :authorize_admin_project!, except: [:index, :show]
def index
@team = @project.users_projects.scoped
@team = @team.send(params[:type]) if %w(masters developers reporters guests).include?(params[:type])
@team = @team.sort_by(&:project_access).reverse.group_by(&:project_access)
@group = @project.group
@users_projects = @project.users_projects.order('project_access DESC')
@assigned_teams = @project.user_team_project_relationships
end

View file

@ -3,7 +3,7 @@ class UsersController < ApplicationController
def show
@user = User.find_by_username!(params[:username])
@projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id))
@projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id)).order('namespace_id DESC')
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
@title = @user.name

View file

@ -0,0 +1,40 @@
class UsersGroupsController < ApplicationController
before_filter :group
# Authorize
before_filter :authorize_admin_group!
layout 'group'
def create
@group.add_users(params[:user_ids].split(','), params[:group_access])
redirect_to people_group_path(@group), notice: 'Users were successfully added.'
end
def update
# TODO: implement
end
def destroy
@users_group = @group.users_groups.find(params[:id])
@users_group.destroy
respond_to do |format|
format.html { redirect_to people_group_path(@group), notice: 'User was successfully removed from group.' }
format.js { render nothing: true }
end
end
protected
def group
@group ||= Group.find_by_path(params[:group_id])
end
def authorize_admin_group!
unless can?(current_user, :manage_group, group)
return render_404
end
end
end

View file

@ -14,4 +14,8 @@ module GroupsHelper
merge_requests_group_path(@group, options)
end
end
def remove_user_from_group_message(group, user)
"You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
end
end

View file

@ -50,6 +50,10 @@ class Ability
rules << project_admin_rules
end
if project.group && project.group.owners.include?(user)
rules << project_admin_rules
end
rules.flatten
end
@ -132,7 +136,7 @@ class Ability
rules = []
# Only group owner and administrators can manage group
if group.owner == user || user.admin?
if group.owners.include?(user) || user.admin?
rules << [
:manage_group,
:manage_namespace

View file

@ -13,26 +13,28 @@
#
class Group < Namespace
has_many :users_groups, dependent: :destroy
has_many :users, through: :users_groups
def add_users_to_project_teams(user_ids, project_access)
UsersProject.add_users_into_projects(
projects.map(&:id),
user_ids,
project_access
)
end
def users
users = User.joins(:users_projects).where(users_projects: {project_id: project_ids})
users = users << owner
users.uniq
end
after_create :add_owner
def human_name
name
end
def truncate_teams
UsersProject.truncate_teams(project_ids)
def owners
@owners ||= (users_groups.owners.map(&:user) << owner)
end
def add_users(user_ids, group_access)
user_ids.compact.each do |user_id|
self.users_groups.create(user_id: user_id, group_access: group_access)
end
end
private
def add_owner
self.add_users([owner.id], UsersGroup::OWNER)
end
end

View file

@ -21,6 +21,16 @@ class ProjectTeam
end
end
def find user_id
user = project.users.find_by_id(user_id)
if group
user ||= group.users.find_by_id(user_id)
end
user
end
def get_tm user_id
project.users_projects.find_by_user_id(user_id)
end
@ -47,23 +57,23 @@ class ProjectTeam
end
def members
project.users_projects
fetch_members
end
def guests
members.guests.map(&:user)
@guests ||= fetch_members(:guests)
end
def reporters
members.reporters.map(&:user)
@reporters ||= fetch_members(:reporters)
end
def developers
members.developers.map(&:user)
@developers ||= fetch_members(:developers)
end
def masters
members.masters.map(&:user)
@masters ||= fetch_members(:masters)
end
def import(source_project)
@ -96,4 +106,22 @@ class ProjectTeam
rescue
false
end
private
def fetch_members(level = nil)
project_members = project.users_projects
group_members = group ? group.users_groups : []
if level
project_members = project_members.send(level)
group_members = group_members.send(level) if group
end
(project_members + group_members).map(&:user).uniq
end
def group
project.group
end
end

View file

@ -71,7 +71,9 @@ class User < ActiveRecord::Base
has_many :keys, dependent: :destroy
# Groups
has_many :groups, class_name: "Group", foreign_key: :owner_id
has_many :own_groups, class_name: "Group", foreign_key: :owner_id
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
@ -230,7 +232,7 @@ class User < ActiveRecord::Base
# Groups where user is an owner
def owned_groups
groups
own_groups
end
def owned_teams
@ -239,14 +241,14 @@ class User < ActiveRecord::Base
# Groups user has access to
def authorized_groups
@group_ids ||= (groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
@group_ids ||= (groups.pluck(:id) + own_groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
Group.where(id: @group_ids)
end
# Projects user has access to
def authorized_projects
@project_ids ||= (owned_projects.pluck(:id) + projects.pluck(:id)).uniq
@project_ids ||= (owned_projects.pluck(:id) + groups.map(&:projects).flatten.map(&:id) + projects.pluck(:id)).uniq
Project.where(id: @project_ids)
end

42
app/models/users_group.rb Normal file
View file

@ -0,0 +1,42 @@
class UsersGroup < ActiveRecord::Base
GUEST = 10
REPORTER = 20
DEVELOPER = 30
MASTER = 40
OWNER = 50
def self.group_access_roles
{
"Guest" => GUEST,
"Reporter" => REPORTER,
"Developer" => DEVELOPER,
"Master" => MASTER,
"Owner" => OWNER
}
end
attr_accessible :group_access, :user_id
belongs_to :user
belongs_to :group
scope :guests, -> { where(group_access: GUEST) }
scope :reporters, -> { where(group_access: REPORTER) }
scope :developers, -> { where(group_access: DEVELOPER) }
scope :masters, -> { where(group_access: MASTER) }
scope :owners, -> { where(group_access: OWNER) }
scope :with_group, ->(group) { where(group_id: group.id) }
scope :with_user, ->(user) { where(user_id: user.id) }
validates :group_access, inclusion: { in: UsersGroup.group_access_roles.values }, presence: true
validates :user_id, presence: true
validates :group_id, presence: true
validates :user_id, uniqueness: { scope: [:group_id], message: "already exists in group" }
delegate :name, :username, :email, to: :user, prefix: true
def human_access
UsersGroup.group_access_roles.key(self.group_access)
end
end

View file

@ -129,9 +129,7 @@ class UsersProject < ActiveRecord::Base
Project.access_options.key(self.project_access)
end
def repo_access_human
self.class.access_roles.invert[self.project_access]
end
alias_method :human_access, :project_access_human
def skip_git?
!!@skip_git

View file

@ -43,7 +43,7 @@ class SystemHooksService
project_id: model.project_id,
user_name: model.user.name,
user_email: model.user.email,
project_access: model.repo_access_human
project_access: model.project_access_human
})
end
end

View file

@ -49,36 +49,6 @@
%strong
= @group.created_at.stamp("March 1, 1999")
.ui-box
%h5.title
Add user to Group projects:
.ui-box-body.form-holder
%p.light
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
%div
= users_select_tag(:user_ids, multiple: true)
%div.prepend-top-10
= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span2"}
%hr
= submit_tag 'Add user to projects in group', class: "btn btn-create"
.ui-box
%h5.title
Users from Group projects
%small
(#{@group.users.count})
%ul.well-list
- @group.users.sort_by(&:name).each do |user|
%li{class: dom_class(user)}
%strong
= link_to user.name, admin_user_path(user)
%span.pull-right.light
= pluralize user.authorized_projects.in_namespace(@group).count, 'project'
.span6
.ui-box
%h5.title
Projects
@ -91,3 +61,34 @@
= link_to project.name_with_namespace, [:admin, project]
%span.pull-right.light
%span.monospace= project.path_with_namespace + ".git"
.span6
.ui-box
%h5.title
Add user(s):
.ui-box-body.form-holder
%p.light
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
= form_tag project_teams_update_admin_group_path(@group), id: "new_team_member", class: "bulk_import", method: :put do
%div
= users_select_tag(:user_ids, multiple: true)
%div.prepend-top-10
= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span2"}
%hr
= submit_tag 'Add users into group', class: "btn btn-create"
.ui-box
%h5.title
Users from #{@group.name} Group
%small
(#{@group.users_groups.count})
%ul.well-list
- @group.users_groups.order('group_access DESC').each do |member|
- user = member.user
%li{class: dom_class(user)}
%strong
= link_to user.name, admin_user_path(user)
%span.pull-right.light
= member.human_access

View file

@ -1,18 +1,18 @@
= form_for @team_member, as: :team_member, url: team_members_group_path(@group) do |f|
= form_for @users_group, url: group_users_groups_path(@group) do |f|
%fieldset
%legend= "New Team member(s) for projects in #{@group.name}"
%legend= "New Group member(s) for #{@group.name}"
%h6 1. Choose people you want in the team
%h6 1. Choose people you want in the group
.clearfix
= f.label :user_ids, "People"
.input= users_select_tag(:user_ids, multiple: true)
.input= users_select_tag(:user_ids, multiple: true, class: 'input-large')
%h6 2. Set access level for them
.clearfix
= f.label :project_access, "Project Access"
.input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
= f.label :group_access, "Group Access"
.input= select_tag :group_access, options_for_select(UsersGroup.group_access_roles, @users_group.group_access), class: "project-access-select chosen"
.form-actions
= hidden_field_tag :redirect_to, people_group_path(@group)
= f.submit 'Add', class: "btn btn-save"
= f.submit 'Add users into group', class: "btn btn-create"

View file

@ -1,18 +0,0 @@
= form_for @team_member, as: :team_member, url: project_team_members_path(@project, @team_member) do |f|
%fieldset
%legend= "New Team member(s) for #{@project.name}"
%h6 1. Choose people you want in the team
.clearfix
= f.label :user_ids, "People"
.input= users_select_tag(:user_ids, multiple: true)
%h6 2. Set access level for them
.clearfix
= f.label :project_access, "Project Access"
.input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
.form-actions
= hidden_field_tag :redirect_to, people_group_path(@group, project_id: @project.id)
= f.submit 'Add', class: "btn btn-save"

View file

@ -1,16 +0,0 @@
= form_tag people_group_path(@group), method: 'get' do
%fieldset
%legend Projects:
%ul.nav.nav-pills.nav-stacked
- @projects.each do |project|
%li{class: ("active" if params[:project_id] == project.id.to_s)}
= link_to people_group_path(@group, project_id: project.id) do
= project.name_with_namespace
%small.pull-right= project.users.count
- if @projects.blank?
%p.nothing_here_message This group has no projects yet
%fieldset
%hr
= link_to "Reset", people_group_path(@group), class: 'btn pull-right'

View file

@ -1,20 +1,20 @@
- can_manage_group = current_user.can? :manage_group, @group
.row
.span3
= render 'people_filter'
.span9
- if can?(current_user, :manage_group, @group)
= render (@project ? "new_member" : "new_group_member")
.span6
- if can_manage_group
= render "new_group_member"
- else
.light-well
%h4.nothing_here_message
Only group owners can manage group members
.span6
.ui-box
%h5.title
Team
#{@group.name} Group Members
%small
(#{@users.size})
(#{@members.count})
%ul.well-list
- @users.each do |user|
%li
= image_tag gravatar_icon(user.email, 16), class: "avatar s16"
%strong= user.name
%span.cgray= user.email
- if @group.owner == user
%span.btn.btn-small.disabled.pull-right Group Owner
- @members.each do |member|
= render 'users_groups/users_group', member: member, show_controls: can_manage_group
%p.light
Group members get access to all projects in this group

View file

@ -21,7 +21,7 @@
Assign to
.input
.pull-left
= f.select(:assignee_id, @project.users.alphabetically.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
= f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
.pull-right
&nbsp;
= link_to 'Assign to me', '#', class: 'btn btn-small assign-to-me-link'

View file

@ -7,7 +7,7 @@
%span.update_issues_text Update selected issues with &nbsp;
.left
= select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status")
= select_tag('update[assignee_id]', options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee")
= select_tag('update[assignee_id]', options_from_collection_for_select(@project.team.members, "id", "name", params[:assignee_id]), prompt: "Assignee")
= select_tag('update[milestone_id]', options_from_collection_for_select(issues_active_milestones, "id", "title", params[:milestone_id]), prompt: "Milestone")
= hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :status, params[:status]
@ -50,7 +50,7 @@
Any
= link_to project_issues_with_filter_path(@project, assignee_id: 0) do
Unassigned
- @project.users.sort_by(&:name).each do |user|
- @project.team.members.sort_by(&:name).each do |user|
%li
= link_to project_issues_with_filter_path(@project, assignee_id: user.id) do
= image_tag gravatar_icon(user.email), class: "avatar s16"

View file

@ -6,7 +6,7 @@
= nav_link(controller: [:team_members, :teams]) do
= link_to project_team_index_path(@project), class: "team-tab tab" do
%i.icon-group
Project Members
Members
= nav_link(controller: :deploy_keys) do
= link_to project_deploy_keys_path(@project) do
%span

View file

@ -0,0 +1,10 @@
.ui-box
%h5.title
%strong #{@group.name} Group
members (#{@group.users_groups.count})
.pull-right
= link_to people_group_path(@group), class: 'btn btn-small' do
%i.icon-edit
%ul.well-list
- @group.users_groups.order('group_access DESC').each do |member|
= render 'users_groups/users_group', member: member, show_controls: false

View file

@ -1,10 +1,9 @@
- can_admin_project = (can? current_user, :admin_project, @project)
- team.each do |access, members|
- role = Project.access_options.key(access).pluralize
.ui-box{class: role.downcase}
.team-table
- can_admin_project = (can? current_user, :admin_project, @project)
.ui-box
%h5.title
= role
%span.light (#{members.size})
%strong #{@project.name} Project
members (#{members.count})
%ul.well-list
- members.sort_by(&:user_name).each do |team_member|
- members.each do |team_member|
= render 'team_members/team_member', member: team_member, current_user_can_admin_project: can_admin_project

View file

@ -1,27 +1,17 @@
- user = member.user
- allow_admin = current_user_can_admin_project
%li{id: dom_id(user), class: "team_member_row user_#{user.id}"}
.row
.span4
= link_to user, title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 32), class: "avatar s32"
%strong= truncate(user.name, lenght: 40)
%br
%small.cgray= user.username
.span4.pull-right
.pull-right
- if allow_admin
.left
.pull-left
= form_for(member, as: :team_member, url: project_team_member_path(@project, member.user)) do |f|
= f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2 trigger-submit"
.pull-right
- if current_user == user
%span.label.label-success This is you!
- if @project.namespace_owner == user
%span.label.label-info Owner
- elsif user.blocked?
%span.label.label-error Blocked
- elsif allow_admin
&nbsp;
= link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
%i.icon-minus.icon-white
= image_tag gravatar_icon(user.email, 32), class: "avatar s32"
%p
%strong= user.name
%span.cgray= user.username

View file

@ -1,10 +1,6 @@
= render "projects/settings_nav"
%h3.page_title
Project Members
(#{@project.users.count})
%small
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
Users with access to this project
- if can? current_user, :admin_team_member, @project
%span.pull-right
@ -15,42 +11,25 @@
= link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do
New Team Member
%hr
%p.light
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
.clearfix
.row
.span3
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if !params[:type])}
= link_to project_team_index_path(type: nil) do
All
%li{class: ("active" if params[:type] == 'masters')}
= link_to project_team_index_path(type: 'masters') do
Masters
%span.pull-right= @project.users_projects.masters.count
%li{class: ("active" if params[:type] == 'developers')}
= link_to project_team_index_path(type: 'developers') do
Developers
%span.pull-right= @project.users_projects.developers.count
%li{class: ("active" if params[:type] == 'reporters')}
= link_to project_team_index_path(type: 'reporters') do
Reporters
%span.pull-right= @project.users_projects.reporters.count
%li{class: ("active" if params[:type] == 'guests')}
= link_to project_team_index_path(type: 'guests') do
Guests
%span.pull-right= @project.users_projects.guests.count
- if @assigned_teams.present?
- if @group
.row
.span6
= render "team_members/group_members"
.span6
= render "team_members/team", members: @users_projects
- else
= render "team_members/team", members: @users_projects
- if @assigned_teams.present?
%h5
Assigned teams
(#{@project.user_teams.count})
%div
= render "team_members/assigned_teams", assigned_teams: @assigned_teams
.span9
%div.team-table
= render "team_members/team", team: @team

View file

@ -0,0 +1,16 @@
- user = member.user
- return unless user
%li{class: dom_class(member)}
= image_tag gravatar_icon(user.email, 16), class: "avatar s16"
%strong= user.name
%span.cgray= user.username
%span.pull-right
- if @group.owners.include?(user)
%span.label.label-info Group Owner
- else
= member.human_access
- if show_controls && user != current_user
= link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.icon-minus.icon-white

View file

@ -149,10 +149,10 @@ Gitlab::Application.routes.draw do
member do
get :issues
get :merge_requests
get :search
get :people
post :team_members
end
resources :users_groups, only: [:create, :update, :destroy]
end
#

View file

@ -0,0 +1,11 @@
class CreateUsersGroups < ActiveRecord::Migration
def change
create_table :users_groups do |t|
t.integer :group_access, null: false
t.integer :group_id, null: false
t.integer :user_id, null: false
t.timestamps
end
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130614132337) do
ActiveRecord::Schema.define(:version => 20130617095603) do
create_table "deploy_keys_projects", :force => true do |t|
t.integer "deploy_key_id", :null => false
@ -53,8 +53,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.integer "assignee_id"
t.integer "author_id"
t.integer "project_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "position", :default => 0
t.string "branch_name"
t.text "description"
@ -71,8 +71,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
create_table "keys", :force => true do |t|
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.text "key"
t.string "title"
t.string "identifier"
@ -89,8 +89,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.integer "author_id"
t.integer "assignee_id"
t.string "title"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.text "st_commits", :limit => 2147483647
t.text "st_diffs", :limit => 2147483647
t.integer "milestone_id"
@ -139,8 +139,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.text "note"
t.string "noteable_type"
t.integer "author_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
t.string "attachment"
t.string "line_code"
@ -158,8 +158,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.string "name"
t.string "path"
t.text "description"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "creator_id"
t.string "default_branch"
t.boolean "issues_enabled", :default => true, :null => false
@ -206,8 +206,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.text "content"
t.integer "author_id", :null => false
t.integer "project_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.string "file_name"
t.datetime "expires_at"
t.boolean "private", :default => true, :null => false
@ -228,9 +228,6 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.datetime "created_at"
end
add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
create_table "tags", :force => true do |t|
t.string "name"
end
@ -263,7 +260,7 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
@ -272,8 +269,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.boolean "admin", :default => false, :null => false
t.integer "projects_limit", :default => 10
@ -299,16 +296,23 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
add_index "users", ["admin"], :name => "index_users_on_admin"
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true
add_index "users", ["name"], :name => "index_users_on_name"
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
add_index "users", ["username"], :name => "index_users_on_username"
create_table "users_groups", :force => true do |t|
t.integer "group_access", :null => false
t.integer "group_id", :null => false
t.integer "user_id", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users_projects", :force => true do |t|
t.integer "user_id", :null => false
t.integer "project_id", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_access", :default => 0, :null => false
t.integer "notification_level", :default => 3, :null => false
end
@ -320,8 +324,8 @@ ActiveRecord::Schema.define(:version => 20130614132337) do
create_table "web_hooks", :force => true do |t|
t.string "url"
t.integer "project_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.string "type", :default => "ProjectHook"
t.integer "service_id"
end

View file

@ -45,7 +45,7 @@ class AdminGroups < Spinach::FeatureSteps
within "#new_team_member" do
select "Reporter", from: "project_access"
end
click_button "Add user to projects in group"
click_button "Add users into group"
end
Then 'I should see "John" in team list in every project as "Reporter"' do

View file

@ -39,11 +39,11 @@ class Groups < Spinach::FeatureSteps
And 'I select user "John" from list with role "Reporter"' do
user = User.find_by_name("John")
within "#new_team_member" do
within ".new_users_group" do
select2(user.id, from: "#user_ids", multiple: true)
select "Reporter", from: "project_access"
select "Reporter", from: "group_access"
end
click_button "Add"
click_button "Add users into group"
end
Then 'I should see user "John" in team list' do

View file

@ -45,7 +45,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Home
Given 'I click the "Team" tab' do
click_link('Project Members')
click_link('Members')
end
Given 'I click the "Attachments" tab' do
@ -73,7 +73,7 @@ class ProjectActiveTab < Spinach::FeatureSteps
end
Then 'the active sub tab should be Team' do
ensure_active_sub_tab('Project Members')
ensure_active_sub_tab('Members')
end
Then 'the active sub tab should be Attachments' do

View file

@ -30,14 +30,20 @@ class ProjectTeamManagement < Spinach::FeatureSteps
end
Then 'I should see "Mike" in team list as "Reporter"' do
within '.reporters' do
user = User.find_by_name("Mike")
within "#user_#{user.id}" do
page.should have_content('Mike')
page.find('#team_member_project_access').value.should == access_value(:reporter)
end
end
Given 'I should see "Sam" in team list as "Developer"' do
within '.developers' do
user = User.find_by_name("Sam")
within "#user_#{user.id}" do
page.should have_content('Sam')
page.find('#team_member_project_access').value.should == access_value(:developer)
end
end
@ -49,8 +55,10 @@ class ProjectTeamManagement < Spinach::FeatureSteps
end
And 'I should see "Sam" in team list as "Reporter"' do
within '.reporters' do
user = User.find_by_name("Sam")
within ".user_#{user.id}" do
page.should have_content('Sam')
page.find('#team_member_project_access').value.should == access_value(:reporter)
end
end
@ -103,4 +111,10 @@ class ProjectTeamManagement < Spinach::FeatureSteps
click_link('Remove user from team')
end
end
private
def access_value(key)
UsersProject.roles_hash[key].to_s
end
end

View file

@ -0,0 +1,7 @@
FactoryGirl.define do
factory :users_group do
group_access { UsersGroup::OWNER }
group
user
end
end

View file

@ -0,0 +1,27 @@
require 'spec_helper'
describe UsersGroup do
describe "Associations" do
it { should belong_to(:group) }
it { should belong_to(:user) }
end
describe "Mass assignment" do
it { should_not allow_mass_assignment_of(:group_id) }
end
describe "Validation" do
let!(:users_group) { create(:users_group) }
it { should validate_presence_of(:user_id) }
it { should validate_uniqueness_of(:user_id).scoped_to(:group_id).with_message(/already exists/) }
it { should validate_presence_of(:group_id) }
it { should ensure_inclusion_of(:group_access).in_array(UsersGroup.group_access_roles.values) }
end
describe "Delegate methods" do
it { should respond_to(:user_name) }
it { should respond_to(:user_email) }
end
end