commit
d7b5284c66
@ -0,0 +1,108 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
module UserInvitation |
||||||
|
EVENT_NAME = 'user_invited' |
||||||
|
|
||||||
|
module_function |
||||||
|
|
||||||
|
## |
||||||
|
# Creates an invited user with the given email address. |
||||||
|
# If no first and last is given it will default to 'OpenProject User' |
||||||
|
# for the first name and 'To-be' for the last name. |
||||||
|
# The default login is the email address. |
||||||
|
# |
||||||
|
# @param email E-Mail address the invitation is sent to. |
||||||
|
# @param login User's login (optional) |
||||||
|
# @param first_name The user's first name (optional) |
||||||
|
# @param last_name The user's last name (optional) |
||||||
|
# |
||||||
|
# @yield [user] Allows modifying the created user before saving it. |
||||||
|
# |
||||||
|
# @return The invited user. If the invitation failed, calling `#registered?` |
||||||
|
# on the returned user will yield `false`. Check for validation errors |
||||||
|
# in that case. |
||||||
|
def invite_new_user(email:, login: nil, first_name: nil, last_name: nil) |
||||||
|
user = User.new login: login || email, |
||||||
|
mail: email, |
||||||
|
firstname: first_name || email, |
||||||
|
lastname: last_name || '(invited)' |
||||||
|
|
||||||
|
yield user if block_given? |
||||||
|
|
||||||
|
invite_user! user |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Invites the given user. An email will be sent to their email address |
||||||
|
# containing the token necessary for the user to register. |
||||||
|
# |
||||||
|
# Validates and saves the given user. The invitation will fail if the user is invalid. |
||||||
|
# |
||||||
|
# @return The invited user or nil if the invitation failed. |
||||||
|
def invite_user!(user) |
||||||
|
user, token = user_invitation user |
||||||
|
|
||||||
|
if token |
||||||
|
OpenProject::Notifications.send(EVENT_NAME, token) |
||||||
|
|
||||||
|
user |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Creates an invited user with the given email address. |
||||||
|
# If no first and last is given it will default to 'OpenProject User' |
||||||
|
# for the first name and 'To-be' for the last name. |
||||||
|
# The default login is the email address. |
||||||
|
# |
||||||
|
# @return Returns the user and the invitation token required to register. |
||||||
|
def user_invitation(user) |
||||||
|
User.transaction do |
||||||
|
if user.valid? |
||||||
|
token = invitation_token user |
||||||
|
token.save! |
||||||
|
|
||||||
|
user.invite |
||||||
|
user.save! |
||||||
|
|
||||||
|
return [user, token] |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
[user, nil] |
||||||
|
end |
||||||
|
|
||||||
|
def token_action |
||||||
|
'invite' |
||||||
|
end |
||||||
|
|
||||||
|
def invitation_token(user) |
||||||
|
Token.find_or_initialize_by user: user, action: token_action |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,109 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'uri' |
||||||
|
|
||||||
|
class InvitationsController < ApplicationController |
||||||
|
|
||||||
|
skip_before_filter :check_if_login_required, only: [:claim] |
||||||
|
|
||||||
|
def index |
||||||
|
|
||||||
|
end |
||||||
|
|
||||||
|
def create |
||||||
|
email = params.require(:email) |
||||||
|
user = User.create mail: email, login: email, firstname: email, lastname: email |
||||||
|
token = invite_user user |
||||||
|
|
||||||
|
if user.errors.empty? |
||||||
|
first, last = email.split("@") |
||||||
|
user.firstname = first |
||||||
|
user.lastname = "@#{last}" |
||||||
|
user.invite |
||||||
|
|
||||||
|
user.save! |
||||||
|
token.save! |
||||||
|
|
||||||
|
puts |
||||||
|
puts "CREATED NEW TOKEN: #{token.value}" |
||||||
|
puts |
||||||
|
|
||||||
|
redirect_to action: :show, id: user.id |
||||||
|
else |
||||||
|
flash.now[:error] = user.errors.full_messages.first |
||||||
|
|
||||||
|
render 'index', locals: { email: email } |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def show |
||||||
|
user = User.find params.require(:id) |
||||||
|
token = Token.find_by action: token_action, user: user |
||||||
|
|
||||||
|
render 'show', locals: { token: token.value, email: user.mail } |
||||||
|
end |
||||||
|
|
||||||
|
def claim |
||||||
|
token = Token.find_by action: token_action, value: params.require(:id) |
||||||
|
|
||||||
|
if current_user.logged? |
||||||
|
flash[:warning] = 'You are already registered, mate.' |
||||||
|
|
||||||
|
redirect_to invitation_path id: token.user_id |
||||||
|
elsif token.expired? |
||||||
|
flash[:error] = 'The invitation has expired.' |
||||||
|
token.destroy |
||||||
|
|
||||||
|
redirect_to signin_path |
||||||
|
else |
||||||
|
session[:invitation_token] = token.value |
||||||
|
flash[:info] = 'Create a new account or register now, pl0x!' |
||||||
|
|
||||||
|
redirect_to signin_path |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
module Functions |
||||||
|
def token_action |
||||||
|
'invitation' |
||||||
|
end |
||||||
|
|
||||||
|
def invite_user(user) |
||||||
|
token = invitation_token user |
||||||
|
|
||||||
|
token |
||||||
|
end |
||||||
|
|
||||||
|
def invitation_token(user) |
||||||
|
Token.find_or_initialize_by user: user, action: token_action |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
include Functions |
||||||
|
end |
@ -0,0 +1,39 @@ |
|||||||
|
class DummyAuthSource < AuthSource |
||||||
|
def test_connection |
||||||
|
# the dummy connection is always available |
||||||
|
end |
||||||
|
|
||||||
|
def authenticate(login, password) |
||||||
|
existing_user(login, password) || on_the_fly_user(login) |
||||||
|
end |
||||||
|
|
||||||
|
def auth_method_name |
||||||
|
'DerpLAP' |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def existing_user(login, password) |
||||||
|
registered_login?(login) && password == 'dummy' |
||||||
|
end |
||||||
|
|
||||||
|
def on_the_fly_user(login) |
||||||
|
return nil unless onthefly_register? |
||||||
|
|
||||||
|
{ |
||||||
|
firstname: login.capitalize, |
||||||
|
lastname: 'Dummy', |
||||||
|
mail: 'login@DerpLAP.net', |
||||||
|
auth_source_id: id |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
def registered_login?(login) |
||||||
|
not users.where(login: login).empty? # empty? to use EXISTS query |
||||||
|
end |
||||||
|
|
||||||
|
# Does this auth source backend allow password changes? |
||||||
|
def self.allow_password_changes? |
||||||
|
false |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,4 @@ |
|||||||
|
// reload iframes parent (project members view) |
||||||
|
// to show updated list of members and a flash message |
||||||
|
window.parent.document.location.reload(); |
||||||
|
|
@ -0,0 +1,155 @@ |
|||||||
|
<%#-- copyright |
||||||
|
OpenProject is a project management system. |
||||||
|
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License version 3. |
||||||
|
|
||||||
|
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License |
||||||
|
as published by the Free Software Foundation; either version 2 |
||||||
|
of the License, or (at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program; if not, write to the Free Software |
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
|
||||||
|
See doc/COPYRIGHT.rdoc for more details. |
||||||
|
|
||||||
|
++#%> |
||||||
|
|
||||||
|
<% html_title 'Members' %> |
||||||
|
<%= toolbar title: 'Members' do %> |
||||||
|
<% if authorize_for(:members, :new) %> |
||||||
|
<a href="<%= new_project_member_path %>" id="add-member-button" title="Add Member" class="button -alt-highlight"> |
||||||
|
<i class="button--icon icon-add"></i> |
||||||
|
<span class="button--text"><%= I18n.t(:button_add_member) %></span> |
||||||
|
</a> |
||||||
|
<% end %> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
|
||||||
|
<div> |
||||||
|
<% if @members.any? %> |
||||||
|
<% authorized = authorize_for('members', 'update') %> |
||||||
|
<div class="generic-table--container"> |
||||||
|
<div class="generic-table--results-container"> |
||||||
|
<table interactive-table role="grid" class="generic-table"> |
||||||
|
<colgroup> |
||||||
|
<col highlight-col> |
||||||
|
<col highlight-col> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_colgroup, :project => @project) %> |
||||||
|
<col> |
||||||
|
</colgroup> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th> |
||||||
|
<div class="generic-table--sort-header-outer"> |
||||||
|
<div class="generic-table--sort-header"> |
||||||
|
<span> |
||||||
|
<%= User.model_name.human %> / <%= Group.model_name.human %> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</th> |
||||||
|
<th> |
||||||
|
<div class="generic-table--sort-header-outer"> |
||||||
|
<div class="generic-table--sort-header"> |
||||||
|
<span> |
||||||
|
<%= l(:label_role_plural) %> |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</th> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_header, :project => @project) %> |
||||||
|
<th></th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<% @members.each do |member| %> |
||||||
|
<% next if member.new_record? %> |
||||||
|
<tr id="member-<%= member.id %>" class=" member"> |
||||||
|
<% |
||||||
|
member_type = member.principal.class.name.downcase |
||||||
|
classes = [ |
||||||
|
member_type, |
||||||
|
('icon icon-group' if member_type == 'group'), |
||||||
|
user_status_class(member.principal) |
||||||
|
].compact.join(' ') |
||||||
|
%> |
||||||
|
<td class="<%= classes %>" title="<%= user_status_i18n member.principal %>"> |
||||||
|
<%= link_to_user member.principal %> |
||||||
|
<% if member.user && member.user.invited? %> |
||||||
|
<i title="<%= t('text_user_invited') %>" class="icon icon-mail"></i> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
<td class="roles"> |
||||||
|
<span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> |
||||||
|
<% if authorized %> |
||||||
|
<%= form_for(member, :url => {:controller => '/members', |
||||||
|
:action => 'update', |
||||||
|
:id => member, |
||||||
|
:page => params[:page], |
||||||
|
:per_page => params[:per_page] }, |
||||||
|
:method => :put, |
||||||
|
:html => { :id => "member-#{member.id}-roles-form", |
||||||
|
:class => 'hol', |
||||||
|
:style => 'display:none' }) do |f| %> |
||||||
|
<p><% @roles.each do |role| %> |
||||||
|
<label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), |
||||||
|
:disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label> |
||||||
|
<% end %></p> |
||||||
|
<%= hidden_field_tag 'member[role_ids][]', '' %> |
||||||
|
<p><%= submit_tag l(:button_change), :class => 'button -highlight -small' %> |
||||||
|
<%= link_to_function l(:button_cancel), |
||||||
|
"$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;", |
||||||
|
class: 'button -small' %></p> |
||||||
|
<% end %> |
||||||
|
<%= call_hook(:view_projects_settings_members_table_row, { :project => @project, :member => member}) %> |
||||||
|
<td class="buttons"> |
||||||
|
<% |
||||||
|
delete_class, delete_title = if member.disposable? |
||||||
|
['icon icon-delete', I18n.t(:title_remove_and_delete_user)] |
||||||
|
else |
||||||
|
['icon icon-close', I18n.t(:button_remove)] |
||||||
|
end |
||||||
|
%> |
||||||
|
<%= link_to_function '', "$('member-#{member.id}-roles').hide(); $('member-#{member.id}-roles-form').show(); return false;", :class => 'icon icon-edit', :title => l(:button_edit) %> |
||||||
|
<%= link_to('', {:controller => '/members', :action => 'destroy', :id => member, :page => params[:page]}, |
||||||
|
:method => :delete, |
||||||
|
data: { confirm: ((!User.current.admin? && member.include?(User.current)) ? l(:text_own_membership_delete_confirmation) : nil) }, |
||||||
|
:title => delete_title, :class => delete_class) if member.deletable? %> |
||||||
|
</td> |
||||||
|
<% end %> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<% end %> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
<div class="generic-table--header-background"></div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<%= pagination_links_full @members, @pagination_url_options || {} %> |
||||||
|
<% else %> |
||||||
|
<div class="generic-table--container"> |
||||||
|
<div class="generic-table--no-results-container"> |
||||||
|
<h2 class="generic-table--no-results-title"> |
||||||
|
<i class="icon-info"></i> |
||||||
|
<%= l(:label_nothing_display) %> |
||||||
|
</h2> |
||||||
|
<div class="generic-table--no-results-description"> |
||||||
|
<p class="nodata"><%= l(:label_no_data) %></p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
</div> |
@ -0,0 +1,43 @@ |
|||||||
|
<%#-- copyright |
||||||
|
OpenProject is a project management system. |
||||||
|
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License version 3. |
||||||
|
|
||||||
|
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License |
||||||
|
as published by the Free Software Foundation; either version 2 |
||||||
|
of the License, or (at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program; if not, write to the Free Software |
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
|
||||||
|
See doc/COPYRIGHT.rdoc for more details. |
||||||
|
|
||||||
|
++#%> |
||||||
|
<%= javascript_include_tag "members_form.js" %> |
||||||
|
|
||||||
|
<%= error_messages_for 'member' %> |
||||||
|
|
||||||
|
<div> |
||||||
|
<% if @principals_available.any? %> |
||||||
|
<%= render :partial => "members/member_form", |
||||||
|
:locals => { :project => @project, :roles => @roles } %> |
||||||
|
<% else %> |
||||||
|
<p> |
||||||
|
<%= I18n.t('text_no_roles_defined') %> |
||||||
|
</p> |
||||||
|
<%= link_to I18n.t('button_back'), :back, class: 'button' %> |
||||||
|
<% end %> |
||||||
|
</div> |
@ -1,147 +0,0 @@ |
|||||||
<%#-- copyright |
|
||||||
OpenProject is a project management system. |
|
||||||
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or |
|
||||||
modify it under the terms of the GNU General Public License version 3. |
|
||||||
|
|
||||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or |
|
||||||
modify it under the terms of the GNU General Public License |
|
||||||
as published by the Free Software Foundation; either version 2 |
|
||||||
of the License, or (at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program; if not, write to the Free Software |
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
|
|
||||||
See doc/COPYRIGHT.rdoc for more details. |
|
||||||
|
|
||||||
++#%> |
|
||||||
<%= javascript_include_tag "members_form.js" %> |
|
||||||
|
|
||||||
<%= error_messages_for 'member' %> |
|
||||||
<% roles = Role.find_all_givable |
|
||||||
# Check if there is at least one principal that can be added to the project |
|
||||||
principals_available = @project.possible_members("", 1) |
|
||||||
member_per_page = 20 |
|
||||||
|
|
||||||
@members = @project.member_principals.includes(:roles, :principal, :member_roles) |
|
||||||
.order(User::USER_FORMATS_STRUCTURE[Setting.user_format].map{|attr| attr.to_s}.join(", ")) |
|
||||||
.page(params[:page]) |
|
||||||
.references(:users) |
|
||||||
.per_page(per_page_param) |
|
||||||
%> |
|
||||||
<div> |
|
||||||
<% if roles.any? && principals_available.any? %> |
|
||||||
<%= render :partial => "members/member_form", |
|
||||||
:locals => { :project => @project, |
|
||||||
:members => @members, |
|
||||||
:roles => roles } %> |
|
||||||
|
|
||||||
<% end %> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<% if @members.any? %> |
|
||||||
<% authorized = authorize_for('members', 'update') %> |
|
||||||
<div class="generic-table--container"> |
|
||||||
<div class="generic-table--results-container"> |
|
||||||
<table interactive-table role="grid" class="generic-table"> |
|
||||||
<colgroup> |
|
||||||
<col highlight-col> |
|
||||||
<col highlight-col> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_colgroup, :project => @project) %> |
|
||||||
<col> |
|
||||||
</colgroup> |
|
||||||
<thead> |
|
||||||
<tr> |
|
||||||
<th> |
|
||||||
<div class="generic-table--sort-header-outer"> |
|
||||||
<div class="generic-table--sort-header"> |
|
||||||
<span> |
|
||||||
<%= User.model_name.human %> / <%= Group.model_name.human %> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</th> |
|
||||||
<th> |
|
||||||
<div class="generic-table--sort-header-outer"> |
|
||||||
<div class="generic-table--sort-header"> |
|
||||||
<span> |
|
||||||
<%= l(:label_role_plural) %> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</th> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_header, :project => @project) %> |
|
||||||
<th></th> |
|
||||||
</tr> |
|
||||||
</thead> |
|
||||||
<tbody> |
|
||||||
<% @members.each do |member| %> |
|
||||||
<% next if member.new_record? %> |
|
||||||
<tr id="member-<%= member.id %>" class=" member"> |
|
||||||
<td class="<%= member.principal.class.name.downcase %> <%= 'icon icon-group' if member.principal.class.name.downcase == 'group' %> <%= user_status_class member.principal%>" title="<%= user_status_i18n member.principal%>"><%= link_to_user member.principal %></td> |
|
||||||
<td class="roles"> |
|
||||||
<span id="member-<%= member.id %>-roles"><%=h member.roles.sort.collect(&:to_s).join(', ') %></span> |
|
||||||
<% if authorized %> |
|
||||||
<%= form_for(member, :url => {:controller => '/members', |
|
||||||
:action => 'update', |
|
||||||
:id => member, |
|
||||||
:page => params[:page]}, |
|
||||||
:method => :put, |
|
||||||
:remote => true, |
|
||||||
:html => { :id => "member-#{member.id}-roles-form", |
|
||||||
:class => 'hol', |
|
||||||
:style => 'display:none' }) do |f| %> |
|
||||||
<p><% roles.each do |role| %> |
|
||||||
<label><%= check_box_tag 'member[role_ids][]', role.id, member.roles.include?(role), |
|
||||||
:disabled => member.member_roles.detect {|mr| mr.role_id == role.id && !mr.inherited_from.nil?} %> <%=h role %></label> |
|
||||||
<% end %></p> |
|
||||||
<%= hidden_field_tag 'member[role_ids][]', '' %> |
|
||||||
<p><%= submit_tag l(:button_change), :class => 'button -highlight -small' %> |
|
||||||
<%= link_to_function l(:button_cancel), |
|
||||||
"$('member-#{member.id}-roles').show(); $('member-#{member.id}-roles-form').hide(); return false;", |
|
||||||
class: 'button -small' %></p> |
|
||||||
<% end %> |
|
||||||
<%= call_hook(:view_projects_settings_members_table_row, { :project => @project, :member => member}) %> |
|
||||||
<td class="buttons"> |
|
||||||
<%= link_to_function l(:button_edit), "$('member-#{member.id}-roles').hide(); $('member-#{member.id}-roles-form').show(); return false;", :class => 'icon icon-edit' %> |
|
||||||
<%= link_to(l(:button_delete), {:controller => '/members', :action => 'destroy', :id => member, :page => params[:page]}, |
|
||||||
:method => :delete, |
|
||||||
:remote => true, |
|
||||||
data: { confirm: ((!User.current.admin? && member.include?(User.current)) ? l(:text_own_membership_delete_confirmation) : nil) }, |
|
||||||
:title => l(:button_delete), :class => 'icon icon-delete') if member.deletable? %> |
|
||||||
</td> |
|
||||||
<% end %> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<% end %> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
<div class="generic-table--header-background"></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<%= pagination_links_full @members, params: { tab: 'members' }.merge(@pagination_url_options || {}) %> |
|
||||||
<% else %> |
|
||||||
<div class="generic-table--container"> |
|
||||||
<div class="generic-table--no-results-container"> |
|
||||||
<h2 class="generic-table--no-results-title"> |
|
||||||
<i class="icon-info"></i> |
|
||||||
<%= l(:label_nothing_display) %> |
|
||||||
</h2> |
|
||||||
<div class="generic-table--no-results-description"> |
|
||||||
<p class="nodata"><%= l(:label_no_data) %></p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<% end %> |
|
||||||
</div> |
|
@ -0,0 +1,60 @@ |
|||||||
|
<%#-- copyright |
||||||
|
OpenProject is a project management system. |
||||||
|
Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License version 3. |
||||||
|
|
||||||
|
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or |
||||||
|
modify it under the terms of the GNU General Public License |
||||||
|
as published by the Free Software Foundation; either version 2 |
||||||
|
of the License, or (at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program; if not, write to the Free Software |
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
|
||||||
|
See doc/COPYRIGHT.rdoc for more details. |
||||||
|
|
||||||
|
++#%> |
||||||
|
|
||||||
|
<%= error_messages_for 'user' %> |
||||||
|
|
||||||
|
<%= javascript_include_tag 'admin_users' %> |
||||||
|
|
||||||
|
<!--[form:user]--> |
||||||
|
<section class="form--section"> |
||||||
|
<div class="form--field"><%= f.text_field :mail, required: true, autofocus: true %></div> |
||||||
|
<div class="form--field"><%= f.text_field :firstname, required: true %></div> |
||||||
|
<div class="form--field"><%= f.text_field :lastname, required: true %></div> |
||||||
|
|
||||||
|
<%= render partial: 'customizable/field', |
||||||
|
collection: @user.custom_field_values, |
||||||
|
as: :value, |
||||||
|
locals: { form: f } %> |
||||||
|
|
||||||
|
<% unless @auth_sources.empty? || OpenProject::Configuration.disable_password_login? %> |
||||||
|
<div class="form--field"> |
||||||
|
<% sources = ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }) %> |
||||||
|
<%= f.select :auth_source_id, sources %> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form--field" id="new_user_login" style="display: none;"> |
||||||
|
<%= f.text_field :login, :required => true, :size => 25, :disabled => true %> |
||||||
|
</div> |
||||||
|
<% end %> |
||||||
|
|
||||||
|
<div class="form--field"><%= f.check_box :admin, :disabled => (@user == User.current) %></div> |
||||||
|
<%= call_hook(:view_users_form, :user => @user, :form => f) %> |
||||||
|
</section> |
||||||
|
|
||||||
|
<!--[eoform:user]--> |
@ -0,0 +1,6 @@ |
|||||||
|
## |
||||||
|
# The default behaviour is to send the user a sign-up mail |
||||||
|
# when they were invited. |
||||||
|
OpenProject::Notifications.subscribe UserInvitation::EVENT_NAME do |token| |
||||||
|
UserMailer.user_signed_up(token).deliver |
||||||
|
end |
@ -1,186 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is a project management system. |
|
||||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License version 3. |
|
||||||
# |
|
||||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
# Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License |
|
||||||
# as published by the Free Software Foundation; either version 2 |
|
||||||
# of the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program is distributed in the hope that it will be useful, |
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
# GNU General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
# |
|
||||||
# See doc/COPYRIGHT.rdoc for more details. |
|
||||||
#++ |
|
||||||
|
|
||||||
Feature: Group Memberships |
|
||||||
|
|
||||||
Background: |
|
||||||
Given I am already admin |
|
||||||
|
|
||||||
Given there is a role "Manager" |
|
||||||
And there is a role "Developer" |
|
||||||
|
|
||||||
And there is 1 project with the following: |
|
||||||
| Name | Project1 | |
|
||||||
| Identifier | project1 | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | peter | |
|
||||||
| Firstname | Peter | |
|
||||||
| Lastname | Pan | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | hannibal | |
|
||||||
| Firstname | Hannibal | |
|
||||||
| Lastname | Smith | |
|
||||||
|
|
||||||
And there is a group named "A-Team" with the following members: |
|
||||||
| peter | |
|
||||||
| hannibal | |
|
||||||
|
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a group to a project on the project's page adds the group members as well |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I add the principal "A-Team" as a member with the roles: |
|
||||||
| Manager | |
|
||||||
Then I should be on the "members" tab of the settings page of the project called "Project1" |
|
||||||
And I should see "A-Team" within ".generic-table" |
|
||||||
And I should see "Hannibal Smith" within ".generic-table" |
|
||||||
And I should see "Peter Pan" within ".generic-table" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Group-based memberships and individual memberships are handled separately |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I add the principal "Hannibal Smith" as a member with the roles: |
|
||||||
| Manager | |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Successful creation." within ".flash.notice" |
|
||||||
|
|
||||||
And I add the principal "A-Team" as a member with the roles: |
|
||||||
| Developer | |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Successful creation." within ".flash.notice" |
|
||||||
|
|
||||||
When I delete the "A-Team" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
Then I should see "Hannibal Smith" within ".generic-table" |
|
||||||
And I should not see "A-Team" within ".generic-table" |
|
||||||
And I should not see "Peter Pan" within ".generic-table" |
|
||||||
|
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Removing a group from a project on the project's page removes all group members as well |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I add the principal "A-Team" as a member with the roles: |
|
||||||
| Manager | |
|
||||||
|
|
||||||
Then I should be on the "members" tab of the settings page of the project called "Project1" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
When I delete the "A-Team" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
Then I should see "Nothing to display" |
|
||||||
And I should not see "A-Team" within ".generic-table--container" |
|
||||||
And I should not see "Hannibal Smith" within ".generic-table--container" |
|
||||||
And I should not see "Peter Pan" within ".generic-table--container" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a user to a group adds the user to projects as well |
|
||||||
When I go to the admin page of the group called "A-Team" |
|
||||||
And I click on "tab-users" |
|
||||||
And I delete "hannibal" from the group |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
And I click on "tab-memberships" |
|
||||||
And I select "Project1" from "Projects" |
|
||||||
And I check "Manager" |
|
||||||
And I press "Add" within "#tab-content-memberships" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
And I click on "tab-users" |
|
||||||
And I check "Hannibal Smith" |
|
||||||
And I press "Add" within "#tab-content-users" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
|
|
||||||
Then I should see "A-Team" within ".generic-table" |
|
||||||
And I should see "Peter Pan" within ".generic-table" |
|
||||||
And I should see "Hannibal Smith" within ".generic-table" |
|
||||||
|
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Removing a user from a group removes the user from projects as well |
|
||||||
When I go to the admin page of the group called "A-Team" |
|
||||||
And I click on "tab-memberships" |
|
||||||
And I select "Project1" from "Projects" |
|
||||||
And I check "Manager" |
|
||||||
And I press "Add" within "#tab-content-memberships" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
When I click on "tab-users" |
|
||||||
And I delete "hannibal" from the group |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
|
|
||||||
Then I should see "A-Team" within ".generic-table" |
|
||||||
And I should not see "Hannibal Smith" within ".generic-table" |
|
||||||
And I should see "Peter Pan" within ".generic-table" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a group to project on the group's page adds the group members as well |
|
||||||
When I go to the admin page of the group called "A-Team" |
|
||||||
And I click on "tab-memberships" |
|
||||||
And I select "Project1" from "Projects" |
|
||||||
And I check "Manager" |
|
||||||
And I press "Add" within "#tab-content-memberships" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
Then the project member "A-Team" should have the role "Manager" |
|
||||||
|
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
|
|
||||||
Then I should see "A-Team" within ".generic-table" |
|
||||||
And I should see "Hannibal Smith" within ".generic-table" |
|
||||||
And I should see "Peter Pan" within ".generic-table" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding/Removing a group to/from a project displays success message |
|
||||||
When I go to the admin page of the group called "A-Team" |
|
||||||
And I click on "tab-memberships" |
|
||||||
And I select "Project1" from "Projects" |
|
||||||
And I check "Manager" |
|
||||||
And I press "Add" within "#tab-content-memberships" |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
|
|
||||||
Then I should see "Successful update." within ".notice" |
|
||||||
And I should see "Project1" |
|
||||||
|
|
||||||
When I follow "Delete" within "table.generic-table.memberships" |
|
||||||
|
|
||||||
Then I should see "Successful deletion." within ".notice" |
|
||||||
And I should see "No data to display" |
|
@ -1,99 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is a project management system. |
|
||||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License version 3. |
|
||||||
# |
|
||||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
# Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License |
|
||||||
# as published by the Free Software Foundation; either version 2 |
|
||||||
# of the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program is distributed in the hope that it will be useful, |
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
# GNU General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
# |
|
||||||
# See doc/COPYRIGHT.rdoc for more details. |
|
||||||
#++ |
|
||||||
|
|
||||||
Feature: Group memberships |
|
||||||
Background: |
|
||||||
Given there is 1 project with the following: |
|
||||||
| name | project1 | |
|
||||||
| identifier | project1 | |
|
||||||
And there is 1 user with the following: |
|
||||||
| login | bob | |
|
||||||
| firstname | Bob | |
|
||||||
| Lastname | Bobbit | |
|
||||||
And there is 1 user with the following: |
|
||||||
| login | alice | |
|
||||||
| firstname | Alice | |
|
||||||
| lastname | Wonderland | |
|
||||||
And there is 1 group with the following: |
|
||||||
| name | group1 | |
|
||||||
And there is a role "alpha" |
|
||||||
And there is a role "beta" |
|
||||||
And the role "alpha" may have the following rights: |
|
||||||
| manage_members | |
|
||||||
And the user "bob" is a "alpha" in the project "project1" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a group with members to a project |
|
||||||
Given the group "group1" has the following members: |
|
||||||
| alice | |
|
||||||
And I am already logged in as "bob" |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "group1" as a member with the roles: |
|
||||||
| beta | |
|
||||||
Then I should see the principal "group1" as a member with the roles: |
|
||||||
| beta | |
|
||||||
And I should see the principal "alice" as a member with the roles: |
|
||||||
| beta | |
|
||||||
|
|
||||||
Scenario: Adding members to a group after the group has been added to the project adds the users to the project |
|
||||||
Given the group "group1" is a "beta" in the project "project1" |
|
||||||
And I am already admin |
|
||||||
When I go to the edit page of the group called "group1" |
|
||||||
And I follow "Users" within ".tabs" |
|
||||||
And I add the user "alice" to the group |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
Then I should see the principal "group1" as a member with the roles: |
|
||||||
| beta | |
|
||||||
And I should see the principal "alice" as a member with the roles: |
|
||||||
| beta | |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Removing a group from a project removes its members (users) as well if they have no roles of their own |
|
||||||
Given the group "group1" has the following members: |
|
||||||
| alice | |
|
||||||
And the group "group1" is a "beta" in the project "project1" |
|
||||||
And I am already logged in as "bob" |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I follow the delete link of the project member "group1" |
|
||||||
Then I should not see the principal "group1" as a member |
|
||||||
And I should not see the principal "alice" as a member |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Removing a group from a project leaves a member if he has other roles besides those inherited from the group |
|
||||||
Given the group "group1" has the following members: |
|
||||||
| alice | |
|
||||||
And the user "alice" is a "alpha" in the project "project1" |
|
||||||
And the group "group1" is a "beta" in the project "project1" |
|
||||||
And I am already logged in as "bob" |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I follow the delete link of the project member "group1" |
|
||||||
Then I should not see the principal "group1" as a member |
|
||||||
And I should see the principal "alice" as a member with the roles: |
|
||||||
| alpha | |
|
||||||
|
|
||||||
|
|
@ -1,114 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is a project management system. |
|
||||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License version 3. |
|
||||||
# |
|
||||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
# Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License |
|
||||||
# as published by the Free Software Foundation; either version 2 |
|
||||||
# of the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program is distributed in the hope that it will be useful, |
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
# GNU General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
# |
|
||||||
# See doc/COPYRIGHT.rdoc for more details. |
|
||||||
#++ |
|
||||||
|
|
||||||
Feature: Error Messages |
|
||||||
|
|
||||||
Background: |
|
||||||
Given I am already admin |
|
||||||
|
|
||||||
Given there is a role "Manager" |
|
||||||
|
|
||||||
And there is 1 project with the following: |
|
||||||
| Name | Project1 | |
|
||||||
| Identifier | project1 | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | peter | |
|
||||||
| Firstname | Peter | |
|
||||||
| Lastname | Pan | |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a Principal, non impaired |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I select the principal "Peter Pan" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should see 1 error message |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should not see 2 error messages |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a Role, non impaired |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I select the role "Manager" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should see 1 error message |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should not see 2 error messages |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a Principal, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I select the principal "Peter Pan" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should see 1 error message |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should not see 2 error messages |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding a Role, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I select the role "Manager" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should see 1 error message |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should not see 2 error messages |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Removing old error or success messages when adding members |
|
||||||
Given there is 1 User with: |
|
||||||
| Login | tinkerbell | |
|
||||||
| Firstname | Tinker | |
|
||||||
| Lastname | Bell | |
|
||||||
When I go to the settings page of the project called "Project1" |
|
||||||
And I click on "tab-members" |
|
||||||
And I select the principal "Peter Pan" |
|
||||||
And I select the role "Manager" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then there should be a flash notice message |
|
||||||
And there should not be any error message |
|
||||||
|
|
||||||
Then I select the principal "Tinker Bell" |
|
||||||
And I click on "Add" within "#tab-content-members" |
|
||||||
And I wait for AJAX |
|
||||||
Then I should see 1 error message |
|
||||||
And there should not be a flash notice message |
|
@ -1,154 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is a project management system. |
|
||||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License version 3. |
|
||||||
# |
|
||||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
# Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License |
|
||||||
# as published by the Free Software Foundation; either version 2 |
|
||||||
# of the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program is distributed in the hope that it will be useful, |
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
# GNU General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
# |
|
||||||
# See doc/COPYRIGHT.rdoc for more details. |
|
||||||
#++ |
|
||||||
|
|
||||||
Feature: Membership |
|
||||||
|
|
||||||
Background: |
|
||||||
Given I am already admin |
|
||||||
|
|
||||||
Given there is a role "Manager" |
|
||||||
And there is a role "Developer" |
|
||||||
|
|
||||||
And there is 1 project with the following: |
|
||||||
| Identifier | project1 | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | peter | |
|
||||||
| Firstname | Peter | |
|
||||||
| Lastname | Pan | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | hannibal | |
|
||||||
| Firstname | Hannibal | |
|
||||||
| Lastname | Smith | |
|
||||||
|
|
||||||
And there is 1 User with: |
|
||||||
| Login | crash | |
|
||||||
| Firstname | <script>alert('h4x');</script> | |
|
||||||
| Lastname | <script>alert('h4x');</script> | |
|
||||||
|
|
||||||
And there is a group named "A-Team" with the following members: |
|
||||||
| peter | |
|
||||||
| hannibal | |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding and Removing a Group as Member, non impaired |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "A-Team" as "Manager" |
|
||||||
Then I should be on the members tab of the settings page of the project "project1" |
|
||||||
And I should see "Successful creation." within ".flash.notice" |
|
||||||
And I should see "A-Team" within ".generic-table" |
|
||||||
|
|
||||||
When I delete the "A-Team" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Nothing to display" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding and removing a User as Member, non impaired |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "Hannibal Smith" as "Manager" |
|
||||||
Then I should see "Successful creation." within ".flash.notice" |
|
||||||
And I should see "Hannibal Smith" within ".generic-table" |
|
||||||
|
|
||||||
When I delete the "Hannibal Smith" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Nothing to display" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Entering a Username as Member in firstname, lastname order, non impaired |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I enter the principal name "Hannibal S" |
|
||||||
Then I should see "Hannibal Smith" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Entering a Username as Member in lastname, firstname order, non impaired |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I enter the principal name "Smith, H" |
|
||||||
Then I should see "Hannibal Smith" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Escaping should work properly when entering a name |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I enter the principal name "script" |
|
||||||
Then I should not see an alert dialog |
|
||||||
And I should see "<script>alert('h4x');</script>" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Escaping should work properly when selecting a user |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
When I select the principal "script" |
|
||||||
Then I should not see an alert dialog |
|
||||||
And I should see "<script>alert('h4x');</script>" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding and Removing a Group as Member, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "A-Team" as "Manager" |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
Then I should not see "A-Team" within "#principal_results" |
|
||||||
And I should see "A-Team" within ".generic-table" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: User should not appear in members form if he/she is already a member of the project, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "A-Team" as "Manager" |
|
||||||
Then I should be on the members tab of the settings page of the project "project1" |
|
||||||
And I should see "Successful creation." within ".flash.notice" |
|
||||||
And I should see "A-Team" within ".generic-table" |
|
||||||
|
|
||||||
When I delete the "A-Team" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Nothing to display" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Entering a Username as Member in firstname, lastname order, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
And I enter the principal name "Hannibal S" |
|
||||||
Then I should see "Hannibal Smith" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Entering a Username as Member in lastname, firstname order, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
And I enter the principal name "Smith, H" |
|
||||||
Then I should see "Hannibal Smith" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Adding and removing a User as Member, impaired |
|
||||||
When I am impaired |
|
||||||
And I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "Hannibal Smith" as "Manager" |
|
||||||
Then I should see "Successful creation." within ".flash.notice" |
|
||||||
And I should see "Hannibal Smith" within ".generic-table" |
|
||||||
|
|
||||||
When I delete the "Hannibal Smith" membership |
|
||||||
And I wait for the AJAX requests to finish |
|
||||||
Then I should see "Nothing to display" |
|
@ -1,79 +0,0 @@ |
|||||||
#-- copyright |
|
||||||
# OpenProject is a project management system. |
|
||||||
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License version 3. |
|
||||||
# |
|
||||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
|
||||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
|
||||||
# Copyright (C) 2010-2013 the ChiliProject Team |
|
||||||
# |
|
||||||
# This program is free software; you can redistribute it and/or |
|
||||||
# modify it under the terms of the GNU General Public License |
|
||||||
# as published by the Free Software Foundation; either version 2 |
|
||||||
# of the License, or (at your option) any later version. |
|
||||||
# |
|
||||||
# This program is distributed in the hope that it will be useful, |
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
# GNU General Public License for more details. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with this program; if not, write to the Free Software |
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
||||||
# |
|
||||||
# See doc/COPYRIGHT.rdoc for more details. |
|
||||||
#++ |
|
||||||
|
|
||||||
Feature: Membership |
|
||||||
|
|
||||||
Background: |
|
||||||
Given I am already admin |
|
||||||
|
|
||||||
Given there is a role "Manager" |
|
||||||
And there is a role "Developer" |
|
||||||
And there is 1 project with the following: |
|
||||||
| Identifier | project1 | |
|
||||||
And there is 1 User with: |
|
||||||
| Login | peter | |
|
||||||
| Firstname | Peter | |
|
||||||
| Lastname | Pan | |
|
||||||
And there is 1 user with the following: |
|
||||||
| login | bob | |
|
||||||
| firstname | Bob | |
|
||||||
| Lastname | Bobbit | |
|
||||||
And there is 1 user with the following: |
|
||||||
| login | alice | |
|
||||||
| firstname | Alice | |
|
||||||
| Lastname | Alison | |
|
||||||
And the user "bob" is a "Manager" in the project "project1" |
|
||||||
And the user "alice" is a "Developer" in the project "project1" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Paginating after adding a member |
|
||||||
Given we paginate after 2 items |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I add the principal "peter" as "Manager" |
|
||||||
When I follow "2" within ".pagination" |
|
||||||
Then I should see "Peter Pan" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Paginating after removing a member |
|
||||||
Given we paginate after 1 items |
|
||||||
And the user "peter" is a "Manager" in the project "project1" |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I delete the "Alice Alison" membership |
|
||||||
Then I should see "Bob Bobbit" |
|
||||||
When I follow "2" within ".pagination" |
|
||||||
Then I should see "Peter Pan" |
|
||||||
|
|
||||||
@javascript |
|
||||||
Scenario: Paginating after updating a member |
|
||||||
Given we paginate after 1 items |
|
||||||
When I go to the members tab of the settings page of the project "project1" |
|
||||||
And I click on "Edit" |
|
||||||
And I check "Manager" |
|
||||||
And I click "Change" |
|
||||||
And I follow "2" within ".pagination" |
|
||||||
Then I should see "Bob Bobbit" |
|
@ -0,0 +1,60 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
desc 'Creates a dummy LDAP auth source for logging in any user using the password "dummy".' |
||||||
|
namespace :ldap do |
||||||
|
task create_dummy: :environment do |
||||||
|
source_name = 'DerpLAP' |
||||||
|
otf_reg = ARGV.include?('onthefly_register') |
||||||
|
|
||||||
|
source = DummyAuthSource.create name: source_name, onthefly_register: otf_reg |
||||||
|
|
||||||
|
puts |
||||||
|
if source.valid? |
||||||
|
puts "Created dummy auth source called \"#{source_name}\"" |
||||||
|
puts 'On-the-fly registration support: ' + otf_reg.to_s |
||||||
|
unless otf_reg |
||||||
|
puts "use `rake ldap:create_dummy[onthefly_register]` to enable on-the-fly registration" |
||||||
|
end |
||||||
|
else |
||||||
|
puts "Dummy auth source already exists. It's called \"#{source_name}\"." |
||||||
|
end |
||||||
|
|
||||||
|
puts |
||||||
|
puts 'Note: Dummy auth sources cannot be edited, so clicking on them' |
||||||
|
puts " in the 'LDAP Authentication' view will result in an error. Bummer!" |
||||||
|
end |
||||||
|
|
||||||
|
task delete_dummies: :environment do |
||||||
|
DummyAuthSource.destroy_all |
||||||
|
|
||||||
|
puts |
||||||
|
puts 'Deleted all dummy auth sources. Users who used it are out of luck! :o' |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,96 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'group memberships through groups page', type: :feature do |
||||||
|
let!(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let!(:peter) { FactoryGirl.create :user, firstname: 'Peter', lastname: 'Pan' } |
||||||
|
let!(:hannibal) { FactoryGirl.create :user, firstname: 'Hannibal', lastname: 'Smith' } |
||||||
|
let(:group) { FactoryGirl.create :group, lastname: 'A-Team' } |
||||||
|
|
||||||
|
let!(:manager) { FactoryGirl.create :role, name: 'Manager' } |
||||||
|
let!(:developer) { FactoryGirl.create :role, name: 'Developer' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
let(:group_page) { Pages::Groups.new.group(group.id) } |
||||||
|
|
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
|
||||||
|
group.add_member! peter |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'adding a user to a group adds the user to the project as well', js: true do |
||||||
|
members_page.visit! |
||||||
|
expect(members_page).not_to have_user 'Hannibal Smith' |
||||||
|
|
||||||
|
group_page.visit! |
||||||
|
group_page.add_to_project! 'Project 1', as: 'Manager' |
||||||
|
expect(page).to have_text 'Successful update' |
||||||
|
|
||||||
|
group_page.add_user! 'Hannibal' |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user 'A-Team', roles: ['Manager'] |
||||||
|
expect(members_page).to have_user 'Peter Pan', roles: ['Manager'] |
||||||
|
expect(members_page).to have_user 'Hannibal Smith', roles: ['Manager'] |
||||||
|
end |
||||||
|
|
||||||
|
context 'given a group with members in a project' do |
||||||
|
before do |
||||||
|
group.add_member! hannibal |
||||||
|
project.add_member! group, [manager] |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'removing a user from the group removes them from the project too' do |
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user 'Hannibal Smith' |
||||||
|
|
||||||
|
group_page.visit! |
||||||
|
group_page.remove_user! 'Hannibal Smith' |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user 'A-Team' |
||||||
|
expect(members_page).to have_user 'Peter Pan' |
||||||
|
expect(members_page).not_to have_user 'Hannibal Smith' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'removing the group from a project', js: true do |
||||||
|
group_page.visit! |
||||||
|
group_page.open_projects_tab! |
||||||
|
expect(group_page).to have_project 'Project 1' |
||||||
|
|
||||||
|
group_page.remove_from_project! 'Project 1' |
||||||
|
expect(page).to have_text 'Successful deletion' |
||||||
|
expect(page).to have_text 'No data to display' |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,126 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'group memberships through project members page', type: :feature do |
||||||
|
let(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let(:alice) { FactoryGirl.create :user, firstname: 'Alice', lastname: 'Wonderland' } |
||||||
|
let(:bob) { FactoryGirl.create :user, firstname: 'Bob', lastname: 'Bobbit' } |
||||||
|
let(:group) { FactoryGirl.create :group, lastname: 'group1' } |
||||||
|
|
||||||
|
let!(:alpha) { FactoryGirl.create :role, name: 'alpha', permissions: [:manage_members] } |
||||||
|
let!(:beta) { FactoryGirl.create :role, name: 'beta' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
let(:groups_page) { Pages::Groups.new } |
||||||
|
|
||||||
|
before do |
||||||
|
FactoryGirl.create :member, user: bob, project: project, roles: [alpha] |
||||||
|
end |
||||||
|
|
||||||
|
context 'given a group with members' do |
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return bob |
||||||
|
|
||||||
|
group.add_member! alice |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'adding group1 as a member with the beta role', js: true do |
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! 'group1', as: 'beta' |
||||||
|
|
||||||
|
expect(members_page).to have_added_user 'group1' |
||||||
|
expect(members_page).to have_user('Alice Wonderland', group_membership: true) |
||||||
|
end |
||||||
|
|
||||||
|
context 'which has has been added to a project' do |
||||||
|
before do |
||||||
|
project.add_member! group, [beta] |
||||||
|
end |
||||||
|
|
||||||
|
context 'with the members having no roles of their own' do |
||||||
|
scenario 'removing the group removes its members too' do |
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user('Alice Wonderland') |
||||||
|
|
||||||
|
members_page.remove_user! 'group1' |
||||||
|
expect(page).to have_text('Removed group1 from project') |
||||||
|
|
||||||
|
expect(members_page).not_to have_user('group1') |
||||||
|
expect(members_page).not_to have_user('Alice Wonderland') |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
context 'with the members having roles of their own' do |
||||||
|
before do |
||||||
|
project.members |
||||||
|
.select { |m| m.user_id == alice.id } |
||||||
|
.each { |m| m.add_and_save_role alpha } |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'removing the group leaves the user without their group roles' do |
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user('Alice Wonderland', roles: ['alpha', 'beta']) |
||||||
|
|
||||||
|
members_page.remove_user! 'group1' |
||||||
|
expect(page).to have_text('Removed group1 from project') |
||||||
|
|
||||||
|
expect(members_page).not_to have_user('group1') |
||||||
|
|
||||||
|
expect(members_page).to have_user('Alice Wonderland', roles: ['alpha']) |
||||||
|
expect(members_page).not_to have_roles('Alice Wonderland', ['beta']) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
context 'given an empty group in a project' do |
||||||
|
before do |
||||||
|
alice # create alice |
||||||
|
project.add_member! group, [beta] |
||||||
|
|
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'adding members to that group adds them to the project too' do |
||||||
|
members_page.visit! |
||||||
|
|
||||||
|
expect(members_page).not_to have_user('Alice Wonderland') # Alice not in the project yet |
||||||
|
expect(members_page).to have_user('group1') # the group is already there though |
||||||
|
|
||||||
|
groups_page.visit! |
||||||
|
groups_page.add_user_to_group! 'Alice Wonderland', 'group1' |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
expect(members_page).to have_user('Alice Wonderland', roles: ['beta']) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,73 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'group memberships through groups page', type: :feature do |
||||||
|
let!(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let!(:peter) { FactoryGirl.create :user, firstname: 'Peter', lastname: 'Pan' } |
||||||
|
|
||||||
|
let!(:manager) { FactoryGirl.create :role, name: 'Manager' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
|
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
end |
||||||
|
|
||||||
|
shared_examples 'errors when adding members' do |
||||||
|
scenario 'adding a principal without a role, non impaired', js: true do |
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! 'Peter Pan', as: nil |
||||||
|
|
||||||
|
expect(page).to have_text 'choose at least one role' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'adding a role without a principal, non impaired', js: true do |
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! nil, as: 'Manager' |
||||||
|
|
||||||
|
expect(page).to have_text 'choose at least one user or group' |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
context 'with an impaired user' do |
||||||
|
before do |
||||||
|
admin.impaired = true |
||||||
|
admin.save! |
||||||
|
end |
||||||
|
|
||||||
|
it_behaves_like 'errors when adding members' |
||||||
|
end |
||||||
|
|
||||||
|
context 'with an un-impaired user' do |
||||||
|
it_behaves_like 'errors when adding members' |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,127 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'group memberships through groups page', type: :feature, js: true do |
||||||
|
let!(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let!(:peter) { FactoryGirl.create :user, firstname: 'Peter', lastname: 'Pan' } |
||||||
|
let!(:hannibal) { FactoryGirl.create :user, firstname: 'Hannibal', lastname: 'Smith' } |
||||||
|
let!(:crash) { FactoryGirl.create :user, firstname: "<script>alert('h4x');</script>", |
||||||
|
lastname: "<script>alert('h4x');</script>" } |
||||||
|
|
||||||
|
let(:group) { FactoryGirl.create :group, lastname: 'A-Team' } |
||||||
|
|
||||||
|
let!(:manager) { FactoryGirl.create :role, name: 'Manager' } |
||||||
|
let!(:developer) { FactoryGirl.create :role, name: 'Developer' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
|
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
|
||||||
|
group.add_member! peter |
||||||
|
group.add_member! hannibal |
||||||
|
end |
||||||
|
|
||||||
|
shared_examples 'adding and removing principals' do |
||||||
|
scenario 'Adding and Removing a Group as Member' do |
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! 'A-Team', as: 'Manager' |
||||||
|
|
||||||
|
expect(members_page).to have_added_user 'A-Team' |
||||||
|
|
||||||
|
members_page.remove_user! 'A-Team' |
||||||
|
expect(page).to have_text 'Removed A-Team from project' |
||||||
|
expect(page).to have_text 'Nothing to display' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Adding and removing a User as Member' do |
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! 'Hannibal Smith', as: 'Manager' |
||||||
|
|
||||||
|
expect(members_page).to have_added_user 'Hannibal Smith' |
||||||
|
|
||||||
|
members_page.remove_user! 'Hannibal Smith' |
||||||
|
expect(page).to have_text 'Removed Hannibal Smith from project' |
||||||
|
expect(page).to have_text 'Nothing to display' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Entering a Username as Member in firstname, lastname order' do |
||||||
|
members_page.visit! |
||||||
|
members_page.open_new_member! |
||||||
|
|
||||||
|
members_page.enter_principal_search! 'Hannibal S' |
||||||
|
expect(page).to have_text 'Hannibal Smith' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Entering a Username as Member in lastname, firstname order' do |
||||||
|
members_page.visit! |
||||||
|
members_page.open_new_member! |
||||||
|
|
||||||
|
members_page.enter_principal_search! 'Smith, H' |
||||||
|
expect(page).to have_text 'Hannibal Smith' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Escaping should work properly when entering a name' do |
||||||
|
members_page.visit! |
||||||
|
members_page.open_new_member! |
||||||
|
members_page.enter_principal_search! 'script' |
||||||
|
|
||||||
|
expect(members_page).not_to have_alert_dialog |
||||||
|
expect(page).to have_text "<script>alert('h4x');</script>" |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
context 'with an impaired user' do |
||||||
|
before do |
||||||
|
admin.impaired = true |
||||||
|
admin.save! |
||||||
|
end |
||||||
|
|
||||||
|
it_behaves_like 'adding and removing principals' |
||||||
|
end |
||||||
|
|
||||||
|
context 'with an un-impaired user' do |
||||||
|
it_behaves_like 'adding and removing principals' |
||||||
|
|
||||||
|
# The following scenario is only tested with an unimpaired user |
||||||
|
# as it does not make a difference whether or not the user is impaired. |
||||||
|
|
||||||
|
scenario 'Escaping should work properly when selecting a user' do |
||||||
|
members_page.visit! |
||||||
|
members_page.open_new_member! |
||||||
|
members_page.select_principal! 'script' |
||||||
|
|
||||||
|
expect(members_page).not_to have_alert_dialog |
||||||
|
expect(page).to have_text "<script>alert('h4x');</script>" |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,84 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'members pagination', type: :feature, js: true do |
||||||
|
let!(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let!(:peter) { FactoryGirl.create :user, firstname: 'Peter', lastname: 'Pan' } |
||||||
|
let!(:bob) { FactoryGirl.create :user, firstname: 'Bob', lastname: 'Bobbit' } |
||||||
|
let!(:alice) { FactoryGirl.create :user, firstname: 'Alice', lastname: 'Alison' } |
||||||
|
|
||||||
|
let!(:manager) { FactoryGirl.create :role, name: 'Manager' } |
||||||
|
let!(:developer) { FactoryGirl.create :role, name: 'Developer' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
|
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
|
||||||
|
project.add_member! bob, [manager] |
||||||
|
project.add_member! alice, [developer] |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'paginating after adding a member' do |
||||||
|
members_page.set_items_per_page! 2 |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
members_page.add_user! 'Peter Pan', as: 'Manager' |
||||||
|
|
||||||
|
members_page.go_to_page! 2 |
||||||
|
expect(members_page).to have_user 'Peter Pan' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Paginating after removing a member' do |
||||||
|
project.add_member! peter, [manager] |
||||||
|
members_page.set_items_per_page! 1 |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
members_page.remove_user! 'Alice Alison' |
||||||
|
expect(members_page).to have_user 'Bob Bobbit' |
||||||
|
|
||||||
|
members_page.go_to_page! 2 |
||||||
|
expect(members_page).to have_user 'Peter Pan' |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Paginating after updating a member' do |
||||||
|
members_page.set_items_per_page! 1 |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
members_page.edit_user! 'Alice Alison', add_roles: ['Manager'] |
||||||
|
expect(page).to have_text 'Successful update' |
||||||
|
expect(members_page).to have_user 'Alice Alison', roles: ['Developer', 'Manager'] |
||||||
|
|
||||||
|
members_page.go_to_page! 2 |
||||||
|
expect(members_page).to have_user 'Bob Bobbit' |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,71 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
|
||||||
|
feature 'members pagination', type: :feature, js: true do |
||||||
|
let!(:project) { FactoryGirl.create :project, name: 'Project 1', identifier: 'project1' } |
||||||
|
|
||||||
|
let(:admin) { FactoryGirl.create :admin } |
||||||
|
let!(:bob) { FactoryGirl.create :user, firstname: 'Bob', lastname: 'Bobbit' } |
||||||
|
let!(:alice) { FactoryGirl.create :user, firstname: 'Alice', lastname: 'Alison' } |
||||||
|
|
||||||
|
let!(:alpha) { FactoryGirl.create :role, name: 'alpha' } |
||||||
|
let!(:beta) { FactoryGirl.create :role, name: 'beta' } |
||||||
|
|
||||||
|
let(:members_page) { Pages::Members.new project.identifier } |
||||||
|
|
||||||
|
before do |
||||||
|
allow(User).to receive(:current).and_return admin |
||||||
|
|
||||||
|
project.add_member! alice, [beta] |
||||||
|
project.add_member! bob, [alpha] |
||||||
|
|
||||||
|
members_page.visit! |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Adding a Role to Alice' do |
||||||
|
members_page.edit_user! 'Alice Alison', add_roles: ['alpha'] |
||||||
|
|
||||||
|
expect(members_page).to have_user('Alice Alison', roles: ['alpha', 'beta']) |
||||||
|
end |
||||||
|
|
||||||
|
scenario 'Adding a role while taking another role away from Alice' do |
||||||
|
members_page.edit_user! 'Alice Alison', add_roles: ['alpha'], remove_roles: ['beta'] |
||||||
|
|
||||||
|
expect(members_page).to have_user('Alice Alison', roles: 'alpha') |
||||||
|
expect(members_page).not_to have_roles('Alice Alison', ['beta']) |
||||||
|
end |
||||||
|
|
||||||
|
scenario "Removing Bob's last role results in an error" do |
||||||
|
members_page.edit_user! 'Bob Bobbit', remove_roles: ['alpha'] |
||||||
|
|
||||||
|
expect(page).to have_text 'choose at least one role' |
||||||
|
expect(members_page).to have_user('Bob Bobbit', roles: ['alpha']) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,128 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'support/pages/page' |
||||||
|
|
||||||
|
module Pages |
||||||
|
class Groups < Page |
||||||
|
def path |
||||||
|
'/admin/groups' |
||||||
|
end |
||||||
|
|
||||||
|
def edit_group!(group_name) |
||||||
|
click_on group_name |
||||||
|
end |
||||||
|
|
||||||
|
def add_user_to_group!(user_name, group_name) |
||||||
|
visit_page unless current_page? |
||||||
|
|
||||||
|
edit_group! group_name |
||||||
|
group(group_name).add_user! user_name |
||||||
|
end |
||||||
|
|
||||||
|
def delete_group!(name) |
||||||
|
find_group(name).find('a[data-method=delete]').click |
||||||
|
accept_alert_dialog! |
||||||
|
end |
||||||
|
|
||||||
|
def find_group(name) |
||||||
|
find('tr', text: name) |
||||||
|
end |
||||||
|
|
||||||
|
def has_group?(name) |
||||||
|
has_selector? 'tr', text: name |
||||||
|
end |
||||||
|
|
||||||
|
def group(group_name) |
||||||
|
Group.new group_name |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
class Group < Pages::Page |
||||||
|
attr_reader :id |
||||||
|
|
||||||
|
def initialize(id) |
||||||
|
@id = id |
||||||
|
end |
||||||
|
|
||||||
|
def path |
||||||
|
"/admin/groups/#{id}/edit" |
||||||
|
end |
||||||
|
|
||||||
|
def open_users_tab! |
||||||
|
click_on 'tab-users' |
||||||
|
end |
||||||
|
|
||||||
|
def open_projects_tab! |
||||||
|
click_on 'tab-memberships' |
||||||
|
end |
||||||
|
|
||||||
|
def add_to_project!(project_name, as:) |
||||||
|
open_projects_tab! |
||||||
|
select_project! project_name |
||||||
|
Array(as).each { |role| check role } |
||||||
|
click_on 'Add' |
||||||
|
end |
||||||
|
|
||||||
|
def remove_from_project!(name) |
||||||
|
open_projects_tab! |
||||||
|
find_project(name).find('a[data-method=delete]').click |
||||||
|
end |
||||||
|
|
||||||
|
def find_project(name) |
||||||
|
find('tr', text: name) |
||||||
|
end |
||||||
|
|
||||||
|
def has_project?(name) |
||||||
|
has_selector? 'tr', text: name |
||||||
|
end |
||||||
|
|
||||||
|
def select_project!(project_name) |
||||||
|
select(project_name, from: 'membership_project_id') |
||||||
|
end |
||||||
|
|
||||||
|
def add_user!(user_name) |
||||||
|
open_users_tab! |
||||||
|
check user_name |
||||||
|
click_on 'Add' |
||||||
|
end |
||||||
|
|
||||||
|
def remove_user!(user_name) |
||||||
|
open_users_tab! |
||||||
|
find_user(user_name).find('a[data-method=delete]').click |
||||||
|
end |
||||||
|
|
||||||
|
def find_user(user_name) |
||||||
|
find('tr', text: user_name) |
||||||
|
end |
||||||
|
|
||||||
|
def has_user?(user_name) |
||||||
|
has_selector? 'tr', text: user_name |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,143 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'support/pages/page' |
||||||
|
|
||||||
|
module Pages |
||||||
|
class Members < Page |
||||||
|
include Capybara::Select2 |
||||||
|
|
||||||
|
attr_reader :project_identifier |
||||||
|
|
||||||
|
def initialize(project_identifier) |
||||||
|
@project_identifier = project_identifier |
||||||
|
end |
||||||
|
|
||||||
|
def path |
||||||
|
"/projects/#{project_identifier}/members" |
||||||
|
end |
||||||
|
|
||||||
|
def open_new_member! |
||||||
|
click_on 'Add Member' |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Adds the given user to this project. |
||||||
|
# |
||||||
|
# @param user_name [String] The full name of the user. |
||||||
|
# @param as [String] The role as which the user should be added. |
||||||
|
def add_user!(user_name, as:) |
||||||
|
click_on 'Add Member' |
||||||
|
|
||||||
|
select_principal! user_name if user_name |
||||||
|
select_role! as if as |
||||||
|
|
||||||
|
click_on 'Add' |
||||||
|
end |
||||||
|
|
||||||
|
def remove_user!(user_name) |
||||||
|
find_user(user_name).find('a[data-method=delete]').click |
||||||
|
end |
||||||
|
|
||||||
|
def has_added_user?(name) |
||||||
|
has_text? "Added #{name} to the project" and |
||||||
|
has_css? 'tr', text: name |
||||||
|
end |
||||||
|
|
||||||
|
## |
||||||
|
# Checks if the members page lists the given user. |
||||||
|
# |
||||||
|
# @param name [String] The full name of the user. |
||||||
|
# @param roles [Array] Checks if the user has the given role. |
||||||
|
# @param group_membership [Boolean] True if the member is added through a group. |
||||||
|
# Such members cannot be removed separately which |
||||||
|
# is why there must be only an edit and no delete button. |
||||||
|
def has_user?(name, roles: nil, group_membership: nil) |
||||||
|
has_selector?('tr', text: name) && |
||||||
|
(roles.nil? || has_roles?(name, roles)) && |
||||||
|
(group_membership.nil? || group_membership == has_group_membership?(name)) |
||||||
|
end |
||||||
|
|
||||||
|
def find_user(name) |
||||||
|
find('tr', text: name) |
||||||
|
end |
||||||
|
|
||||||
|
def edit_user!(name, add_roles: [], remove_roles: []) |
||||||
|
user = find_user(name) |
||||||
|
user.find('a[title=Edit]').click |
||||||
|
|
||||||
|
Array(add_roles).each { |role| check role } |
||||||
|
Array(remove_roles).each { |role| uncheck role } |
||||||
|
|
||||||
|
click_on 'Change' |
||||||
|
end |
||||||
|
|
||||||
|
def has_group_membership?(user_name) |
||||||
|
user = find_user(user_name) |
||||||
|
|
||||||
|
user.has_selector?('a[title=Edit]') && |
||||||
|
user.has_no_selector?('a[title=Delete]') |
||||||
|
end |
||||||
|
|
||||||
|
def has_roles?(user_name, roles) |
||||||
|
user = find_user(user_name) |
||||||
|
|
||||||
|
Array(roles).all? { |role| user.has_text? role } |
||||||
|
end |
||||||
|
|
||||||
|
def select_principal!(principal_name) |
||||||
|
if !User.current.impaired? |
||||||
|
select2(principal_name, css: '#s2id_member_user_ids') |
||||||
|
else |
||||||
|
find('form .principals').check principal_name |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def select_role!(role_name) |
||||||
|
if !User.current.impaired? |
||||||
|
select2(role_name, css: '#s2id_member_role_ids') |
||||||
|
else |
||||||
|
find('form .roles').check role_name |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def enter_principal_search!(principal_name) |
||||||
|
if !User.current.impaired? |
||||||
|
find('#s2id_member_user_ids') |
||||||
|
.find('.select2-choices .select2-input') |
||||||
|
.set(principal_name) |
||||||
|
else |
||||||
|
fill_in 'principal_search', with: principal_name |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def go_to_page!(number) |
||||||
|
find('.pagination a', text: number.to_s).click |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,80 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is a project management system. |
||||||
|
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF) |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See doc/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
module Pages |
||||||
|
class Page |
||||||
|
include Capybara::DSL |
||||||
|
include RSpec::Matchers |
||||||
|
|
||||||
|
def current_page? |
||||||
|
URI.parse(current_url).path == path |
||||||
|
end |
||||||
|
|
||||||
|
def visit! |
||||||
|
raise 'No path defined' unless path |
||||||
|
|
||||||
|
visit path |
||||||
|
|
||||||
|
self |
||||||
|
end |
||||||
|
|
||||||
|
def accept_alert_dialog! |
||||||
|
alert_dialog.accept if selenium_driver? |
||||||
|
end |
||||||
|
|
||||||
|
def dismiss_alert_dialog! |
||||||
|
alert_dialog.dismiss if selenium_driver? |
||||||
|
end |
||||||
|
|
||||||
|
def alert_dialog |
||||||
|
page.driver.browser.switch_to.alert |
||||||
|
end |
||||||
|
|
||||||
|
def has_alert_dialog? |
||||||
|
if selenium_driver? |
||||||
|
begin |
||||||
|
page.driver.browser.switch_to.alert |
||||||
|
rescue Selenium::WebDriver::Error::NoAlertPresentError |
||||||
|
false |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def selenium_driver? |
||||||
|
Capybara.current_driver.to_s.include?('selenium') |
||||||
|
end |
||||||
|
|
||||||
|
def set_items_per_page!(n) |
||||||
|
Setting.per_page_options = "#{n}, 50, 100" |
||||||
|
end |
||||||
|
|
||||||
|
def path |
||||||
|
nil |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue