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