diff --git a/app/controllers/my_profile/mailconf_controller.rb b/app/controllers/my_profile/mailconf_controller.rb index 1cefbe4..1c6e24f 100644 --- a/app/controllers/my_profile/mailconf_controller.rb +++ b/app/controllers/my_profile/mailconf_controller.rb @@ -15,11 +15,27 @@ class MailconfController < MyProfileController @user = profile.user end - post_only :save - def save - profile.user.update_attributes(params[:user]) - flash[:notice] = _('e-Mail settings saved successfully.') - redirect_to :action => 'index' + post_only :enable + def enable + @task = EmailActivation.new(:target => environment, :requestor => profile) + begin + @task.save! + flash[:notice] = _('Please fill your personal information below in order to get your mailbox approved by one of the administrators') + redirect_to :controller => 'profile_editor', :action => 'edit' + rescue Exception => ex + flash[:notice] = _('e-Mail was not enabled successfully.') + render :action => 'index' + end + end + post_only :disable + def disable + if profile.user.disable_email! + flash[:notice] = _('e-Mail disabled successfully.') + redirect_to :controller => 'profile_editor' + else + flash[:notice] = _('e-Mail was not disabled successfully.') + redirect_to :action => 'index' + end end end diff --git a/app/controllers/my_profile/profile_editor_controller.rb b/app/controllers/my_profile/profile_editor_controller.rb index c4b13b6..4c95a72 100644 --- a/app/controllers/my_profile/profile_editor_controller.rb +++ b/app/controllers/my_profile/profile_editor_controller.rb @@ -3,7 +3,7 @@ class ProfileEditorController < MyProfileController protect 'edit_profile', :profile def index - @pending_tasks = profile.tasks.pending.select{|i| user.has_permission?(i.permission, profile)} + @pending_tasks = profile.all_pending_tasks.select{|i| user.has_permission?(i.permission, profile)} end helper :profile diff --git a/app/controllers/my_profile/tasks_controller.rb b/app/controllers/my_profile/tasks_controller.rb index 47945e0..ed1bba9 100644 --- a/app/controllers/my_profile/tasks_controller.rb +++ b/app/controllers/my_profile/tasks_controller.rb @@ -3,11 +3,11 @@ class TasksController < MyProfileController protect 'perform_task', :profile def index - @tasks = profile.tasks.pending + @tasks = profile.all_pending_tasks end def processed - @tasks = profile.tasks.finished + @tasks = profile.all_finished_tasks end VALID_DECISIONS = [ 'finish', 'cancel' ] @@ -15,7 +15,7 @@ class TasksController < MyProfileController def close decision = params[:decision] if request.post? && VALID_DECISIONS.include?(decision) && params[:id] - task = profile.tasks.find(params[:id]) + task = profile.find_in_all_tasks(params[:id]) task.update_attributes!(params[:task]) task.send(decision) end diff --git a/app/controllers/public/enterprise_registration_controller.rb b/app/controllers/public/enterprise_registration_controller.rb index 2b4910e..843e625 100644 --- a/app/controllers/public/enterprise_registration_controller.rb +++ b/app/controllers/public/enterprise_registration_controller.rb @@ -10,6 +10,9 @@ class EnterpriseRegistrationController < ApplicationController # to the first step explicitly? def index @create_enterprise = CreateEnterprise.new(params[:create_enterprise]) + if params[:create_enterprise] && params[:create_enterprise][:target_id] + @create_enterprise.target = Profile.find(params[:create_enterprise][:target_id]) + end @create_enterprise.requestor = current_user.person the_action = if request.post? diff --git a/app/models/email_activation.rb b/app/models/email_activation.rb new file mode 100644 index 0000000..e80ae87 --- /dev/null +++ b/app/models/email_activation.rb @@ -0,0 +1,26 @@ +class EmailActivation < Task + + validates_presence_of :requestor_id, :target_id + + alias :environment :target + alias :person :requestor + + def validate_on_create + if !self.requestor.nil? && self.requestor.user.email_activation_pending? + self.errors.add_to_base(_('You have already requested activation of your mailbox.')) + end + end + + def description + _("'%{user} wants to activate email '%{email}'") % { :user => person.name, :email => person.email_addresses.join(', ') } + end + + def perform + person.user.enable_email! + end + + def sends_email? + false + end + +end diff --git a/app/models/environment.rb b/app/models/environment.rb index f63abc1..14378f4 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -3,6 +3,8 @@ # domains. class Environment < ActiveRecord::Base + has_many :tasks, :dependent => :destroy, :as => 'target' + PERMISSIONS['Environment'] = { 'view_environment_admin_panel' => N_('View environment admin panel'), 'edit_environment_features' => N_('Edit environment features'), diff --git a/app/models/profile.rb b/app/models/profile.rb index 9e4b60d..dbc1141 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -103,7 +103,32 @@ class Profile < ActiveRecord::Base has_many :consumptions has_many :consumed_product_categories, :through => :consumptions, :source => :product_category - has_many :tasks, :foreign_key => :target_id, :dependent => :destroy + has_many :tasks, :dependent => :destroy, :as => 'target' + + %w[ pending finished ].each do |status| + class_eval <<-CODE + def all_#{status}_tasks + env_tasks = [] + if self.person? + env_tasks = Environment.find(:all).select{ |env| self.is_admin?(env) }.map{ |env| env.tasks.#{status} }.flatten + end + tasks.#{status} + env_tasks + end + CODE + end + + def find_in_all_tasks(task_id) + if tasks.exists?(task_id) + return tasks.find(task_id) + else + if self.person? + environments_admin = Environment.find(:all).select{ |env| self.is_admin?(env) } + task = environments_admin.select{ |env| env.tasks.exists?(task_id) }.map{ |i| i.tasks.find(task_id) } + return task.first unless task.empty? + end + end + return nil + end has_many :profile_categorizations, :conditions => [ 'categories_profiles.virtual = ?', false ] has_many :categories, :through => :profile_categorizations diff --git a/app/models/task.rb b/app/models/task.rb index 49cf626..4e5be50 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -28,7 +28,7 @@ class Task < ActiveRecord::Base end belongs_to :requestor, :class_name => 'Person', :foreign_key => :requestor_id - belongs_to :target, :class_name => 'Profile', :foreign_key => :target_id + belongs_to :target, :foreign_key => :target_id, :polymorphic => true validates_uniqueness_of :code, :on => :create validates_presence_of :code diff --git a/app/models/user.rb b/app/models/user.rb index 56c5fa6..0a7387d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -185,6 +185,22 @@ class User < ActiveRecord::Base person.name end + def enable_email! + self.update_attribute(:enable_email, true) + end + + def disable_email! + self.update_attribute(:enable_email, false) + end + + def email_activation_pending? + if self.environment.nil? + return false + else + return EmailActivation.exists?(:requestor_id => self.person.id, :target_id => self.environment.id, :status => Task::Status::ACTIVE) + end + end + protected # before filter def encrypt_password diff --git a/app/views/mailconf/index.rhtml b/app/views/mailconf/index.rhtml index 4f3f08c..ad9f6ef 100644 --- a/app/views/mailconf/index.rhtml +++ b/app/views/mailconf/index.rhtml @@ -1,17 +1,37 @@

