@@ -0,0 +1,105 | |||||
|
1 | # Redmine - project management software | |||
|
2 | # Copyright (C) 2006-2015 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class EmailAddressesController < ApplicationController | |||
|
19 | before_filter :find_user, :require_admin_or_current_user | |||
|
20 | before_filter :find_email_address, :only => [:update, :destroy] | |||
|
21 | ||||
|
22 | def index | |||
|
23 | @addresses = @user.email_addresses.order(:id).where(:is_default => false).to_a | |||
|
24 | @address ||= EmailAddress.new | |||
|
25 | end | |||
|
26 | ||||
|
27 | def create | |||
|
28 | saved = false | |||
|
29 | if @user.email_addresses.count <= Setting.max_additional_emails.to_i | |||
|
30 | @address = EmailAddress.new(:user => @user, :is_default => false) | |||
|
31 | attrs = params[:email_address] | |||
|
32 | if attrs.is_a?(Hash) | |||
|
33 | @address.address = attrs[:address].to_s | |||
|
34 | end | |||
|
35 | saved = @address.save | |||
|
36 | end | |||
|
37 | ||||
|
38 | respond_to do |format| | |||
|
39 | format.html { | |||
|
40 | if saved | |||
|
41 | redirect_to user_email_addresses_path(@user) | |||
|
42 | else | |||
|
43 | index | |||
|
44 | render :action => 'index' | |||
|
45 | end | |||
|
46 | } | |||
|
47 | format.js { | |||
|
48 | @address = nil if saved | |||
|
49 | index | |||
|
50 | render :action => 'index' | |||
|
51 | } | |||
|
52 | end | |||
|
53 | end | |||
|
54 | ||||
|
55 | def update | |||
|
56 | if params[:notify].present? | |||
|
57 | @address.notify = params[:notify].to_s | |||
|
58 | end | |||
|
59 | @address.save | |||
|
60 | ||||
|
61 | respond_to do |format| | |||
|
62 | format.html { | |||
|
63 | redirect_to user_email_addresses_path(@user) | |||
|
64 | } | |||
|
65 | format.js { | |||
|
66 | @address = nil | |||
|
67 | index | |||
|
68 | render :action => 'index' | |||
|
69 | } | |||
|
70 | end | |||
|
71 | end | |||
|
72 | ||||
|
73 | def destroy | |||
|
74 | @address.destroy | |||
|
75 | ||||
|
76 | respond_to do |format| | |||
|
77 | format.html { | |||
|
78 | redirect_to user_email_addresses_path(@user) | |||
|
79 | } | |||
|
80 | format.js { | |||
|
81 | @address = nil | |||
|
82 | index | |||
|
83 | render :action => 'index' | |||
|
84 | } | |||
|
85 | end | |||
|
86 | end | |||
|
87 | ||||
|
88 | private | |||
|
89 | ||||
|
90 | def find_user | |||
|
91 | @user = User.find(params[:user_id]) | |||
|
92 | end | |||
|
93 | ||||
|
94 | def find_email_address | |||
|
95 | @address = @user.email_addresses.where(:is_default => false).find(params[:id]) | |||
|
96 | rescue ActiveRecord::RecordNotFound | |||
|
97 | render_404 | |||
|
98 | end | |||
|
99 | ||||
|
100 | def require_admin_or_current_user | |||
|
101 | unless @user == User.current | |||
|
102 | require_admin | |||
|
103 | end | |||
|
104 | end | |||
|
105 | end |
@@ -0,0 +1,38 | |||||
|
1 | # encoding: utf-8 | |||
|
2 | # | |||
|
3 | # Redmine - project management software | |||
|
4 | # Copyright (C) 2006-2015 Jean-Philippe Lang | |||
|
5 | # | |||
|
6 | # This program is free software; you can redistribute it and/or | |||
|
7 | # modify it under the terms of the GNU General Public License | |||
|
8 | # as published by the Free Software Foundation; either version 2 | |||
|
9 | # of the License, or (at your option) any later version. | |||
|
10 | # | |||
|
11 | # This program is distributed in the hope that it will be useful, | |||
|
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
14 | # GNU General Public License for more details. | |||
|
15 | # | |||
|
16 | # You should have received a copy of the GNU General Public License | |||
|
17 | # along with this program; if not, write to the Free Software | |||
|
18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
19 | ||||
|
20 | module EmailAddressesHelper | |||
|
21 | ||||
|
22 | # Returns a link to enable or disable notifications for the address | |||
|
23 | def toggle_email_address_notify_link(address) | |||
|
24 | if address.notify? | |||
|
25 | link_to image_tag('email.png'), | |||
|
26 | user_email_address_path(address.user, address, :notify => '0'), | |||
|
27 | :method => :put, | |||
|
28 | :title => l(:label_disable_notifications), | |||
|
29 | :remote => true | |||
|
30 | else | |||
|
31 | link_to image_tag('email_disabled.png'), | |||
|
32 | user_email_address_path(address.user, address, :notify => '1'), | |||
|
33 | :method => :put, | |||
|
34 | :title => l(:label_enable_notifications), | |||
|
35 | :remote => true | |||
|
36 | end | |||
|
37 | end | |||
|
38 | end |
@@ -0,0 +1,54 | |||||
|
1 | # Redmine - project management software | |||
|
2 | # Copyright (C) 2006-2015 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | class EmailAddress < ActiveRecord::Base | |||
|
19 | belongs_to :user | |||
|
20 | attr_protected :id | |||
|
21 | ||||
|
22 | after_update :destroy_tokens | |||
|
23 | after_destroy :destroy_tokens | |||
|
24 | ||||
|
25 | validates_presence_of :address | |||
|
26 | validates_format_of :address, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true | |||
|
27 | validates_length_of :address, :maximum => User::MAIL_LENGTH_LIMIT, :allow_nil => true | |||
|
28 | validates_uniqueness_of :address, :case_sensitive => false, | |||
|
29 | :if => Proc.new {|email| email.address_changed? && email.address.present?} | |||
|
30 | ||||
|
31 | def address=(arg) | |||
|
32 | write_attribute(:address, arg.to_s.strip) | |||
|
33 | end | |||
|
34 | ||||
|
35 | def destroy | |||
|
36 | if is_default? | |||
|
37 | false | |||
|
38 | else | |||
|
39 | super | |||
|
40 | end | |||
|
41 | end | |||
|
42 | ||||
|
43 | private | |||
|
44 | ||||
|
45 | # Delete all outstanding password reset tokens on email change. | |||
|
46 | # This helps to keep the account secure in case the associated email account | |||
|
47 | # was compromised. | |||
|
48 | def destroy_tokens | |||
|
49 | if address_changed? || destroyed? | |||
|
50 | tokens = ['recovery'] | |||
|
51 | Token.where(:user_id => user_id, :action => tokens).delete_all | |||
|
52 | end | |||
|
53 | end | |||
|
54 | end |
@@ -0,0 +1,26 | |||||
|
1 | <% if @addresses.present? %> | |||
|
2 | <table class="list email_addresses"> | |||
|
3 | <% @addresses.each do |address| %> | |||
|
4 | <tr class="<%= cycle("odd", "even") %>"> | |||
|
5 | <td class="email"><%= address.address %></td> | |||
|
6 | <td class="buttons"> | |||
|
7 | <%= toggle_email_address_notify_link(address) %> | |||
|
8 | <%= delete_link user_email_address_path(@user, address), :remote => true %> | |||
|
9 | </td> | |||
|
10 | </tr> | |||
|
11 | <% end %> | |||
|
12 | </table> | |||
|
13 | <% end %> | |||
|
14 | ||||
|
15 | <% unless @addresses.size >= Setting.max_additional_emails.to_i %> | |||
|
16 | <div> | |||
|
17 | <%= form_for @address, :url => user_email_addresses_path(@user), :remote => true do |f| %> | |||
|
18 | <p><%= l(:label_email_address_add) %></p> | |||
|
19 | <%= error_messages_for @address %> | |||
|
20 | <p> | |||
|
21 | <%= f.text_field :address, :size => 40 %> | |||
|
22 | <%= submit_tag l(:button_add) %> | |||
|
23 | </p> | |||
|
24 | <% end %> | |||
|
25 | </div> | |||
|
26 | <% end %> |
@@ -0,0 +1,3 | |||||
|
1 | $('#ajax-modal').html('<%= escape_javascript(render :partial => 'email_addresses/index') %>'); | |||
|
2 | showModal('ajax-modal', '600px', '<%= escape_javascript l(:label_email_address_plural) %>'); | |||
|
3 | $('#email_address_address').focus(); |
@@ -0,0 +1,12 | |||||
|
1 | class CreateEmailAddresses < ActiveRecord::Migration | |||
|
2 | def change | |||
|
3 | create_table :email_addresses do |t| | |||
|
4 | t.column :user_id, :integer, :null => false | |||
|
5 | t.column :address, :string, :null => false | |||
|
6 | t.column :is_default, :boolean, :null => false, :default => false | |||
|
7 | t.column :notify, :boolean, :null => false, :default => true | |||
|
8 | t.column :created_on, :timestamp, :null => false | |||
|
9 | t.column :updated_on, :timestamp, :null => false | |||
|
10 | end | |||
|
11 | end | |||
|
12 | end |
@@ -0,0 +1,14 | |||||
|
1 | class PopulateEmailAddresses < ActiveRecord::Migration | |||
|
2 | def self.up | |||
|
3 | t = EmailAddress.connection.quoted_true | |||
|
4 | n = EmailAddress.connection.quoted_date(Time.now) | |||
|
5 | ||||
|
6 | sql = "INSERT INTO #{EmailAddress.table_name} (user_id, address, is_default, notify, created_on, updated_on)" + | |||
|
7 | " SELECT id, mail, #{t}, #{t}, '#{n}', '#{n}' FROM #{User.table_name} WHERE type = 'User' ORDER BY id" | |||
|
8 | EmailAddress.connection.execute(sql) | |||
|
9 | end | |||
|
10 | ||||
|
11 | def self.down | |||
|
12 | EmailAddress.delete_all | |||
|
13 | end | |||
|
14 | end |
@@ -0,0 +1,9 | |||||
|
1 | class RemoveUsersMail < ActiveRecord::Migration | |||
|
2 | def self.up | |||
|
3 | remove_column :users, :mail | |||
|
4 | end | |||
|
5 | ||||
|
6 | def self.down | |||
|
7 | raise IrreversibleMigration | |||
|
8 | end | |||
|
9 | end |
@@ -0,0 +1,9 | |||||
|
1 | class AddEmailAddressesUserIdIndex < ActiveRecord::Migration | |||
|
2 | def up | |||
|
3 | add_index :email_addresses, :user_id | |||
|
4 | end | |||
|
5 | ||||
|
6 | def down | |||
|
7 | remove_index :email_addresses, :user_id | |||
|
8 | end | |||
|
9 | end |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
@@ -0,0 +1,57 | |||||
|
1 | --- | |||
|
2 | email_address_001: | |||
|
3 | id: 1 | |||
|
4 | user_id: 1 | |||
|
5 | address: admin@somenet.foo | |||
|
6 | is_default: true | |||
|
7 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
8 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
9 | email_address_002: | |||
|
10 | id: 2 | |||
|
11 | user_id: 2 | |||
|
12 | address: jsmith@somenet.foo | |||
|
13 | is_default: true | |||
|
14 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
15 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
16 | email_address_003: | |||
|
17 | id: 3 | |||
|
18 | user_id: 3 | |||
|
19 | address: dlopper@somenet.foo | |||
|
20 | is_default: true | |||
|
21 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
22 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
23 | email_address_004: | |||
|
24 | id: 4 | |||
|
25 | user_id: 4 | |||
|
26 | address: rhill@somenet.foo | |||
|
27 | is_default: true | |||
|
28 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
29 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
30 | email_address_005: | |||
|
31 | id: 5 | |||
|
32 | user_id: 5 | |||
|
33 | address: dlopper2@somenet.foo | |||
|
34 | is_default: true | |||
|
35 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
36 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
37 | email_address_007: | |||
|
38 | id: 7 | |||
|
39 | user_id: 7 | |||
|
40 | address: someone@foo.bar | |||
|
41 | is_default: true | |||
|
42 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
43 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
44 | email_address_008: | |||
|
45 | id: 8 | |||
|
46 | user_id: 8 | |||
|
47 | address: miscuser8@foo.bar | |||
|
48 | is_default: true | |||
|
49 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
50 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
51 | email_address_009: | |||
|
52 | id: 9 | |||
|
53 | user_id: 9 | |||
|
54 | address: miscuser9@foo.bar | |||
|
55 | is_default: true | |||
|
56 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
57 | updated_on: 2006-07-19 19:34:07 +02:00 |
@@ -0,0 +1,144 | |||||
|
1 | # Redmine - project management software | |||
|
2 | # Copyright (C) 2006-2015 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
|
17 | ||||
|
18 | require File.expand_path('../../test_helper', __FILE__) | |||
|
19 | ||||
|
20 | class EmailAddressesControllerTest < ActionController::TestCase | |||
|
21 | fixtures :users, :email_addresses | |||
|
22 | ||||
|
23 | def setup | |||
|
24 | User.current = nil | |||
|
25 | end | |||
|
26 | ||||
|
27 | def test_index_with_no_additional_emails | |||
|
28 | @request.session[:user_id] = 2 | |||
|
29 | get :index, :user_id => 2 | |||
|
30 | assert_response :success | |||
|
31 | assert_template 'index' | |||
|
32 | end | |||
|
33 | ||||
|
34 | def test_index_with_additional_emails | |||
|
35 | @request.session[:user_id] = 2 | |||
|
36 | EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
37 | ||||
|
38 | get :index, :user_id => 2 | |||
|
39 | assert_response :success | |||
|
40 | assert_template 'index' | |||
|
41 | assert_select '.email', :text => 'another@somenet.foo' | |||
|
42 | end | |||
|
43 | ||||
|
44 | def test_index_with_additional_emails_as_js | |||
|
45 | @request.session[:user_id] = 2 | |||
|
46 | EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
47 | ||||
|
48 | xhr :get, :index, :user_id => 2 | |||
|
49 | assert_response :success | |||
|
50 | assert_template 'index' | |||
|
51 | assert_include 'another@somenet.foo', response.body | |||
|
52 | end | |||
|
53 | ||||
|
54 | def test_index_by_admin_should_be_allowed | |||
|
55 | @request.session[:user_id] = 1 | |||
|
56 | get :index, :user_id => 2 | |||
|
57 | assert_response :success | |||
|
58 | assert_template 'index' | |||
|
59 | end | |||
|
60 | ||||
|
61 | def test_index_by_another_user_should_be_denied | |||
|
62 | @request.session[:user_id] = 3 | |||
|
63 | get :index, :user_id => 2 | |||
|
64 | assert_response 403 | |||
|
65 | end | |||
|
66 | ||||
|
67 | def test_create | |||
|
68 | @request.session[:user_id] = 2 | |||
|
69 | assert_difference 'EmailAddress.count' do | |||
|
70 | post :create, :user_id => 2, :email_address => {:address => 'another@somenet.foo'} | |||
|
71 | assert_response 302 | |||
|
72 | assert_redirected_to '/users/2/email_addresses' | |||
|
73 | end | |||
|
74 | email = EmailAddress.order('id DESC').first | |||
|
75 | assert_equal 2, email.user_id | |||
|
76 | assert_equal 'another@somenet.foo', email.address | |||
|
77 | end | |||
|
78 | ||||
|
79 | def test_create_as_js | |||
|
80 | @request.session[:user_id] = 2 | |||
|
81 | assert_difference 'EmailAddress.count' do | |||
|
82 | xhr :post, :create, :user_id => 2, :email_address => {:address => 'another@somenet.foo'} | |||
|
83 | assert_response 200 | |||
|
84 | end | |||
|
85 | end | |||
|
86 | ||||
|
87 | def test_create_with_failure | |||
|
88 | @request.session[:user_id] = 2 | |||
|
89 | assert_no_difference 'EmailAddress.count' do | |||
|
90 | post :create, :user_id => 2, :email_address => {:address => 'invalid'} | |||
|
91 | assert_response 200 | |||
|
92 | end | |||
|
93 | end | |||
|
94 | ||||
|
95 | def test_update | |||
|
96 | @request.session[:user_id] = 2 | |||
|
97 | email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
98 | ||||
|
99 | put :update, :user_id => 2, :id => email.id, :notify => '0' | |||
|
100 | assert_response 302 | |||
|
101 | ||||
|
102 | assert_equal false, email.reload.notify | |||
|
103 | end | |||
|
104 | ||||
|
105 | def test_update_as_js | |||
|
106 | @request.session[:user_id] = 2 | |||
|
107 | email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
108 | ||||
|
109 | xhr :put, :update, :user_id => 2, :id => email.id, :notify => '0' | |||
|
110 | assert_response 200 | |||
|
111 | ||||
|
112 | assert_equal false, email.reload.notify | |||
|
113 | end | |||
|
114 | ||||
|
115 | def test_destroy | |||
|
116 | @request.session[:user_id] = 2 | |||
|
117 | email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
118 | ||||
|
119 | assert_difference 'EmailAddress.count', -1 do | |||
|
120 | delete :destroy, :user_id => 2, :id => email.id | |||
|
121 | assert_response 302 | |||
|
122 | assert_redirected_to '/users/2/email_addresses' | |||
|
123 | end | |||
|
124 | end | |||
|
125 | ||||
|
126 | def test_destroy_as_js | |||
|
127 | @request.session[:user_id] = 2 | |||
|
128 | email = EmailAddress.create!(:user_id => 2, :address => 'another@somenet.foo') | |||
|
129 | ||||
|
130 | assert_difference 'EmailAddress.count', -1 do | |||
|
131 | xhr :delete, :destroy, :user_id => 2, :id => email.id | |||
|
132 | assert_response 200 | |||
|
133 | end | |||
|
134 | end | |||
|
135 | ||||
|
136 | def test_should_not_destroy_default | |||
|
137 | @request.session[:user_id] = 2 | |||
|
138 | ||||
|
139 | assert_no_difference 'EmailAddress.count' do | |||
|
140 | delete :destroy, :user_id => 2, :id => User.find(2).email_address.id | |||
|
141 | assert_response 404 | |||
|
142 | end | |||
|
143 | end | |||
|
144 | end |
@@ -41,7 +41,7 class UsersController < ApplicationController | |||||
41 |
|
41 | |||
42 | @status = params[:status] || 1 |
|
42 | @status = params[:status] || 1 | |
43 |
|
43 | |||
44 | scope = User.logged.status(@status) |
|
44 | scope = User.logged.status(@status).preload(:email_address) | |
45 | scope = scope.like(params[:name]) if params[:name].present? |
|
45 | scope = scope.like(params[:name]) if params[:name].present? | |
46 | scope = scope.in_group(params[:group_id]) if params[:group_id].present? |
|
46 | scope = scope.in_group(params[:group_id]) if params[:group_id].present? | |
47 |
|
47 |
@@ -42,6 +42,12 module UsersHelper | |||||
42 | end |
|
42 | end | |
43 | end |
|
43 | end | |
44 |
|
44 | |||
|
45 | def additional_emails_link(user) | |||
|
46 | if user.email_addresses.count > 1 || Setting.max_additional_emails.to_i > 0 | |||
|
47 | link_to l(:label_email_address_plural), user_email_addresses_path(@user), :class => 'icon icon-email-add', :remote => true | |||
|
48 | end | |||
|
49 | end | |||
|
50 | ||||
45 | def user_settings_tabs |
|
51 | def user_settings_tabs | |
46 | tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general}, |
|
52 | tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general}, | |
47 | {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural} |
|
53 | {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural} |
@@ -60,6 +60,10 class Document < ActiveRecord::Base | |||||
60 | @updated_on |
|
60 | @updated_on | |
61 | end |
|
61 | end | |
62 |
|
62 | |||
|
63 | def notified_users | |||
|
64 | project.notified_users.reject {|user| !visible?(user)} | |||
|
65 | end | |||
|
66 | ||||
63 | private |
|
67 | private | |
64 |
|
68 | |||
65 | def send_notification |
|
69 | def send_notification |
@@ -306,7 +306,7 class MailHandler < ActionMailer::Base | |||||
306 | if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project) |
|
306 | if user.allowed_to?("add_#{obj.class.name.underscore}_watchers".to_sym, obj.project) | |
307 | addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase} |
|
307 | addresses = [email.to, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase} | |
308 | unless addresses.empty? |
|
308 | unless addresses.empty? | |
309 |
User.active. |
|
309 | User.active.having_mail(addresses).each do |w| | |
310 | obj.add_watcher(w) |
|
310 | obj.add_watcher(w) | |
311 | end |
|
311 | end | |
312 | end |
|
312 | end |
@@ -39,8 +39,8 class Mailer < ActionMailer::Base | |||||
39 | @issue = issue |
|
39 | @issue = issue | |
40 | @users = to_users + cc_users |
|
40 | @users = to_users + cc_users | |
41 | @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue) |
|
41 | @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue) | |
42 |
mail :to => to_users |
|
42 | mail :to => to_users, | |
43 |
:cc => cc_users |
|
43 | :cc => cc_users, | |
44 | :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}" |
|
44 | :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}" | |
45 | end |
|
45 | end | |
46 |
|
46 | |||
@@ -71,8 +71,8 class Mailer < ActionMailer::Base | |||||
71 | @journal = journal |
|
71 | @journal = journal | |
72 | @journal_details = journal.visible_details(@users.first) |
|
72 | @journal_details = journal.visible_details(@users.first) | |
73 | @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}") |
|
73 | @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}") | |
74 |
mail :to => to_users |
|
74 | mail :to => to_users, | |
75 |
:cc => cc_users |
|
75 | :cc => cc_users, | |
76 | :subject => s |
|
76 | :subject => s | |
77 | end |
|
77 | end | |
78 |
|
78 | |||
@@ -95,7 +95,7 class Mailer < ActionMailer::Base | |||||
95 | @issues_url = url_for(:controller => 'issues', :action => 'index', |
|
95 | @issues_url = url_for(:controller => 'issues', :action => 'index', | |
96 | :set_filter => 1, :assigned_to_id => user.id, |
|
96 | :set_filter => 1, :assigned_to_id => user.id, | |
97 | :sort => 'due_date:asc') |
|
97 | :sort => 'due_date:asc') | |
98 |
mail :to => user |
|
98 | mail :to => user, | |
99 | :subject => l(:mail_subject_reminder, :count => issues.size, :days => days) |
|
99 | :subject => l(:mail_subject_reminder, :count => issues.size, :days => days) | |
100 | end |
|
100 | end | |
101 |
|
101 | |||
@@ -109,7 +109,7 class Mailer < ActionMailer::Base | |||||
109 | @author = User.current |
|
109 | @author = User.current | |
110 | @document = document |
|
110 | @document = document | |
111 | @document_url = url_for(:controller => 'documents', :action => 'show', :id => document) |
|
111 | @document_url = url_for(:controller => 'documents', :action => 'show', :id => document) | |
112 |
mail :to => document. |
|
112 | mail :to => document.notified_users, | |
113 | :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}" |
|
113 | :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}" | |
114 | end |
|
114 | end | |
115 |
|
115 | |||
@@ -127,15 +127,15 class Mailer < ActionMailer::Base | |||||
127 | when 'Project' |
|
127 | when 'Project' | |
128 | added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container) |
|
128 | added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container) | |
129 | added_to = "#{l(:label_project)}: #{container}" |
|
129 | added_to = "#{l(:label_project)}: #{container}" | |
130 |
recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)} |
|
130 | recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)} | |
131 | when 'Version' |
|
131 | when 'Version' | |
132 | added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project) |
|
132 | added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project) | |
133 | added_to = "#{l(:label_version)}: #{container.name}" |
|
133 | added_to = "#{l(:label_version)}: #{container.name}" | |
134 |
recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)} |
|
134 | recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)} | |
135 | when 'Document' |
|
135 | when 'Document' | |
136 | added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id) |
|
136 | added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id) | |
137 | added_to = "#{l(:label_document)}: #{container.title}" |
|
137 | added_to = "#{l(:label_document)}: #{container.title}" | |
138 |
recipients = container. |
|
138 | recipients = container.notified_users | |
139 | end |
|
139 | end | |
140 | redmine_headers 'Project' => container.project.identifier |
|
140 | redmine_headers 'Project' => container.project.identifier | |
141 | @attachments = attachments |
|
141 | @attachments = attachments | |
@@ -157,8 +157,8 class Mailer < ActionMailer::Base | |||||
157 | references news |
|
157 | references news | |
158 | @news = news |
|
158 | @news = news | |
159 | @news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
|
159 | @news_url = url_for(:controller => 'news', :action => 'show', :id => news) | |
160 |
mail :to => news. |
|
160 | mail :to => news.notified_users, | |
161 |
:cc => news. |
|
161 | :cc => news.notified_watchers_for_added_news, | |
162 | :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
162 | :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}" | |
163 | end |
|
163 | end | |
164 |
|
164 | |||
@@ -176,8 +176,8 class Mailer < ActionMailer::Base | |||||
176 | @news = news |
|
176 | @news = news | |
177 | @comment = comment |
|
177 | @comment = comment | |
178 | @news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
|
178 | @news_url = url_for(:controller => 'news', :action => 'show', :id => news) | |
179 |
mail :to => news. |
|
179 | mail :to => news.notified_users, | |
180 |
:cc => news.watcher |
|
180 | :cc => news.notified_watchers, | |
181 | :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" |
|
181 | :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" | |
182 | end |
|
182 | end | |
183 |
|
183 | |||
@@ -192,8 +192,8 class Mailer < ActionMailer::Base | |||||
192 | @author = message.author |
|
192 | @author = message.author | |
193 | message_id message |
|
193 | message_id message | |
194 | references message.root |
|
194 | references message.root | |
195 |
recipients = message. |
|
195 | recipients = message.notified_users | |
196 |
cc = ((message.root.watcher |
|
196 | cc = ((message.root.notified_watchers + message.board.notified_watchers).uniq - recipients) | |
197 | @message = message |
|
197 | @message = message | |
198 | @message_url = url_for(message.event_url) |
|
198 | @message_url = url_for(message.event_url) | |
199 | mail :to => recipients, |
|
199 | mail :to => recipients, | |
@@ -211,8 +211,8 class Mailer < ActionMailer::Base | |||||
211 | 'Wiki-Page-Id' => wiki_content.page.id |
|
211 | 'Wiki-Page-Id' => wiki_content.page.id | |
212 | @author = wiki_content.author |
|
212 | @author = wiki_content.author | |
213 | message_id wiki_content |
|
213 | message_id wiki_content | |
214 |
recipients = wiki_content. |
|
214 | recipients = wiki_content.notified_users | |
215 |
cc = wiki_content.page.wiki.watcher |
|
215 | cc = wiki_content.page.wiki.notified_watchers - recipients | |
216 | @wiki_content = wiki_content |
|
216 | @wiki_content = wiki_content | |
217 | @wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
|
217 | @wiki_content_url = url_for(:controller => 'wiki', :action => 'show', | |
218 | :project_id => wiki_content.project, |
|
218 | :project_id => wiki_content.project, | |
@@ -232,8 +232,8 class Mailer < ActionMailer::Base | |||||
232 | 'Wiki-Page-Id' => wiki_content.page.id |
|
232 | 'Wiki-Page-Id' => wiki_content.page.id | |
233 | @author = wiki_content.author |
|
233 | @author = wiki_content.author | |
234 | message_id wiki_content |
|
234 | message_id wiki_content | |
235 |
recipients = wiki_content. |
|
235 | recipients = wiki_content.notified_users | |
236 |
cc = wiki_content.page.wiki.watcher |
|
236 | cc = wiki_content.page.wiki.notified_watchers + wiki_content.page.notified_watchers - recipients | |
237 | @wiki_content = wiki_content |
|
237 | @wiki_content = wiki_content | |
238 | @wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
|
238 | @wiki_content_url = url_for(:controller => 'wiki', :action => 'show', | |
239 | :project_id => wiki_content.project, |
|
239 | :project_id => wiki_content.project, | |
@@ -267,7 +267,7 class Mailer < ActionMailer::Base | |||||
267 | # Mailer.account_activation_request(user).deliver => sends an email to all active administrators |
|
267 | # Mailer.account_activation_request(user).deliver => sends an email to all active administrators | |
268 | def account_activation_request(user) |
|
268 | def account_activation_request(user) | |
269 | # Send the email to all active administrators |
|
269 | # Send the email to all active administrators | |
270 |
recipients = User.active.where(:admin => true) |
|
270 | recipients = User.active.where(:admin => true) | |
271 | @user = user |
|
271 | @user = user | |
272 | @url = url_for(:controller => 'users', :action => 'index', |
|
272 | @url = url_for(:controller => 'users', :action => 'index', | |
273 | :status => User::STATUS_REGISTERED, |
|
273 | :status => User::STATUS_REGISTERED, | |
@@ -378,12 +378,20 class Mailer < ActionMailer::Base | |||||
378 | 'From' => Setting.mail_from, |
|
378 | 'From' => Setting.mail_from, | |
379 | 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>" |
|
379 | 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>" | |
380 |
|
380 | |||
|
381 | # Replaces users with their email addresses | |||
|
382 | [:to, :cc, :bcc].each do |key| | |||
|
383 | if headers[key].present? | |||
|
384 | headers[key] = self.class.email_addresses(headers[key]) | |||
|
385 | end | |||
|
386 | end | |||
|
387 | ||||
381 | # Removes the author from the recipients and cc |
|
388 | # Removes the author from the recipients and cc | |
382 | # if the author does not want to receive notifications |
|
389 | # if the author does not want to receive notifications | |
383 | # about what the author do |
|
390 | # about what the author do | |
384 | if @author && @author.logged? && @author.pref.no_self_notified |
|
391 | if @author && @author.logged? && @author.pref.no_self_notified | |
385 | headers[:to].delete(@author.mail) if headers[:to].is_a?(Array) |
|
392 | addresses = @author.mails | |
386 |
headers[: |
|
393 | headers[:to] -= addresses if headers[:to].is_a?(Array) | |
|
394 | headers[:cc] -= addresses if headers[:cc].is_a?(Array) | |||
387 | end |
|
395 | end | |
388 |
|
396 | |||
389 | if @author && @author.logged? |
|
397 | if @author && @author.logged? | |
@@ -447,6 +455,25 class Mailer < ActionMailer::Base | |||||
447 | end |
|
455 | end | |
448 | end |
|
456 | end | |
449 |
|
457 | |||
|
458 | # Returns an array of email addresses to notify by | |||
|
459 | # replacing users in arg with their notified email addresses | |||
|
460 | # | |||
|
461 | # Example: | |||
|
462 | # Mailer.email_addresses(users) | |||
|
463 | # => ["foo@example.net", "bar@example.net"] | |||
|
464 | def self.email_addresses(arg) | |||
|
465 | arr = Array.wrap(arg) | |||
|
466 | mails = arr.reject {|a| a.is_a? Principal} | |||
|
467 | users = arr - mails | |||
|
468 | if users.any? | |||
|
469 | mails += EmailAddress. | |||
|
470 | where(:user_id => users.map(&:id)). | |||
|
471 | where("is_default = ? OR notify = ?", true, true). | |||
|
472 | pluck(:address) | |||
|
473 | end | |||
|
474 | mails | |||
|
475 | end | |||
|
476 | ||||
450 | private |
|
477 | private | |
451 |
|
478 | |||
452 | # Appends a Redmine header field (name is prepended with 'X-Redmine-') |
|
479 | # Appends a Redmine header field (name is prepended with 'X-Redmine-') |
@@ -103,6 +103,10 class Message < ActiveRecord::Base | |||||
103 | usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project))) |
|
103 | usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project))) | |
104 | end |
|
104 | end | |
105 |
|
105 | |||
|
106 | def notified_users | |||
|
107 | project.notified_users.reject {|user| !visible?(user)} | |||
|
108 | end | |||
|
109 | ||||
106 | private |
|
110 | private | |
107 |
|
111 | |||
108 | def add_author_as_watcher |
|
112 | def add_author_as_watcher |
@@ -54,20 +54,29 class News < ActiveRecord::Base | |||||
54 | user.allowed_to?(:comment_news, project) |
|
54 | user.allowed_to?(:comment_news, project) | |
55 | end |
|
55 | end | |
56 |
|
56 | |||
|
57 | def notified_users | |||
|
58 | project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)} | |||
|
59 | end | |||
|
60 | ||||
57 | def recipients |
|
61 | def recipients | |
58 | project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}.map(&:mail) |
|
62 | notified_users.map(&:mail) | |
59 | end |
|
63 | end | |
60 |
|
64 | |||
61 |
# Returns the |
|
65 | # Returns the users that should be cc'd when a new news is added | |
62 |
def |
|
66 | def notified_watchers_for_added_news | |
63 |
|
|
67 | watchers = [] | |
64 | if m = project.enabled_module('news') |
|
68 | if m = project.enabled_module('news') | |
65 |
|
|
69 | watchers = m.notified_watchers | |
66 | unless project.is_public? |
|
70 | unless project.is_public? | |
67 |
|
|
71 | watchers = watchers.select {|user| project.users.include?(user)} | |
68 | end |
|
72 | end | |
69 | end |
|
73 | end | |
70 | cc.map(&:mail) |
|
74 | watchers | |
|
75 | end | |||
|
76 | ||||
|
77 | # Returns the email addresses that should be cc'd when a new news is added | |||
|
78 | def cc_for_added_news | |||
|
79 | notified_watchers_for_added_news.map(&:mail) | |||
71 | end |
|
80 | end | |
72 |
|
81 | |||
73 | # returns latest news for projects visible by user |
|
82 | # returns latest news for projects visible by user |
@@ -68,7 +68,8 class Principal < ActiveRecord::Base | |||||
68 | where({}) |
|
68 | where({}) | |
69 | else |
|
69 | else | |
70 | pattern = "%#{q}%" |
|
70 | pattern = "%#{q}%" | |
71 |
sql = %w(login firstname lastname |
|
71 | sql = %w(login firstname lastname).map {|column| "LOWER(#{table_name}.#{column}) LIKE LOWER(:p)"}.join(" OR ") | |
|
72 | sql << " OR #{table_name}.id IN (SELECT user_id FROM #{EmailAddress.table_name} WHERE LOWER(address) LIKE LOWER(:p))" | |||
72 | params = {:p => pattern} |
|
73 | params = {:p => pattern} | |
73 | if q =~ /^(.+)\s+(.+)$/ |
|
74 | if q =~ /^(.+)\s+(.+)$/ | |
74 | a, b = "#{$1}%", "#{$2}%" |
|
75 | a, b = "#{$1}%", "#{$2}%" | |
@@ -108,6 +109,14 class Principal < ActiveRecord::Base | |||||
108 | to_s |
|
109 | to_s | |
109 | end |
|
110 | end | |
110 |
|
111 | |||
|
112 | def mail=(*args) | |||
|
113 | nil | |||
|
114 | end | |||
|
115 | ||||
|
116 | def mail | |||
|
117 | nil | |||
|
118 | end | |||
|
119 | ||||
111 | def visible?(user=User.current) |
|
120 | def visible?(user=User.current) | |
112 | Principal.visible(user).where(:id => id).first == self |
|
121 | Principal.visible(user).where(:id => id).first == self | |
113 | end |
|
122 | end | |
@@ -145,7 +154,6 class Principal < ActiveRecord::Base | |||||
145 | self.hashed_password ||= '' |
|
154 | self.hashed_password ||= '' | |
146 | self.firstname ||= '' |
|
155 | self.firstname ||= '' | |
147 | self.lastname ||= '' |
|
156 | self.lastname ||= '' | |
148 | self.mail ||= '' |
|
|||
149 | true |
|
157 | true | |
150 | end |
|
158 | end | |
151 | end |
|
159 | end |
@@ -81,6 +81,8 class User < Principal | |||||
81 | has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' |
|
81 | has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' | |
82 | has_one :rss_token, lambda {where "action='feeds'"}, :class_name => 'Token' |
|
82 | has_one :rss_token, lambda {where "action='feeds'"}, :class_name => 'Token' | |
83 | has_one :api_token, lambda {where "action='api'"}, :class_name => 'Token' |
|
83 | has_one :api_token, lambda {where "action='api'"}, :class_name => 'Token' | |
|
84 | has_one :email_address, lambda {where :is_default => true}, :autosave => true | |||
|
85 | has_many :email_addresses, :dependent => :delete_all | |||
84 | belongs_to :auth_source |
|
86 | belongs_to :auth_source | |
85 |
|
87 | |||
86 | scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") } |
|
88 | scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") } | |
@@ -96,15 +98,12 class User < Principal | |||||
96 | LOGIN_LENGTH_LIMIT = 60 |
|
98 | LOGIN_LENGTH_LIMIT = 60 | |
97 | MAIL_LENGTH_LIMIT = 60 |
|
99 | MAIL_LENGTH_LIMIT = 60 | |
98 |
|
100 | |||
99 |
validates_presence_of :login, :firstname, :lastname |
|
101 | validates_presence_of :login, :firstname, :lastname, :if => Proc.new { |user| !user.is_a?(AnonymousUser) } | |
100 | validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, :case_sensitive => false |
|
102 | validates_uniqueness_of :login, :if => Proc.new { |user| user.login_changed? && user.login.present? }, :case_sensitive => false | |
101 | validates_uniqueness_of :mail, :if => Proc.new { |user| user.mail_changed? && user.mail.present? }, :case_sensitive => false |
|
|||
102 | # Login must contain letters, numbers, underscores only |
|
103 | # Login must contain letters, numbers, underscores only | |
103 | validates_format_of :login, :with => /\A[a-z0-9_\-@\.]*\z/i |
|
104 | validates_format_of :login, :with => /\A[a-z0-9_\-@\.]*\z/i | |
104 | validates_length_of :login, :maximum => LOGIN_LENGTH_LIMIT |
|
105 | validates_length_of :login, :maximum => LOGIN_LENGTH_LIMIT | |
105 | validates_length_of :firstname, :lastname, :maximum => 30 |
|
106 | validates_length_of :firstname, :lastname, :maximum => 30 | |
106 | validates_format_of :mail, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, :allow_blank => true |
|
|||
107 | validates_length_of :mail, :maximum => MAIL_LENGTH_LIMIT, :allow_nil => true |
|
|||
108 | validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true |
|
107 | validates_inclusion_of :mail_notification, :in => MAIL_NOTIFICATION_OPTIONS.collect(&:first), :allow_blank => true | |
109 | validate :validate_password_length |
|
108 | validate :validate_password_length | |
110 | validate do |
|
109 | validate do | |
@@ -113,6 +112,7 class User < Principal | |||||
113 | end |
|
112 | end | |
114 | end |
|
113 | end | |
115 |
|
114 | |||
|
115 | before_validation :instantiate_email_address | |||
116 | before_create :set_mail_notification |
|
116 | before_create :set_mail_notification | |
117 | before_save :generate_password_if_needed, :update_hashed_password |
|
117 | before_save :generate_password_if_needed, :update_hashed_password | |
118 | before_destroy :remove_references_before_destroy |
|
118 | before_destroy :remove_references_before_destroy | |
@@ -127,6 +127,14 class User < Principal | |||||
127 | where("#{User.table_name}.id NOT IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id) |
|
127 | where("#{User.table_name}.id NOT IN (SELECT gu.user_id FROM #{table_name_prefix}groups_users#{table_name_suffix} gu WHERE gu.group_id = ?)", group_id) | |
128 | } |
|
128 | } | |
129 | scope :sorted, lambda { order(*User.fields_for_order_statement)} |
|
129 | scope :sorted, lambda { order(*User.fields_for_order_statement)} | |
|
130 | scope :having_mail, lambda {|arg| | |||
|
131 | addresses = Array.wrap(arg).map {|a| a.to_s.downcase} | |||
|
132 | if addresses.any? | |||
|
133 | joins(:email_addresses).where("LOWER(address) IN (?)", addresses).uniq | |||
|
134 | else | |||
|
135 | none | |||
|
136 | end | |||
|
137 | } | |||
130 |
|
138 | |||
131 | def set_mail_notification |
|
139 | def set_mail_notification | |
132 | self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? |
|
140 | self.mail_notification = Setting.default_notification_option if self.mail_notification.blank? | |
@@ -152,8 +160,21 class User < Principal | |||||
152 | base_reload(*args) |
|
160 | base_reload(*args) | |
153 | end |
|
161 | end | |
154 |
|
162 | |||
|
163 | def mail | |||
|
164 | email_address.try(:address) | |||
|
165 | end | |||
|
166 | ||||
155 | def mail=(arg) |
|
167 | def mail=(arg) | |
156 | write_attribute(:mail, arg.to_s.strip) |
|
168 | email = email_address || build_email_address | |
|
169 | email.address = arg | |||
|
170 | end | |||
|
171 | ||||
|
172 | def mail_changed? | |||
|
173 | email_address.try(:address_changed?) | |||
|
174 | end | |||
|
175 | ||||
|
176 | def mails | |||
|
177 | email_addresses.pluck(:address) | |||
157 | end |
|
178 | end | |
158 |
|
179 | |||
159 | def self.find_or_initialize_by_identity_url(url) |
|
180 | def self.find_or_initialize_by_identity_url(url) | |
@@ -421,7 +442,7 class User < Principal | |||||
421 |
|
442 | |||
422 | # Makes find_by_mail case-insensitive |
|
443 | # Makes find_by_mail case-insensitive | |
423 | def self.find_by_mail(mail) |
|
444 | def self.find_by_mail(mail) | |
424 | where("LOWER(mail) = ?", mail.to_s.downcase).first |
|
445 | having_mail(mail).first | |
425 | end |
|
446 | end | |
426 |
|
447 | |||
427 | # Returns true if the default admin account can no longer be used |
|
448 | # Returns true if the default admin account can no longer be used | |
@@ -669,7 +690,7 class User < Principal | |||||
669 | def self.anonymous |
|
690 | def self.anonymous | |
670 | anonymous_user = AnonymousUser.first |
|
691 | anonymous_user = AnonymousUser.first | |
671 | if anonymous_user.nil? |
|
692 | if anonymous_user.nil? | |
672 |
anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', |
|
693 | anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :login => '', :status => 0) | |
673 | raise 'Unable to create the anonymous user.' if anonymous_user.new_record? |
|
694 | raise 'Unable to create the anonymous user.' if anonymous_user.new_record? | |
674 | end |
|
695 | end | |
675 | anonymous_user |
|
696 | anonymous_user | |
@@ -699,6 +720,10 class User < Principal | |||||
699 | end |
|
720 | end | |
700 | end |
|
721 | end | |
701 |
|
722 | |||
|
723 | def instantiate_email_address | |||
|
724 | email_address || build_email_address | |||
|
725 | end | |||
|
726 | ||||
702 | private |
|
727 | private | |
703 |
|
728 | |||
704 | def generate_password_if_needed |
|
729 | def generate_password_if_needed | |
@@ -708,16 +733,13 class User < Principal | |||||
708 | end |
|
733 | end | |
709 | end |
|
734 | end | |
710 |
|
735 | |||
711 |
# Delete all outstanding password reset tokens on password |
|
736 | # Delete all outstanding password reset tokens on password change. | |
712 | # Delete the autologin tokens on password change to prohibit session leakage. |
|
737 | # Delete the autologin tokens on password change to prohibit session leakage. | |
713 | # This helps to keep the account secure in case the associated email account |
|
738 | # This helps to keep the account secure in case the associated email account | |
714 | # was compromised. |
|
739 | # was compromised. | |
715 | def destroy_tokens |
|
740 | def destroy_tokens | |
716 | tokens = [] |
|
741 | if hashed_password_changed? | |
717 |
tokens |
|
742 | tokens = ['recovery', 'autologin'] | |
718 | tokens |= ['recovery'] if mail_changed? |
|
|||
719 |
|
||||
720 | if tokens.any? |
|
|||
721 | Token.where(:user_id => id, :action => tokens).delete_all |
|
743 | Token.where(:user_id => id, :action => tokens).delete_all | |
722 | end |
|
744 | end | |
723 | end |
|
745 | end | |
@@ -779,6 +801,7 class AnonymousUser < User | |||||
779 | def logged?; false end |
|
801 | def logged?; false end | |
780 | def admin; false end |
|
802 | def admin; false end | |
781 | def name(*args); I18n.t(:label_user_anonymous) end |
|
803 | def name(*args); I18n.t(:label_user_anonymous) end | |
|
804 | def mail=(*args); nil end | |||
782 | def mail; nil end |
|
805 | def mail; nil end | |
783 | def time_zone; nil end |
|
806 | def time_zone; nil end | |
784 | def rss_key; nil end |
|
807 | def rss_key; nil end | |
@@ -804,4 +827,9 class AnonymousUser < User | |||||
804 | def destroy |
|
827 | def destroy | |
805 | false |
|
828 | false | |
806 | end |
|
829 | end | |
|
830 | ||||
|
831 | protected | |||
|
832 | ||||
|
833 | def instantiate_email_address | |||
|
834 | end | |||
807 | end |
|
835 | end |
@@ -41,11 +41,13 class WikiContent < ActiveRecord::Base | |||||
41 | page.nil? ? [] : page.attachments |
|
41 | page.nil? ? [] : page.attachments | |
42 | end |
|
42 | end | |
43 |
|
43 | |||
|
44 | def notified_users | |||
|
45 | project.notified_users.reject {|user| !visible?(user)} | |||
|
46 | end | |||
|
47 | ||||
44 | # Returns the mail addresses of users that should be notified |
|
48 | # Returns the mail addresses of users that should be notified | |
45 | def recipients |
|
49 | def recipients | |
46 | notified = project.notified_users |
|
50 | notified_users.collect(&:mail) | |
47 | notified.reject! {|user| !visible?(user)} |
|
|||
48 | notified.collect(&:mail) |
|
|||
49 | end |
|
51 | end | |
50 |
|
52 | |||
51 | # Return true if the content is the current page content |
|
53 | # Return true if the content is the current page content |
@@ -1,4 +1,5 | |||||
1 | <div class="contextual"> |
|
1 | <div class="contextual"> | |
|
2 | <%= additional_emails_link(@user) %> | |||
2 | <%= link_to(l(:button_change_password), {:action => 'password'}, :class => 'icon icon-passwd') if @user.change_password_allowed? %> |
|
3 | <%= link_to(l(:button_change_password), {:action => 'password'}, :class => 'icon icon-passwd') if @user.change_password_allowed? %> | |
3 | <%= call_hook(:view_my_account_contextual, :user => @user)%> |
|
4 | <%= call_hook(:view_my_account_contextual, :user => @user)%> | |
4 | </div> |
|
5 | </div> |
@@ -16,6 +16,8 | |||||
16 |
|
16 | |||
17 | <p><%= setting_check_box :lost_password, :label => :label_password_lost %></p> |
|
17 | <p><%= setting_check_box :lost_password, :label => :label_password_lost %></p> | |
18 |
|
18 | |||
|
19 | <p><%= setting_text_field :max_additional_emails, :size => 6 %></p> | |||
|
20 | ||||
19 | <p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p> |
|
21 | <p><%= setting_check_box :openid, :disabled => !Object.const_defined?(:OpenID) %></p> | |
20 |
|
22 | |||
21 | <p><%= setting_check_box :rest_api_enabled %></p> |
|
23 | <p><%= setting_check_box :rest_api_enabled %></p> |
@@ -1,5 +1,6 | |||||
1 | <div class="contextual"> |
|
1 | <div class="contextual"> | |
2 | <%= link_to l(:label_profile), user_path(@user), :class => 'icon icon-user' %> |
|
2 | <%= link_to l(:label_profile), user_path(@user), :class => 'icon icon-user' %> | |
|
3 | <%= additional_emails_link(@user) %> | |||
3 | <%= change_status_link(@user) %> |
|
4 | <%= change_status_link(@user) %> | |
4 | <%= delete_link user_path(@user) if User.current != @user %> |
|
5 | <%= delete_link user_path(@user) if User.current != @user %> | |
5 | </div> |
|
6 | </div> |
@@ -5,8 +5,7 module ActiveRecord | |||||
5 | include Redmine::I18n |
|
5 | include Redmine::I18n | |
6 | # Translate attribute names for validation errors display |
|
6 | # Translate attribute names for validation errors display | |
7 | def self.human_attribute_name(attr, *args) |
|
7 | def self.human_attribute_name(attr, *args) | |
8 | attr = attr.to_s.sub(/_id$/, '') |
|
8 | attr = attr.to_s.sub(/_id$/, '').sub(/^.+\./, '') | |
9 |
|
||||
10 | l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr]) |
|
9 | l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr]) | |
11 | end |
|
10 | end | |
12 | end |
|
11 | end |
@@ -227,6 +227,7 en: | |||||
227 | field_firstname: First name |
|
227 | field_firstname: First name | |
228 | field_lastname: Last name |
|
228 | field_lastname: Last name | |
229 | field_mail: Email |
|
229 | field_mail: Email | |
|
230 | field_address: Email | |||
230 | field_filename: File |
|
231 | field_filename: File | |
231 | field_filesize: Size |
|
232 | field_filesize: Size | |
232 | field_downloads: Downloads |
|
233 | field_downloads: Downloads | |
@@ -413,6 +414,7 en: | |||||
413 | setting_force_default_language_for_anonymous: Force default language for anonymous users |
|
414 | setting_force_default_language_for_anonymous: Force default language for anonymous users | |
414 | setting_force_default_language_for_loggedin: Force default language for logged-in users |
|
415 | setting_force_default_language_for_loggedin: Force default language for logged-in users | |
415 | setting_link_copied_issue: Link issues on copy |
|
416 | setting_link_copied_issue: Link issues on copy | |
|
417 | setting_max_additional_emails: Maximum number of additional email addresses | |||
416 |
|
418 | |||
417 | permission_add_project: Create project |
|
419 | permission_add_project: Create project | |
418 | permission_add_subprojects: Create subprojects |
|
420 | permission_add_subprojects: Create subprojects | |
@@ -931,6 +933,10 en: | |||||
931 | label_search_attachments_no: Do not search attachments |
|
933 | label_search_attachments_no: Do not search attachments | |
932 | label_search_attachments_only: Search attachments only |
|
934 | label_search_attachments_only: Search attachments only | |
933 | label_search_open_issues_only: Open issues only |
|
935 | label_search_open_issues_only: Open issues only | |
|
936 | label_email_address_plural: Emails | |||
|
937 | label_email_address_add: Add email address | |||
|
938 | label_enable_notifications: Enable notifications | |||
|
939 | label_disable_notifications: Disable notifications | |||
934 |
|
940 | |||
935 | button_login: Login |
|
941 | button_login: Login | |
936 | button_submit: Submit |
|
942 | button_submit: Submit |
@@ -247,6 +247,7 fr: | |||||
247 | field_firstname: PrΓ©nom |
|
247 | field_firstname: PrΓ©nom | |
248 | field_lastname: Nom |
|
248 | field_lastname: Nom | |
249 | field_mail: Email |
|
249 | field_mail: Email | |
|
250 | field_address: Email | |||
250 | field_filename: Fichier |
|
251 | field_filename: Fichier | |
251 | field_filesize: Taille |
|
252 | field_filesize: Taille | |
252 | field_downloads: TΓ©lΓ©chargements |
|
253 | field_downloads: TΓ©lΓ©chargements | |
@@ -433,6 +434,7 fr: | |||||
433 | setting_force_default_language_for_anonymous: Forcer la langue par dΓ©fault pour les utilisateurs anonymes |
|
434 | setting_force_default_language_for_anonymous: Forcer la langue par dΓ©fault pour les utilisateurs anonymes | |
434 | setting_force_default_language_for_loggedin: Forcer la langue par dΓ©fault pour les utilisateurs identifiΓ©s |
|
435 | setting_force_default_language_for_loggedin: Forcer la langue par dΓ©fault pour les utilisateurs identifiΓ©s | |
435 | setting_link_copied_issue: Lier les demandes lors de la copie |
|
436 | setting_link_copied_issue: Lier les demandes lors de la copie | |
|
437 | setting_max_additional_emails: Nombre maximal d'adresses email additionnelles | |||
436 |
|
438 | |||
437 | permission_add_project: CrΓ©er un projet |
|
439 | permission_add_project: CrΓ©er un projet | |
438 | permission_add_subprojects: CrΓ©er des sous-projets |
|
440 | permission_add_subprojects: CrΓ©er des sous-projets | |
@@ -951,6 +953,10 fr: | |||||
951 | label_search_attachments_no: Ne pas rechercher les fichiers |
|
953 | label_search_attachments_no: Ne pas rechercher les fichiers | |
952 | label_search_attachments_only: Rechercher les fichiers uniquement |
|
954 | label_search_attachments_only: Rechercher les fichiers uniquement | |
953 | label_search_open_issues_only: Demandes ouvertes uniquement |
|
955 | label_search_open_issues_only: Demandes ouvertes uniquement | |
|
956 | label_email_address_plural: Emails | |||
|
957 | label_email_address_add: Ajouter une adresse email | |||
|
958 | label_enable_notifications: Activer les notifications | |||
|
959 | label_disable_notifications: DΓ©sactiver les notifications | |||
954 |
|
960 | |||
955 | button_login: Connexion |
|
961 | button_login: Connexion | |
956 | button_submit: Soumettre |
|
962 | button_submit: Soumettre |
@@ -75,6 +75,7 Rails.application.routes.draw do | |||||
75 |
|
75 | |||
76 | resources :users do |
|
76 | resources :users do | |
77 | resources :memberships, :controller => 'principal_memberships' |
|
77 | resources :memberships, :controller => 'principal_memberships' | |
|
78 | resources :email_addresses, :only => [:index, :create, :update, :destroy] | |||
78 | end |
|
79 | end | |
79 |
|
80 | |||
80 | post 'watchers/watch', :to => 'watchers#watch', :as => 'watch' |
|
81 | post 'watchers/watch', :to => 'watchers#watch', :as => 'watch' |
@@ -36,6 +36,10 unsubscribe: | |||||
36 | password_min_length: |
|
36 | password_min_length: | |
37 | format: int |
|
37 | format: int | |
38 | default: 8 |
|
38 | default: 8 | |
|
39 | # Maximum number of additional email addresses per user | |||
|
40 | max_additional_emails: | |||
|
41 | format: int | |||
|
42 | default: 5 | |||
39 | # Maximum lifetime of user sessions in minutes |
|
43 | # Maximum lifetime of user sessions in minutes | |
40 | session_lifetime: |
|
44 | session_lifetime: | |
41 | format: int |
|
45 | format: int |
@@ -378,10 +378,10 function setPredecessorFieldsVisibility() { | |||||
378 | } |
|
378 | } | |
379 | } |
|
379 | } | |
380 |
|
380 | |||
381 | function showModal(id, width) { |
|
381 | function showModal(id, width, title) { | |
382 | var el = $('#'+id).first(); |
|
382 | var el = $('#'+id).first(); | |
383 | if (el.length === 0 || el.is(':visible')) {return;} |
|
383 | if (el.length === 0 || el.is(':visible')) {return;} | |
384 |
|
|
384 | if (!title) title = el.find('h3.title').text(); | |
385 | el.dialog({ |
|
385 | el.dialog({ | |
386 | width: width, |
|
386 | width: width, | |
387 | modal: true, |
|
387 | modal: true, |
@@ -132,6 +132,7 table.list td.checkbox { width: 15px; padding: 2px 0 0 0; } | |||||
132 | table.list td.checkbox input {padding:0px;} |
|
132 | table.list td.checkbox input {padding:0px;} | |
133 | table.list td.buttons { width: 15%; white-space:nowrap; text-align: right; } |
|
133 | table.list td.buttons { width: 15%; white-space:nowrap; text-align: right; } | |
134 | table.list td.buttons a { padding-right: 0.6em; } |
|
134 | table.list td.buttons a { padding-right: 0.6em; } | |
|
135 | table.list td.buttons img {vertical-align:middle;} | |||
135 | table.list td.reorder {width:15%; white-space:nowrap; text-align:center; } |
|
136 | table.list td.reorder {width:15%; white-space:nowrap; text-align:center; } | |
136 | table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; } |
|
137 | table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; } | |
137 |
|
138 | |||
@@ -209,7 +210,7 tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70% | |||||
209 | tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; } |
|
210 | tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; } | |
210 |
|
211 | |||
211 | tr.user td {width:13%;white-space: nowrap;} |
|
212 | tr.user td {width:13%;white-space: nowrap;} | |
212 |
|
|
213 | td.username, td.firstname, td.lastname, td.email {text-align:left !important;} | |
213 | tr.user td.email { width:18%; } |
|
214 | tr.user td.email { width:18%; } | |
214 | tr.user.locked, tr.user.registered { color: #aaa; } |
|
215 | tr.user.locked, tr.user.registered { color: #aaa; } | |
215 | tr.user.locked a, tr.user.registered a { color: #aaa; } |
|
216 | tr.user.locked a, tr.user.registered a { color: #aaa; } | |
@@ -1046,6 +1047,7 a.close-icon:hover {background-image:url('../images/close_hl.png');} | |||||
1046 | .icon-zoom-out { background-image: url(../images/zoom_out.png); } |
|
1047 | .icon-zoom-out { background-image: url(../images/zoom_out.png); } | |
1047 | .icon-passwd { background-image: url(../images/textfield_key.png); } |
|
1048 | .icon-passwd { background-image: url(../images/textfield_key.png); } | |
1048 | .icon-test { background-image: url(../images/bullet_go.png); } |
|
1049 | .icon-test { background-image: url(../images/bullet_go.png); } | |
|
1050 | .icon-email-add { background-image: url(../images/email_add.png); } | |||
1049 |
|
1051 | |||
1050 | .icon-file { background-image: url(../images/files/default.png); } |
|
1052 | .icon-file { background-image: url(../images/files/default.png); } | |
1051 | .icon-file.text-plain { background-image: url(../images/files/text.png); } |
|
1053 | .icon-file.text-plain { background-image: url(../images/files/text.png); } |
@@ -1,22 +1,4 | |||||
1 | --- |
|
1 | --- | |
2 | users_004: |
|
|||
3 | created_on: 2006-07-19 19:34:07 +02:00 |
|
|||
4 | status: 1 |
|
|||
5 | last_login_on: |
|
|||
6 | language: en |
|
|||
7 | # password = foo |
|
|||
8 | salt: 3126f764c3c5ac61cbfc103f25f934cf |
|
|||
9 | hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b |
|
|||
10 | updated_on: 2006-07-19 19:34:07 +02:00 |
|
|||
11 | admin: false |
|
|||
12 | mail: rhill@somenet.foo |
|
|||
13 | lastname: Hill |
|
|||
14 | firstname: Robert |
|
|||
15 | id: 4 |
|
|||
16 | auth_source_id: |
|
|||
17 | mail_notification: all |
|
|||
18 | login: rhill |
|
|||
19 | type: User |
|
|||
20 | users_001: |
|
2 | users_001: | |
21 | created_on: 2006-07-19 19:12:21 +02:00 |
|
3 | created_on: 2006-07-19 19:12:21 +02:00 | |
22 | status: 1 |
|
4 | status: 1 | |
@@ -27,7 +9,6 users_001: | |||||
27 | hashed_password: b5b6ff9543bf1387374cdfa27a54c96d236a7150 |
|
9 | hashed_password: b5b6ff9543bf1387374cdfa27a54c96d236a7150 | |
28 | updated_on: 2006-07-19 22:57:52 +02:00 |
|
10 | updated_on: 2006-07-19 22:57:52 +02:00 | |
29 | admin: true |
|
11 | admin: true | |
30 | mail: admin@somenet.foo |
|
|||
31 | lastname: Admin |
|
12 | lastname: Admin | |
32 | firstname: Redmine |
|
13 | firstname: Redmine | |
33 | id: 1 |
|
14 | id: 1 | |
@@ -45,7 +26,6 users_002: | |||||
45 | hashed_password: bfbe06043353a677d0215b26a5800d128d5413bc |
|
26 | hashed_password: bfbe06043353a677d0215b26a5800d128d5413bc | |
46 | updated_on: 2006-07-19 22:42:15 +02:00 |
|
27 | updated_on: 2006-07-19 22:42:15 +02:00 | |
47 | admin: false |
|
28 | admin: false | |
48 | mail: jsmith@somenet.foo |
|
|||
49 | lastname: Smith |
|
29 | lastname: Smith | |
50 | firstname: John |
|
30 | firstname: John | |
51 | id: 2 |
|
31 | id: 2 | |
@@ -63,7 +43,6 users_003: | |||||
63 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed |
|
43 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed | |
64 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
44 | updated_on: 2006-07-19 19:33:19 +02:00 | |
65 | admin: false |
|
45 | admin: false | |
66 | mail: dlopper@somenet.foo |
|
|||
67 | lastname: Lopper |
|
46 | lastname: Lopper | |
68 | firstname: Dave |
|
47 | firstname: Dave | |
69 | id: 3 |
|
48 | id: 3 | |
@@ -71,6 +50,23 users_003: | |||||
71 | mail_notification: all |
|
50 | mail_notification: all | |
72 | login: dlopper |
|
51 | login: dlopper | |
73 | type: User |
|
52 | type: User | |
|
53 | users_004: | |||
|
54 | created_on: 2006-07-19 19:34:07 +02:00 | |||
|
55 | status: 1 | |||
|
56 | last_login_on: | |||
|
57 | language: en | |||
|
58 | # password = foo | |||
|
59 | salt: 3126f764c3c5ac61cbfc103f25f934cf | |||
|
60 | hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b | |||
|
61 | updated_on: 2006-07-19 19:34:07 +02:00 | |||
|
62 | admin: false | |||
|
63 | lastname: Hill | |||
|
64 | firstname: Robert | |||
|
65 | id: 4 | |||
|
66 | auth_source_id: | |||
|
67 | mail_notification: all | |||
|
68 | login: rhill | |||
|
69 | type: User | |||
74 | users_005: |
|
70 | users_005: | |
75 | id: 5 |
|
71 | id: 5 | |
76 | created_on: 2006-07-19 19:33:19 +02:00 |
|
72 | created_on: 2006-07-19 19:33:19 +02:00 | |
@@ -81,7 +77,6 users_005: | |||||
81 | hashed_password: 1 |
|
77 | hashed_password: 1 | |
82 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
78 | updated_on: 2006-07-19 19:33:19 +02:00 | |
83 | admin: false |
|
79 | admin: false | |
84 | mail: dlopper2@somenet.foo |
|
|||
85 | lastname: Lopper2 |
|
80 | lastname: Lopper2 | |
86 | firstname: Dave2 |
|
81 | firstname: Dave2 | |
87 | auth_source_id: |
|
82 | auth_source_id: | |
@@ -97,7 +92,6 users_006: | |||||
97 | hashed_password: 1 |
|
92 | hashed_password: 1 | |
98 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
93 | updated_on: 2006-07-19 19:33:19 +02:00 | |
99 | admin: false |
|
94 | admin: false | |
100 | mail: '' |
|
|||
101 | lastname: Anonymous |
|
95 | lastname: Anonymous | |
102 | firstname: '' |
|
96 | firstname: '' | |
103 | auth_source_id: |
|
97 | auth_source_id: | |
@@ -116,7 +110,6 users_007: | |||||
116 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed |
|
110 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed | |
117 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
111 | updated_on: 2006-07-19 19:33:19 +02:00 | |
118 | admin: false |
|
112 | admin: false | |
119 | mail: someone@foo.bar |
|
|||
120 | lastname: One |
|
113 | lastname: One | |
121 | firstname: Some |
|
114 | firstname: Some | |
122 | auth_source_id: |
|
115 | auth_source_id: | |
@@ -134,7 +127,6 users_008: | |||||
134 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed |
|
127 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed | |
135 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
128 | updated_on: 2006-07-19 19:33:19 +02:00 | |
136 | admin: false |
|
129 | admin: false | |
137 | mail: miscuser8@foo.bar |
|
|||
138 | lastname: Misc |
|
130 | lastname: Misc | |
139 | firstname: User |
|
131 | firstname: User | |
140 | auth_source_id: |
|
132 | auth_source_id: | |
@@ -150,7 +142,6 users_009: | |||||
150 | hashed_password: 1 |
|
142 | hashed_password: 1 | |
151 | updated_on: 2006-07-19 19:33:19 +02:00 |
|
143 | updated_on: 2006-07-19 19:33:19 +02:00 | |
152 | admin: false |
|
144 | admin: false | |
153 | mail: miscuser9@foo.bar |
|
|||
154 | lastname: Misc |
|
145 | lastname: Misc | |
155 | firstname: User |
|
146 | firstname: User | |
156 | auth_source_id: |
|
147 | auth_source_id: |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class AdminControllerTest < ActionController::TestCase |
|
20 | class AdminControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :roles |
|
21 | fixtures :projects, :users, :email_addresses, :roles | |
22 |
|
22 | |||
23 | def setup |
|
23 | def setup | |
24 | User.current = nil |
|
24 | User.current = nil |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class DocumentsControllerTest < ActionController::TestCase |
|
20 | class DocumentsControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
21 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
22 | :enabled_modules, :documents, :enumerations, |
|
22 | :enabled_modules, :documents, :enumerations, | |
23 | :groups_users, :attachments |
|
23 | :groups_users, :attachments | |
24 |
|
24 |
@@ -19,7 +19,7 require File.expand_path('../../test_helper', __FILE__) | |||||
19 |
|
19 | |||
20 | class IssuesControllerTest < ActionController::TestCase |
|
20 | class IssuesControllerTest < ActionController::TestCase | |
21 | fixtures :projects, |
|
21 | fixtures :projects, | |
22 | :users, |
|
22 | :users, :email_addresses, | |
23 | :roles, |
|
23 | :roles, | |
24 | :members, |
|
24 | :members, | |
25 | :member_roles, |
|
25 | :member_roles, |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class IssuesCustomFieldsVisibilityTest < ActionController::TestCase |
|
20 | class IssuesCustomFieldsVisibilityTest < ActionController::TestCase | |
21 | tests IssuesController |
|
21 | tests IssuesController | |
22 | fixtures :projects, |
|
22 | fixtures :projects, | |
23 | :users, |
|
23 | :users, :email_addresses, | |
24 | :roles, |
|
24 | :roles, | |
25 | :members, |
|
25 | :members, | |
26 | :member_roles, |
|
26 | :member_roles, |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class MailHandlerControllerTest < ActionController::TestCase |
|
20 | class MailHandlerControllerTest < ActionController::TestCase | |
21 | fixtures :users, :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :issue_statuses, |
|
21 | fixtures :users, :email_addresses, :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :issue_statuses, | |
22 | :trackers, :projects_trackers, :enumerations |
|
22 | :trackers, :projects_trackers, :enumerations | |
23 |
|
23 | |||
24 | FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler' |
|
24 | FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler' |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class MessagesControllerTest < ActionController::TestCase |
|
20 | class MessagesControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules |
|
21 | fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :boards, :messages, :enabled_modules | |
22 |
|
22 | |||
23 | def setup |
|
23 | def setup | |
24 | User.current = nil |
|
24 | User.current = nil |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class MyControllerTest < ActionController::TestCase |
|
20 | class MyControllerTest < ActionController::TestCase | |
21 | fixtures :users, :user_preferences, :roles, :projects, :members, :member_roles, |
|
21 | fixtures :users, :email_addresses, :user_preferences, :roles, :projects, :members, :member_roles, | |
22 | :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources |
|
22 | :issues, :issue_statuses, :trackers, :enumerations, :custom_fields, :auth_sources | |
23 |
|
23 | |||
24 | def setup |
|
24 | def setup |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class NewsControllerTest < ActionController::TestCase |
|
20 | class NewsControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
21 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
22 | :enabled_modules, :news, :comments, |
|
22 | :enabled_modules, :news, :comments, | |
23 | :attachments |
|
23 | :attachments | |
24 |
|
24 |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class ProjectsControllerTest < ActionController::TestCase |
|
20 | class ProjectsControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :versions, :users, :roles, :members, |
|
21 | fixtures :projects, :versions, :users, :email_addresses, :roles, :members, | |
22 | :member_roles, :issues, :journals, :journal_details, |
|
22 | :member_roles, :issues, :journals, :journal_details, | |
23 | :trackers, :projects_trackers, :issue_statuses, |
|
23 | :trackers, :projects_trackers, :issue_statuses, | |
24 | :enabled_modules, :enumerations, :boards, :messages, |
|
24 | :enabled_modules, :enumerations, :boards, :messages, |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesBazaarControllerTest < ActionController::TestCase |
|
20 | class RepositoriesBazaarControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class RepositoriesControllerTest < ActionController::TestCase |
|
20 | class RepositoriesControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, |
|
21 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules, | |
22 | :repositories, :issues, :issue_statuses, :changesets, :changes, |
|
22 | :repositories, :issues, :issue_statuses, :changesets, :changes, | |
23 | :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers |
|
23 | :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers | |
24 |
|
24 |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesCvsControllerTest < ActionController::TestCase |
|
20 | class RepositoriesCvsControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/cvs_repository').to_s |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesDarcsControllerTest < ActionController::TestCase |
|
20 | class RepositoriesDarcsControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/darcs_repository').to_s |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesFilesystemControllerTest < ActionController::TestCase |
|
20 | class RepositoriesFilesystemControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/filesystem_repository').to_s |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesGitControllerTest < ActionController::TestCase |
|
20 | class RepositoriesGitControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesMercurialControllerTest < ActionController::TestCase |
|
20 | class RepositoriesMercurialControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
24 | :repositories, :enabled_modules |
|
24 | :repositories, :enabled_modules | |
25 |
|
25 | |||
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s |
|
26 | REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class RepositoriesSubversionControllerTest < ActionController::TestCase |
|
20 | class RepositoriesSubversionControllerTest < ActionController::TestCase | |
21 | tests RepositoriesController |
|
21 | tests RepositoriesController | |
22 |
|
22 | |||
23 | fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, |
|
23 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules, | |
24 | :repositories, :issues, :issue_statuses, :changesets, :changes, |
|
24 | :repositories, :issues, :issue_statuses, :changesets, :changes, | |
25 | :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers |
|
25 | :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers | |
26 |
|
26 |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class UsersControllerTest < ActionController::TestCase |
|
20 | class UsersControllerTest < ActionController::TestCase | |
21 | include Redmine::I18n |
|
21 | include Redmine::I18n | |
22 |
|
22 | |||
23 | fixtures :users, :projects, :members, :member_roles, :roles, |
|
23 | fixtures :users, :email_addresses, :projects, :members, :member_roles, :roles, | |
24 | :custom_fields, :custom_values, :groups_users, |
|
24 | :custom_fields, :custom_values, :groups_users, | |
25 | :auth_sources, |
|
25 | :auth_sources, | |
26 | :enabled_modules, |
|
26 | :enabled_modules, |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class WikiControllerTest < ActionController::TestCase |
|
20 | class WikiControllerTest < ActionController::TestCase | |
21 | fixtures :projects, :users, :roles, :members, :member_roles, |
|
21 | fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, | |
22 | :enabled_modules, :wikis, :wiki_pages, :wiki_contents, |
|
22 | :enabled_modules, :wikis, :wiki_pages, :wiki_contents, | |
23 | :wiki_content_versions, :attachments, |
|
23 | :wiki_content_versions, :attachments, | |
24 | :issues, :issue_statuses |
|
24 | :issues, :issue_statuses |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class AccountTest < Redmine::IntegrationTest |
|
20 | class AccountTest < Redmine::IntegrationTest | |
21 | fixtures :users, :roles |
|
21 | fixtures :users, :email_addresses, :roles | |
22 |
|
22 | |||
23 | def test_login |
|
23 | def test_login | |
24 | get "/my/page" |
|
24 | get "/my/page" |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base |
|
20 | class Redmine::ApiTest::UsersTest < Redmine::ApiTest::Base | |
21 | fixtures :users, :members, :member_roles, :roles, :projects |
|
21 | fixtures :users, :email_addresses, :members, :member_roles, :roles, :projects | |
22 |
|
22 | |||
23 | test "GET /users.xml should return users" do |
|
23 | test "GET /users.xml should return users" do | |
24 | get '/users.xml', {}, credentials('admin') |
|
24 | get '/users.xml', {}, credentials('admin') |
@@ -19,7 +19,7 require File.expand_path('../../test_helper', __FILE__) | |||||
19 |
|
19 | |||
20 | class IssuesTest < Redmine::IntegrationTest |
|
20 | class IssuesTest < Redmine::IntegrationTest | |
21 | fixtures :projects, |
|
21 | fixtures :projects, | |
22 | :users, |
|
22 | :users, :email_addresses, | |
23 | :roles, |
|
23 | :roles, | |
24 | :members, |
|
24 | :members, | |
25 | :member_roles, |
|
25 | :member_roles, |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class UsersTest < Redmine::IntegrationTest |
|
20 | class UsersTest < Redmine::IntegrationTest | |
21 | fixtures :users |
|
21 | fixtures :users, :email_addresses | |
22 |
|
22 | |||
23 | def test_destroy_should_not_accept_get_requests |
|
23 | def test_destroy_should_not_accept_get_requests | |
24 | assert_no_difference 'User.count' do |
|
24 | assert_no_difference 'User.count' do |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class DocumentTest < ActiveSupport::TestCase |
|
20 | class DocumentTest < ActiveSupport::TestCase | |
21 | fixtures :projects, :enumerations, :documents, :attachments, |
|
21 | fixtures :projects, :enumerations, :documents, :attachments, | |
22 | :enabled_modules, |
|
22 | :enabled_modules, | |
23 | :users, :members, :member_roles, :roles, |
|
23 | :users, :email_addresses, :members, :member_roles, :roles, | |
24 | :groups_users |
|
24 | :groups_users | |
25 |
|
25 | |||
26 | def test_create |
|
26 | def test_create |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class IssueTest < ActiveSupport::TestCase |
|
20 | class IssueTest < ActiveSupport::TestCase | |
21 | fixtures :projects, :users, :members, :member_roles, :roles, |
|
21 | fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, | |
22 | :groups_users, |
|
22 | :groups_users, | |
23 | :trackers, :projects_trackers, |
|
23 | :trackers, :projects_trackers, | |
24 | :enabled_modules, |
|
24 | :enabled_modules, |
@@ -223,6 +223,17 class MailHandlerTest < ActiveSupport::TestCase | |||||
223 | assert_equal 1, issue.watcher_user_ids.size |
|
223 | assert_equal 1, issue.watcher_user_ids.size | |
224 | end |
|
224 | end | |
225 |
|
225 | |||
|
226 | def test_add_issue_from_additional_email_address | |||
|
227 | user = User.find(2) | |||
|
228 | user.mail = 'mainaddress@somenet.foo' | |||
|
229 | user.save! | |||
|
230 | EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo') | |||
|
231 | ||||
|
232 | issue = submit_email('ticket_on_given_project.eml') | |||
|
233 | assert issue | |||
|
234 | assert_equal user, issue.author | |||
|
235 | end | |||
|
236 | ||||
226 | def test_add_issue_by_unknown_user |
|
237 | def test_add_issue_by_unknown_user | |
227 | assert_no_difference 'User.count' do |
|
238 | assert_no_difference 'User.count' do | |
228 | assert_equal false, |
|
239 | assert_equal false, |
@@ -20,7 +20,7 require File.expand_path('../../test_helper', __FILE__) | |||||
20 | class MailerTest < ActiveSupport::TestCase |
|
20 | class MailerTest < ActiveSupport::TestCase | |
21 | include Redmine::I18n |
|
21 | include Redmine::I18n | |
22 | include ActionDispatch::Assertions::SelectorAssertions |
|
22 | include ActionDispatch::Assertions::SelectorAssertions | |
23 | fixtures :projects, :enabled_modules, :issues, :users, :members, |
|
23 | fixtures :projects, :enabled_modules, :issues, :users, :email_addresses, :members, | |
24 | :member_roles, :roles, :documents, :attachments, :news, |
|
24 | :member_roles, :roles, :documents, :attachments, :news, | |
25 | :tokens, :journals, :journal_details, :changesets, |
|
25 | :tokens, :journals, :journal_details, :changesets, | |
26 | :trackers, :projects_trackers, |
|
26 | :trackers, :projects_trackers, | |
@@ -298,6 +298,14 class MailerTest < ActiveSupport::TestCase | |||||
298 | assert last_email.bcc.include?('dlopper@somenet.foo') |
|
298 | assert last_email.bcc.include?('dlopper@somenet.foo') | |
299 | end |
|
299 | end | |
300 |
|
300 | |||
|
301 | def test_issue_add_should_send_mail_to_all_user_email_address | |||
|
302 | EmailAddress.create!(:user_id => 3, :address => 'otheremail@somenet.foo') | |||
|
303 | issue = Issue.find(1) | |||
|
304 | assert Mailer.deliver_issue_add(issue) | |||
|
305 | assert last_email.bcc.include?('dlopper@somenet.foo') | |||
|
306 | assert last_email.bcc.include?('otheremail@somenet.foo') | |||
|
307 | end | |||
|
308 | ||||
301 | test "#issue_add should not notify project members that are not allow to view the issue" do |
|
309 | test "#issue_add should not notify project members that are not allow to view the issue" do | |
302 | issue = Issue.find(1) |
|
310 | issue = Issue.find(1) | |
303 | Role.find(2).remove_permission!(:view_issues) |
|
311 | Role.find(2).remove_permission!(:view_issues) | |
@@ -771,6 +779,30 class MailerTest < ActiveSupport::TestCase | |||||
771 | ActionMailer::Base.delivery_method = :test |
|
779 | ActionMailer::Base.delivery_method = :test | |
772 | end |
|
780 | end | |
773 |
|
781 | |||
|
782 | def test_email_addresses_should_keep_addresses | |||
|
783 | assert_equal ["foo@example.net"], | |||
|
784 | Mailer.email_addresses("foo@example.net") | |||
|
785 | ||||
|
786 | assert_equal ["foo@example.net", "bar@example.net"], | |||
|
787 | Mailer.email_addresses(["foo@example.net", "bar@example.net"]) | |||
|
788 | end | |||
|
789 | ||||
|
790 | def test_email_addresses_should_replace_users_with_their_email_addresses | |||
|
791 | assert_equal ["admin@somenet.foo"], | |||
|
792 | Mailer.email_addresses(User.find(1)) | |||
|
793 | ||||
|
794 | assert_equal ["admin@somenet.foo", "jsmith@somenet.foo"], | |||
|
795 | Mailer.email_addresses(User.where(:id => [1,2])).sort | |||
|
796 | end | |||
|
797 | ||||
|
798 | def test_email_addresses_should_include_notified_emails_addresses_only | |||
|
799 | EmailAddress.create!(:user_id => 2, :address => "another@somenet.foo", :notify => false) | |||
|
800 | EmailAddress.create!(:user_id => 2, :address => "another2@somenet.foo") | |||
|
801 | ||||
|
802 | assert_equal ["another2@somenet.foo", "jsmith@somenet.foo"], | |||
|
803 | Mailer.email_addresses(User.find(2)).sort | |||
|
804 | end | |||
|
805 | ||||
774 | private |
|
806 | private | |
775 |
|
807 | |||
776 | def last_email |
|
808 | def last_email |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class UserTest < ActiveSupport::TestCase |
|
20 | class UserTest < ActiveSupport::TestCase | |
21 | fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources, |
|
21 | fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources, | |
22 | :trackers, :issue_statuses, |
|
22 | :trackers, :issue_statuses, | |
23 | :projects_trackers, |
|
23 | :projects_trackers, | |
24 | :watchers, |
|
24 | :watchers, | |
@@ -57,11 +57,41 class UserTest < ActiveSupport::TestCase | |||||
57 | assert_equal "foo@bar.com", u.mail |
|
57 | assert_equal "foo@bar.com", u.mail | |
58 | end |
|
58 | end | |
59 |
|
59 | |||
60 | def test_mail_validation |
|
60 | def test_should_create_email_address | |
61 | u = User.new |
|
61 | u = User.new(:firstname => "new", :lastname => "user") | |
|
62 | u.login = "create_email_address" | |||
|
63 | u.mail = "defaultemail@somenet.foo" | |||
|
64 | assert u.save | |||
|
65 | u.reload | |||
|
66 | assert u.email_address | |||
|
67 | assert_equal "defaultemail@somenet.foo", u.email_address.address | |||
|
68 | assert_equal true, u.email_address.is_default | |||
|
69 | assert_equal true, u.email_address.notify | |||
|
70 | end | |||
|
71 | ||||
|
72 | def test_should_not_create_user_without_mail | |||
|
73 | set_language_if_valid 'en' | |||
|
74 | u = User.new(:firstname => "new", :lastname => "user") | |||
|
75 | u.login = "user_without_mail" | |||
|
76 | assert !u.save | |||
|
77 | assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages | |||
|
78 | end | |||
|
79 | ||||
|
80 | def test_should_not_create_user_with_blank_mail | |||
|
81 | set_language_if_valid 'en' | |||
|
82 | u = User.new(:firstname => "new", :lastname => "user") | |||
|
83 | u.login = "user_with_blank_mail" | |||
|
84 | u.mail = '' | |||
|
85 | assert !u.save | |||
|
86 | assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages | |||
|
87 | end | |||
|
88 | ||||
|
89 | def test_should_not_update_user_with_blank_mail | |||
|
90 | set_language_if_valid 'en' | |||
|
91 | u = User.find(2) | |||
62 | u.mail = '' |
|
92 | u.mail = '' | |
63 |
assert !u. |
|
93 | assert !u.save | |
64 |
assert_ |
|
94 | assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages | |
65 | end |
|
95 | end | |
66 |
|
96 | |||
67 | def test_login_length_validation |
|
97 | def test_login_length_validation | |
@@ -151,6 +181,7 class UserTest < ActiveSupport::TestCase | |||||
151 | end |
|
181 | end | |
152 |
|
182 | |||
153 | def test_mail_uniqueness_should_not_be_case_sensitive |
|
183 | def test_mail_uniqueness_should_not_be_case_sensitive | |
|
184 | set_language_if_valid 'en' | |||
154 | u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") |
|
185 | u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo") | |
155 | u.login = 'newuser1' |
|
186 | u.login = 'newuser1' | |
156 | u.password, u.password_confirmation = "password", "password" |
|
187 | u.password, u.password_confirmation = "password", "password" | |
@@ -160,7 +191,7 class UserTest < ActiveSupport::TestCase | |||||
160 | u.login = 'newuser2' |
|
191 | u.login = 'newuser2' | |
161 | u.password, u.password_confirmation = "password", "password" |
|
192 | u.password, u.password_confirmation = "password", "password" | |
162 | assert !u.save |
|
193 | assert !u.save | |
163 |
assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors |
|
194 | assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages | |
164 | end |
|
195 | end | |
165 |
|
196 | |||
166 | def test_update |
|
197 | def test_update | |
@@ -677,7 +708,7 class UserTest < ActiveSupport::TestCase | |||||
677 | assert_kind_of AnonymousUser, anon1 |
|
708 | assert_kind_of AnonymousUser, anon1 | |
678 | anon2 = AnonymousUser.create( |
|
709 | anon2 = AnonymousUser.create( | |
679 | :lastname => 'Anonymous', :firstname => '', |
|
710 | :lastname => 'Anonymous', :firstname => '', | |
680 |
|
|
711 | :login => '', :status => 0) | |
681 | assert_equal 1, anon2.errors.count |
|
712 | assert_equal 1, anon2.errors.count | |
682 | end |
|
713 | end | |
683 |
|
714 |
@@ -18,7 +18,7 | |||||
18 | require File.expand_path('../../test_helper', __FILE__) |
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
19 |
|
19 | |||
20 | class WatcherTest < ActiveSupport::TestCase |
|
20 | class WatcherTest < ActiveSupport::TestCase | |
21 | fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules, |
|
21 | fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :enabled_modules, | |
22 | :issues, :issue_statuses, :enumerations, :trackers, :projects_trackers, |
|
22 | :issues, :issue_statuses, :enumerations, :trackers, :projects_trackers, | |
23 | :boards, :messages, |
|
23 | :boards, :messages, | |
24 | :wikis, :wiki_pages, |
|
24 | :wikis, :wiki_pages, |
General Comments 0
You need to be logged in to leave comments.
Login now