<%= _('e-Mail configuration') %>

-<% form_tag(:action => 'save') do %> +<%= error_messages_for :task %> -
- <%= check_box :user, :enable_email %> - -
- <%= _("Marking this option gives you an e-mail account with the address above. You'll be able to access a webmail from your user menu.") %> -
-
+<% if profile.user.email_activation_pending? %> + +

<%= _('You already request activation of your mailbox. Please wait until an administrator approves your request.') %>

<% button_bar do %> - <%= submit_button :save, _('Save') %> <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> <% end %> + +<% else %> + + + <% if profile.user.enable_email %> + +

<%= _("Disable e-Mail account below:") %>

+ + <% button_bar do %> + <%= button(:cancel, _('Disable e-Mail'), { :action => 'disable' }, :method => 'post') %> + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> + <% end %> + + <% else %> + +

<%= _("Enable e-Mail account below:") %>

+ +
<%= _("You'll be able to access a webmail from your user menu.") %>
+ <% button_bar do %> + <%= button(:ok, _('Enable e-Mail'), { :action => 'enable' }, :method => 'post') %> + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> + <% end %> + + <% end %> + <% end %> diff --git a/app/views/tasks/new.rhtml b/app/views/tasks/new.rhtml index ef61935..7de4661 100644 --- a/app/views/tasks/new.rhtml +++ b/app/views/tasks/new.rhtml @@ -7,6 +7,7 @@ <% else %> <%= display_form_field( _('To: '), f.select(:target_id, profile.friends.map{|p|[p.name, p.id]})) %> <% end %> + <%= hidden_field_tag 'ticket[target_type]', 'Profile' %> <%= f.text_field :title, :style => 'width:80%;' %> <%= f.text_area :description, :style => 'height:200px; width:80%;' %> diff --git a/config/mail.yml.dist b/config/mail.yml.dist new file mode 100644 index 0000000..ebc364f --- /dev/null +++ b/config/mail.yml.dist @@ -0,0 +1,2 @@ +enabled: true +webmail_url: "http://mail.yourdomain.net/" diff --git a/db/migrate/061_add_target_type_column_for_task.rb b/db/migrate/061_add_target_type_column_for_task.rb new file mode 100644 index 0000000..1b66186 --- /dev/null +++ b/db/migrate/061_add_target_type_column_for_task.rb @@ -0,0 +1,10 @@ +class AddTargetTypeColumnForTask < ActiveRecord::Migration + def self.up + add_column :tasks, :target_type, :string + execute "update tasks set target_type = 'Profile'" + end + + def self.down + remove_column :tasks, :target_type + end +end diff --git a/db/schema.rb b/db/schema.rb index 611e511..dfebde8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 60) do +ActiveRecord::Schema.define(:version => 61) do create_table "article_versions", :force => true do |t| t.integer "article_id" @@ -288,6 +288,7 @@ ActiveRecord::Schema.define(:version => 60) do t.string "code", :limit => 40 t.string "type" t.datetime "created_at" + t.string "target_type" end create_table "thumbnails", :force => true do |t| diff --git a/po/pt_BR/noosfero.po b/po/pt_BR/noosfero.po index 9206ee9..40b51d3 100644 --- a/po/pt_BR/noosfero.po +++ b/po/pt_BR/noosfero.po @@ -12,8 +12,13 @@ msgid "" msgstr "" "Project-Id-Version: noosfero 0.13.0\n" +<<<<<<< HEAD:po/pt_BR/noosfero.po "POT-Creation-Date: 2009-01-30 15:19-0300\n" -"PO-Revision-Date: 2009-02-02 19:06-0300\n" +"PO-Revision-Date: 2009-02-03 18:38-0300\n" +======= +"POT-Creation-Date: 2009-01-06 16:46-0300\n" +"PO-Revision-Date: 2009-01-28 18:24-0300\n" +>>>>>>> ActionItem897-novo:po/pt_BR/noosfero.po "Last-Translator: Joenio Costa \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -4542,6 +4547,10 @@ msgstr "%s quer publicar conteúdo: %s." msgid "Name for publishing" msgstr "Nome para publicação" +#: app/views/mailconf/index.rhtml:1 +msgid "e-Mail configuration" +msgstr "Configuração de e-Mail" + #: app/views/tasks/_approve_article.rhtml:24 msgid "Comment for author" msgstr "Comentário para o autor" diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index 8f7c87d..03b0450 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -55,3 +55,10 @@ profile_moderator: system: true permissions: - moderate_comments +environment_administrator: + id: 8 + key: 'environment_administrator' + name: 'Environment administrator' + system: true + permissions: + - perform_task diff --git a/test/functional/mailconf_controller_test.rb b/test/functional/mailconf_controller_test.rb index ecf82bc..5d5e4a5 100644 --- a/test/functional/mailconf_controller_test.rb +++ b/test/functional/mailconf_controller_test.rb @@ -51,28 +51,18 @@ class MailconfControllerTest < Test::Unit::TestCase login_as('ze') get :index, :profile => 'ze' assert_tag( - :tag => 'form', - :attributes => { :action => '/myprofile/ze/mailconf/save'}, - :descendant => { - :tag => 'input', - :attributes => { :name => 'user[enable_email]', :type => 'checkbox' } - } + :tag => 'a', + :content => 'Enable e-Mail', + :attributes => {:href => '/myprofile/ze/mailconf/enable'} ) end - should 'display correctly the state true of e-mail enable/disable' do - login_as('ze') - users(:ze).update_attributes!(:enable_email => true) - get :index, :profile => 'ze' - assert_tag :tag => 'input', :attributes => { :name => 'user[enable_email]', :type => 'checkbox', :value => '1', :checked => 'checked' } - end - should 'display correctly the state false of e-mail enable/disable' do login_as('ze') users(:ze).update_attributes!(:enable_email => false) get :index, :profile => 'ze' - assert_no_tag :tag => 'input', :attributes => { :name => 'user[enable_email]', :type => 'checkbox', :value => '1', :checked => 'checked' } - assert_tag :tag => 'input', :attributes => { :name => 'user[enable_email]', :type => 'hidden', :value => '0' } + assert_tag :tag => 'a', :content => 'Enable e-Mail' + assert_no_tag :tag => 'a', :content => 'Disable e-Mail', :attributes => { :href => '/myprofile/ze/mailconf/disable' } end should 'not display www in email address when force_www=true' do @@ -81,7 +71,7 @@ class MailconfControllerTest < Test::Unit::TestCase env.force_www = true env.save! get :index, :profile => 'ze' - assert_tag :tag => 'label', :attributes => { :for => 'user_enable_email' }, :content => /ze@colivre.net/ + assert_tag :tag => 'li', :content => /ze@colivre.net/ end should 'not display www in email address when force_www=false' do @@ -90,30 +80,38 @@ class MailconfControllerTest < Test::Unit::TestCase env.force_www = false env.save! get :index, :profile => 'ze' - assert_tag :tag => 'label', :attributes => { :for => 'user_enable_email' }, :content => /ze@colivre.net/ + assert_tag :tag => 'li', :content => /ze@colivre.net/ end - should 'save mail enable/disable as true' do + should 'create task to environment admin when enable email' do login_as('ze') - post :save, :profile => 'ze', :user => { :enable_email => '1' } - assert Profile['ze'].user.enable_email + assert_difference EmailActivation, :count do + post :enable, :profile => 'ze' + end end should 'save mail enable/disable as false' do login_as('ze') - post :save, :profile => 'ze', :user => { :enable_email => '0' } + assert users(:ze).enable_email! + post :disable, :profile => 'ze' assert !Profile['ze'].user.enable_email end should 'go back on save' do login_as('ze') - post :save, :profile => 'ze' - assert_redirected_to :action => 'index' + post :enable, :profile => 'ze' + assert_redirected_to :controller => 'profile_editor' + end + + should 'go to profile editor after enable email' do + login_as('ze') + post :enable, :profile => 'ze' + assert_redirected_to :controller => 'profile_editor', :action => 'edit' end should 'display notice after saving' do login_as('ze') - post :save, :profile => 'ze' + post :enable, :profile => 'ze' assert_kind_of String, flash[:notice] end @@ -123,4 +121,12 @@ class MailconfControllerTest < Test::Unit::TestCase assert_tag :tag => 'div', :attributes => { :id => 'content'}, :descendant => { :tag => 'a', :attributes => { :href => '/myprofile/ze' } } end + should 'not display input for enable/disable e-mail when has pending_enable_email' do + login_as('ze') + users(:ze).update_attribute(:environment_id, Environment.default.id) + EmailActivation.create!(:requestor => users(:ze).person, :target => Environment.default) + get :index, :profile => 'ze' + assert_no_tag :tag => 'input', :attributes => {:name => 'user[enable_email]', :type => 'checkbox'} + end + end diff --git a/test/functional/profile_editor_controller_test.rb b/test/functional/profile_editor_controller_test.rb index c10e09e..c920138 100644 --- a/test/functional/profile_editor_controller_test.rb +++ b/test/functional/profile_editor_controller_test.rb @@ -46,8 +46,7 @@ class ProfileEditorControllerTest < Test::Unit::TestCase pending = [] pending.expects(:select).returns(pending) pending.expects(:empty?).returns(false) # force the display of the pending tasks list - tasks.expects(:pending).returns(pending) - ze.expects(:tasks).returns(tasks) + ze.expects(:all_pending_tasks).returns(pending) get :index, :profile => ze.identifier assert_same pending, assigns(:pending_tasks) assert_tag :tag => 'div', :attributes => { :class => 'pending-tasks' }, :descendant => { :tag => 'a', :attributes => { :href => '/myprofile/ze/tasks' } } diff --git a/test/functional/tasks_controller_test.rb b/test/functional/tasks_controller_test.rb index 053a05d..7da5cb8 100644 --- a/test/functional/tasks_controller_test.rb +++ b/test/functional/tasks_controller_test.rb @@ -147,7 +147,8 @@ class TasksControllerTest < Test::Unit::TestCase f = create_user('friend').person profile.add_friend f - post :new, :profile => profile.identifier, :ticket => {:title => 'test ticket', :target_id => f.id} + post :new, :profile => profile.identifier, :ticket => {:title => 'test ticket', :target_id => f.id, :target_type => 'Profile'} + assert_response :redirect assert_equal f, assigns(:ticket).target end diff --git a/test/integration/enterprise_registration_test.rb b/test/integration/enterprise_registration_test.rb index 8ce1655..cc95802 100644 --- a/test/integration/enterprise_registration_test.rb +++ b/test/integration/enterprise_registration_test.rb @@ -39,6 +39,7 @@ class EnterpriseRegistrationTest < ActionController::IntegrationTest post '/enterprise_registration', :create_enterprise => data.merge(:target_id => org.id) end + assert_template 'confirmation' assert_tag :tag => 'a', :attributes => { :href => '/' } code = CreateEnterprise.find(:first, :order => 'id desc').code diff --git a/test/unit/create_enterprise_test.rb b/test/unit/create_enterprise_test.rb index 3ec6842..5e45fc7 100644 --- a/test/unit/create_enterprise_test.rb +++ b/test/unit/create_enterprise_test.rb @@ -109,8 +109,8 @@ class CreateEnterpriseTest < Test::Unit::TestCase :legal_form => 'cooperative', :economic_activity => 'free software', :region_id => region.id, - :requestor_id => person.id, - :target_id => validator.id, + :requestor => person, + :target => validator, }) enterprise = Enterprise.new @@ -143,8 +143,8 @@ class CreateEnterpriseTest < Test::Unit::TestCase :legal_form => 'cooperative', :economic_activity => 'free software', :region_id => region.id, - :requestor_id => person.id, - :target_id => validator.id, + :requestor => person, + :target => validator, }) enterprise = Enterprise.new diff --git a/test/unit/email_activation_test.rb b/test/unit/email_activation_test.rb new file mode 100644 index 0000000..c52a792 --- /dev/null +++ b/test/unit/email_activation_test.rb @@ -0,0 +1,44 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class EmailActivationTest < Test::Unit::TestCase + + should 'require a requestor' do + task = EmailActivation.new + task.valid? + + assert task.errors.invalid?(:requestor_id) + end + + should 'require a target (environment)' do + task = EmailActivation.new + task.valid? + + assert task.errors.invalid?(:target_id) + end + + should 'enable user email when finish' do + ze = create_user('zezinho', :environment_id => Environment.default.id) + assert !ze.enable_email + task = EmailActivation.create!(:requestor => ze.person, :target => Environment.default) + task.finish + ze.reload + assert ze.enable_email + end + + should 'create only once pending task by user' do + ze = create_user('zezinho', :environment_id => Environment.default.id) + task = EmailActivation.new(:requestor => ze.person, :target => Environment.default) + assert task.save! + + anothertask = EmailActivation.new(:requestor => ze.person, :target => Environment.default) + assert !anothertask.save + end + + should 'display email address on description of task' do + ze = create_user('zezinho', :environment_id => Environment.default.id) + Environment.default.domains = [Domain.create!(:name => 'env_test.invalid')] + task = EmailActivation.new(:requestor => ze.person, :target => Environment.default) + assert_match /zezinho@env_test.invalid/, task.description + end + +end diff --git a/test/unit/environment_test.rb b/test/unit/environment_test.rb index e74df78..8505e27 100644 --- a/test/unit/environment_test.rb +++ b/test/unit/environment_test.rb @@ -681,4 +681,11 @@ class EnvironmentTest < Test::Unit::TestCase assert_equal ['Category'], Environment.new.category_types end + should 'has tasks' do + e = Environment.default + assert_nothing_raised do + e.tasks + end + end + end diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb index 4224231..2666c20 100644 --- a/test/unit/profile_test.rb +++ b/test/unit/profile_test.rb @@ -1198,6 +1198,56 @@ class ProfileTest < Test::Unit::TestCase assert community.enable_contact? end + should 'include pending tasks from environment if is admin' do + env = Environment.default + person = create_user('molly').person + task = Task.create!(:requestor => person, :target => env) + + Person.any_instance.stubs(:is_admin?).returns(true) + assert_equal [task], person.all_pending_tasks + end + + should 'find task from environment if is admin' do + env = Environment.default + person = create_user('molly').person + task = Task.create!(:requestor => person, :target => env) + + Person.any_instance.stubs(:is_admin?).returns(true) + assert_equal task, person.find_in_all_tasks(task.id) + end + + should 'find task from all environment if is admin' do + env = Environment.default + another = Environment.create!(:name => 'another_env') + person = Person['ze'] + task1 = Task.create!(:requestor => person, :target => env) + task2 = Task.create!(:requestor => person, :target => another) + + another.affiliate(person, Environment::Roles.admin) + env.affiliate(person, Environment::Roles.admin) + + Person.any_instance.stubs(:is_admin?).returns(true) + + assert_equal [task1, task2], person.all_pending_tasks + end + + should 'find task by id on all environments' do + env = Environment.create!(:name => 'other_env') + another = Environment.create!(:name => 'another_env') + person = Person['ze'] + + task1 = Task.create!(:requestor => person, :target => env) + task2 = Task.create!(:requestor => person, :target => another) + + person.stubs(:is_admin?).with(env).returns(true) + Environment.find(:all).select{|i| i.name != 'other_env'}.each do |env| + person.stubs(:is_admin?).with(env).returns(false) + end + + assert_not_nil person.find_in_all_tasks(task1.id) + assert_nil person.find_in_all_tasks(task2.id) + end + private def assert_invalid_identifier(id) diff --git a/test/unit/task_test.rb b/test/unit/task_test.rb index 6abdf34..2f7723f 100644 --- a/test/unit/task_test.rb +++ b/test/unit/task_test.rb @@ -20,10 +20,10 @@ class TaskTest < Test::Unit::TestCase end end - def test_relationship_with_target + should 'target be able to polymorphic relationship' do t = Task.create - assert_raise ActiveRecord::AssociationTypeMismatch do - t.target = 1 + assert_nothing_raised do + t.target = Environment.new end assert_nothing_raised do t.target = Profile.new diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 41ed654..5e4f2b0 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -262,6 +262,27 @@ class UserTest < Test::Unit::TestCase assert_equal false, User.new.enable_email end + should 'enable email' do + user = create_user('cooler') + assert !user.enable_email + assert user.enable_email! + assert user.enable_email + end + + should 'has email activation pending' do + user = create_user('cooler') + user.update_attribute(:environment_id, Environment.default.id) + EmailActivation.create!(:requestor => user.person, :target => Environment.default) + assert user.email_activation_pending? + end + + should 'not has email activation pending if not have environment' do + user = create_user('cooler') + user.expects(:environment).returns(nil) + EmailActivation.create!(:requestor => user.person, :target => Environment.default) + assert !user.email_activation_pending? + end + protected def new_user(options = {}) user = User.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options)) -- libgit2 0.21.2