Merge branch 'invite-refactor' note: this requires you to migrate your

database
This commit is contained in:
Maxwell Salzberg 2011-08-17 16:28:39 -07:00
commit 57ee4cd8a9
25 changed files with 592 additions and 615 deletions

View file

@ -8,12 +8,12 @@ class AdminsController < ApplicationController
@users = params[:user].empty? ? [] : User.where(params[:user])
end
def admin_inviter
opts = {:service => 'email', :identifier => params[:identifier]}
existing_user = Invitation.find_existing_user('email', params[:identifier])
opts.merge!(:existing_user => existing_user) if existing_user
Invitation.create_invitee(opts)
flash[:notice] = "invitation sent to #{params[:identifier]}"
def admin_inviter
user = User.find_by_email params[:idenitifer]
unless user
Invitation.create(:service => 'email', :identifer => params[:identifier], :admin => true)
flash[:notice] = "invitation sent to #{params[:identifier]}"
end
redirect_to user_search_path
end

View file

@ -5,6 +5,7 @@
class InvitationsController < Devise::InvitationsController
before_filter :check_token, :only => [:edit]
before_filter :check_if_invites_open, :only =>[:create]
def new
@sent_invitations = current_user.invitations_from_me.includes(:recipient)
@ -16,63 +17,36 @@ class InvitationsController < Devise::InvitationsController
end
def create
unless AppConfig[:open_invitations]
flash[:error] = I18n.t 'invitations.create.no_more'
redirect_to :back
return
end
aspect = params[:user].delete(:aspects)
aspect_id = params[:user].delete(:aspects)
message = params[:user].delete(:invite_messages)
emails = params[:user][:email].to_s.gsub(/\s/, '').split(/, */)
#NOTE should we try and find users by email here? probs
aspect = current_user.aspects.find(aspect_id)
good_emails, bad_emails = emails.partition{|e| e.try(:match, Devise.email_regexp)}
invites = Invitation.batch_invite(emails, :sender => current_user, :aspect => aspect, :service => 'email')
if good_emails.include?(current_user.email)
if good_emails.length == 1
flash[:error] = I18n.t 'invitations.create.own_address'
redirect_to :back
return
else
bad_emails.push(current_user.email)
good_emails.delete(current_user.email)
end
end
good_emails.each{|e| Resque.enqueue(Job::Mail::InviteUserByEmail, current_user.id, e, aspect, message)}
if bad_emails.any?
flash[:error] = I18n.t('invitations.create.sent') + good_emails.join(', ') + " "+ I18n.t('invitations.create.rejected') + bad_emails.join(', ')
else
flash[:notice] = I18n.t('invitations.create.sent') + good_emails.join(', ')
end
flash[:notice] = extract_messages(invites)
redirect_to :back
end
def update
begin
invitation_token = params[:user][:invitation_token]
if invitation_token.nil? || invitation_token.blank?
raise I18n.t('invitations.check_token.not_found')
end
user = User.find_by_invitation_token(params[:user][:invitation_token])
user = User.find_by_invitation_token!(invitation_token)
user.accept_invitation!(params[:user])
user.seed_aspects
rescue Exception => e #What exception is this trying to rescue? If it is ActiveRecord::NotFound, we should say so.
raise e unless e.respond_to?(:record)
user = nil
record = e.record
record.errors.delete(:person)
flash[:error] = record.errors.full_messages.join(", ")
end
if user
flash[:notice] = I18n.t 'registrations.create.success'
sign_in_and_redirect(:user, user)
if user.persisted? && user.person && user.person.persisted?
user.seed_aspects
flash[:notice] = I18n.t 'registrations.create.success'
sign_in_and_redirect(:user, user)
else
redirect_to accept_user_invitation_path(
:invitation_token => params[:user][:invitation_token])
redirect_to accept_user_invitation_path(:invitation_token => params[:user][:invitation_token]), :error => user.errors.full_messages.join(", ")
end
end
@ -90,12 +64,37 @@ class InvitationsController < Devise::InvitationsController
@resource = User.find_by_invitation_token(params[:invitation_token])
render 'devise/mailer/invitation_instructions', :layout => false
end
protected
protected
def check_token
if User.find_by_invitation_token(params[:invitation_token]).nil?
flash[:error] = I18n.t 'invitations.check_token.not_found'
redirect_to root_url
end
end
def check_if_invites_open
unless AppConfig[:open_invitations]
flash[:error] = I18n.t 'invitations.create.no_more'
redirect_to :back
return
end
end
# @param invites [Array<Invitation>] Invitations to be sent.
# @return [String] A full list of success and error messages.
def extract_messages(invites)
success_message = "Invites Successfully Sent to: "
failure_message = "There was a problem with: "
successes, failures = invites.partition{|x| x.persisted? }
success_message += successes.map{|k| k.identifier }.join(', ')
failure_message += failures.map{|k| k.identifier }.join(', ')
messages = []
messages << success_message if successes.present?
messages << failure_message if failures.present?
messages.join('\n')
end
end

View file

@ -59,7 +59,8 @@ class ServicesController < ApplicationController
if i_id = params[:invitation_id]
invited_user = Invitation.find(i_id).recipient
else
invited_user = current_user.invite_user(params[:aspect_id], params[:provider], @uid)
invite = Invitation.create(:service => params[:provider], :identifier => @uid, :sender => current_user, :aspect => current_user.aspects.find(params[:aspect_id]))
invited_user = invite.attach_recipient!
end
@subject = t('services.inviter.join_me_on_diaspora')

View file

@ -1,4 +1,4 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# Copyright (c) 2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
@ -8,121 +8,145 @@ class Invitation < ActiveRecord::Base
belongs_to :recipient, :class_name => 'User'
belongs_to :aspect
validates_presence_of :sender,
:recipient,
:aspect
attr_accessible :sender, :recipient, :aspect, :service, :identifier, :admin
# @param opts [Hash] Takes :identifier, :service, :idenfitier, :from, :message
# @return [User]
def self.invite(opts={})
opts[:identifier].downcase! if opts[:identifier]
# return if the current user is trying to invite himself via email
return false if opts[:identifier] == opts[:from].email
before_validation :set_email_as_default_service
if existing_user = self.find_existing_user(opts[:service], opts[:identifier])
# If the sender of the invitation is already connected to the person
# he is inviting, raise an error.
if opts[:from].contact_for(opts[:from].person)
raise "You are already connceted to this person"
validates_presence_of :identifier, :service
validate :valid_identifier?
validates_presence_of :sender, :aspect, :unless => :admin?
validate :ensure_not_inviting_self, :on => :create, :unless => :admin?
validate :sender_owns_aspect?, :unless => :admin?
validates_uniqueness_of :sender_id, :scope => [:identifier, :service], :unless => :admin?
# Check whether or not the existing User has already been invited;
# and if so, start sharing with the Person.
elsif not existing_user.invited?
opts[:from].share_with(existing_user.person, opts[:into])
return
after_create :queue_send! #TODO make this after_commit :queue_saved!, :on => :create
# If the sender has already invited the recipient, raise an error.
elsif Invitation.where(:sender_id => opts[:from].id, :recipient_id => existing_user.id).first
raise "You already invited this person"
# When everything checks out, we merge the existing user into the
# options hash to pass on to self.create_invitee.
else
opts.merge(:existing_user => existing_user)
end
# @note options hash is passed through to [Invitation.new]
# @see [Invitation.new]
#
# @param [Array<String>] emails
# @option opts [User] :sender
# @option opts [Aspect] :aspect
# @option opts [String] :service
# @return [Array<Invitation>] An array of [Invitation] models
# the valid ones are saved, and the invalid ones are not.
def self.batch_invite(emails, opts)
users_on_pod = User.where(:email => emails, :invitation_token => nil)
#share with anyone whose email you entered who is on the pod
emails = emails - users_on_pod.map{|u| u.email}
users_on_pod.each{|u| opts[:sender].share_with(u.person, opts[:aspect])}
emails.map! do |e|
Invitation.create(opts.merge(:identifier => e))
end
create_invitee(opts)
emails
end
# @param service [String] String representation of the service invitation provider (i.e. facebook, email)
# @param identifier [String] String representation of the reciepients identity on the provider (i.e. 'bob.smith', bob@aol.com)
# @return [User]
def self.find_existing_user(service, identifier)
unless existing_user = User.where(:invitation_service => service,
:invitation_identifier => identifier).first
if service == 'email'
existing_user ||= User.where(:email => identifier).first
else
existing_user ||= User.joins(:services).where(:services => {:type => "Services::#{service.titleize}", :uid => identifier}).first
end
end
existing_user
# Downcases the incoming service identifier and assigns it
#
# @param ident [String] Service identifier
# @see super
def identifier=(ident)
ident.downcase! if ident
super
end
# @params opts [Hash] Takes :from, :existing_user, :service, :identifier, :message
# @return [User]
def self.create_invitee(opts={})
invitee = opts[:existing_user]
invitee ||= User.new(:invitation_service => opts[:service], :invitation_identifier => opts[:identifier])
# Determine if we want to skip emailing the recipient.
#
# @return [Boolean]
# @return [void]
def skip_email?
self.service != 'email'
end
# (dan) I'm not sure why, but we need to call .valid? on our User.
invitee.valid?
# Return a User immediately if an invalid email is passed in
return invitee if opts[:service] == 'email' && !opts[:identifier].match(Devise.email_regexp)
if invitee.new_record?
invitee.errors.clear
invitee.serialized_private_key = User.generate_key if invitee.serialized_private_key.blank?
invitee.send(:generate_invitation_token)
elsif invitee.invitation_token.nil?
return invitee
# Attach a recipient [User] to the [Invitation] unless
# there is one already present.
#
# @return [User] The recipient.
def attach_recipient!
unless self.recipient.present?
self.recipient = User.find_or_create_by_invitation(self)
self.save
end
self.recipient
end
# Logic if there is an explicit sender
if opts[:from]
invitee.save(:validate => false)
Invitation.create!(:sender => opts[:from],
:recipient => invitee,
:aspect => opts[:into],
:message => opts[:message])
invitee.reload
end
invitee.skip_invitation = (opts[:service] != 'email')
invitee.invite!
# Find or create user, and send that resultant User an
# invitation.
#
# @return [Invitation] self
def send!
self.attach_recipient!
# Sets an instance variable in User (set by devise invitable)
# This determines whether an email should be sent to the recipient.
recipient.skip_invitation = self.skip_email?
recipient.invite!
# Logging the invitation action
log_hash = {:event => :invitation_sent, :to => opts[:identifier], :service => opts[:service]}
log_hash.merge({:inviter => opts[:from].diaspora_handle, :invitier_uid => opts[:from].id, :inviter_created_at_unix => opts[:from].created_at.to_i}) if opts[:from]
log_hash = {:event => :invitation_sent, :to => self[:identifier], :service => self[:service]}
log_hash.merge({:inviter => self.sender.diaspora_handle, :invitier_uid => self.sender.id, :inviter_created_at_unix => self.sender.created_at.to_i}) if self.sender
Rails.logger.info(log_hash)
invitee
self
end
# @return [Invitation] self
def resend
recipient.invite!
end
# @return Contact
def share_with!
if contact = sender.share_with(recipient.person, aspect)
self.destroy
end
contact
self.send!
end
# @return [String]
def recipient_identifier
if recipient.invitation_service == 'email'
recipient.invitation_identifier
elsif recipient.invitation_service == 'facebook'
if su = ServiceUser.where(:uid => recipient.invitation_identifier).first
case self.service
when 'email'
self.identifier
when'facebook'
if su = ServiceUser.where(:uid => self.identifier).first
su.name
else
I18n.t('invitations.a_facebook_user')
end
end
end
def queue_send!
unless self.recipient.present?
Resque.enqueue(Job::Mail::InviteUserByEmail, self.id)
end
end
# @note before_save
def set_email_as_default_service
self.service ||= 'email'
end
# @note Validation
def ensure_not_inviting_self
if self.identifier == self.sender.email
errors[:base] << 'You can not invite yourself.'
end
end
# @note Validation
def sender_owns_aspect?
if self.sender_id != self.aspect.user_id
errors[:base] << 'You do not own that aspect.'
end
end
# @note Validation
def valid_identifier?
return false unless self.identifier
if self.service == 'email'
unless self.identifier.match(Devise.email_regexp)
errors[:base] << 'invalid email'
end
end
end
end

View file

@ -7,9 +7,9 @@ module Job
module Mail
class InviteUserByEmail < Base
@queue = :mail
def self.perform(sender_id, email, aspect_id, invite_message)
user = User.find(sender_id)
user.invite_user(aspect_id, 'email', email, invite_message)
def self.perform(invite_id)
invite = Invitation.find(invite_id)
invite.send!
end
end
end

View file

@ -7,7 +7,7 @@ module Job
class ResendInvitation < Base
@queue = :mail
def self.perform(invitation_id)
inv = Invitation.where(:id => invitation_id).first
inv = Invitation.find(invitation_id)
inv.resend
end
end

View file

@ -19,6 +19,7 @@ class Person < ActiveRecord::Base
has_one :profile, :dependent => :destroy
delegate :last_name, :to => :profile
accepts_nested_attributes_for :profile
before_validation :downcase_diaspora_handle
def downcase_diaspora_handle
@ -51,7 +52,21 @@ class Person < ActiveRecord::Base
AppConfig[:featured_users].present? ? Person.where(:diaspora_handle => AppConfig[:featured_users]) : []
end
# Set a default of an empty profile when a new Person record is instantiated.
# Passing :profile => nil to Person.new will instantiate a person with no profile.
# Calling Person.new with a block:
# Person.new do |p|
# p.profile = nil
# end
# will not work! The nil profile will be overriden with an empty one.
def initialize(params={})
profile_set = params.has_key?(:profile) || params.has_key?("profile")
params[:profile_attributes] = params.delete(:profile) if params.has_key?(:profile) && params[:profile].is_a?(Hash)
super
self.profile ||= Profile.new unless profile_set
end
def self.find_from_id_or_username(params)
p = if params[:id].present?
Person.where(:id => params[:id]).first

View file

@ -30,8 +30,8 @@ class ServiceUser < ActiveRecord::Base
self.contact = self.service.user.contact_for(self.person)
end
self.invitation = Invitation.joins(:recipient).where(:sender_id => self.service.user_id,
:users => {:invitation_service => self.service.provider,
:invitation_identifier => self.uid}).first
self.invitation = Invitation.where(:sender_id => self.service.user_id,
:service => self.service.provider,
:identifier => self.uid).first
end
end

View file

@ -59,24 +59,46 @@ class User < ActiveRecord::Base
:invitation_service,
:invitation_identifier
# Sometimes we access the person in a strange way and need to do this
# @note we should make this method depricated.
#
# @return [Person]
def save_person!
self.person.save if self.person && self.person.changed?
self.person
# @return [User]
def self.find_by_invitation(invitation)
service = invitation.service
identifier = invitation.identifier
if service == 'email'
existing_user = User.where(:email => identifier).first
else
existing_user = User.joins(:services).where(:services => {:type => "Services::#{service.titleize}", :uid => identifier}).first
end
if existing_user.nil?
i = Invitation.where(:service => service, :identifier => identifier).first
existing_user = i.recipient if i
end
existing_user
end
# Set the User's email to the one they've been invited at, if the user
# is being created via an invitation.
#
# @return [User]
def infer_email_from_invitation_provider
self.email = self.invitation_identifier if self.invitation_service == 'email'
self
def self.find_or_create_by_invitation(invitation)
if existing_user = self.find_by_invitation(invitation)
existing_user
else
self.create_from_invitation!(invitation)
end
end
def self.create_from_invitation!(invitation)
user = User.new
user.generate_keys
user.send(:generate_invitation_token)
user.email = invitation.identifier if invitation.service == 'email'
# we need to make a custom validator here to make this safer
user.save(:validate => false)
user
end
def update_user_preferences(pref_hash)
if self.disable_mail
UserPreference::VALID_EMAIL_TYPES.each{|x| self.user_preferences.find_or_create_by_email_type(x)}
@ -291,19 +313,6 @@ class User < ActiveRecord::Base
end
end
###Invitations############
def invite_user(aspect_id, service, identifier, invite_message = "")
if aspect = aspects.find(aspect_id)
Invitation.invite(:service => service,
:identifier => identifier,
:from => self,
:into => aspect,
:message => invite_message)
else
false
end
end
# This method is called when an invited user accepts his invitation
#
# @param [Hash] opts the options to accept the invitation with
@ -312,25 +321,29 @@ class User < ActiveRecord::Base
# @option opts [String] :password_confirmation
def accept_invitation!(opts = {})
log_hash = {:event => :invitation_accepted, :username => opts[:username], :uid => self.id}
log_hash[:inviter] = invitations_to_me.first.sender.diaspora_handle if invitations_to_me.first
begin
if self.invited?
self.setup(opts)
self.invitation_token = nil
self.password = opts[:password]
self.password_confirmation = opts[:password_confirmation]
self.save!
invitations_to_me.each{|invitation| invitation.share_with!}
log_hash[:status] = "success"
Rails.logger.info log_hash
log_hash[:inviter] = invitations_to_me.first.sender.diaspora_handle if invitations_to_me.first && invitations_to_me.first.sender
self.reload # Because to_request adds a request and saves elsewhere
self
if self.invited?
self.setup(opts)
self.invitation_token = nil
self.password = opts[:password]
self.password_confirmation = opts[:password_confirmation]
self.save
return unless self.errors.empty?
# moved old Invitation#share_with! logic into here,
# but i don't think we want to destroy the invitation
# anymore. we may want to just call self.share_with
invitations_to_me.each do |invitation|
if !invitation.admin? && invitation.sender.share_with(self.person, invitation.aspect)
invitation.destroy
end
end
rescue Exception => e
log_hash[:status] = "failure"
Rails.logger.info log_hash
raise e
log_hash[:status] = "success"
Rails.logger.info(log_hash)
self
end
end
@ -344,28 +357,22 @@ class User < ActiveRecord::Base
def setup(opts)
self.username = opts[:username]
self.email = opts[:email]
self.language ||= 'en'
self.valid?
errors = self.errors
errors.delete :person
return if errors.size > 0
opts[:person] ||= {}
unless opts[:person][:profile].is_a?(Profile)
opts[:person][:profile] ||= Profile.new
opts[:person][:profile] = Profile.new(opts[:person][:profile])
end
self.person = Person.new(opts[:person])
self.person.diaspora_handle = "#{opts[:username]}@#{AppConfig[:pod_uri].authority}"
self.person.url = AppConfig[:pod_url]
self.serialized_private_key = User.generate_key if self.serialized_private_key.blank?
self.person.serialized_public_key = OpenSSL::PKey::RSA.new(self.serialized_private_key).public_key
self.set_person(Person.new(opts[:person] || {} ))
self.generate_keys
self
end
def set_person(person)
person.url = AppConfig[:pod_url]
person.diaspora_handle = "#{self.username}@#{AppConfig[:pod_uri].authority}"
self.person = person
end
def seed_aspects
self.aspects.create(:name => I18n.t('aspects.seed.family'))
self.aspects.create(:name => I18n.t('aspects.seed.friends'))
@ -379,10 +386,6 @@ class User < ActiveRecord::Base
aq
end
def self.generate_key
key_size = (Rails.env == 'test' ? 512 : 4096)
OpenSSL::PKey::RSA::generate(key_size)
end
def encryption_key
OpenSSL::PKey::RSA.new(serialized_private_key)
@ -433,4 +436,34 @@ class User < ActiveRecord::Base
i += 1
end
end
# Generate public/private keys for User and associated Person
def generate_keys
key_size = (Rails.env == 'test' ? 512 : 4096)
self.serialized_private_key = OpenSSL::PKey::RSA::generate(key_size) if self.serialized_private_key.blank?
if self.person && self.person.serialized_public_key.blank?
self.person.serialized_public_key = OpenSSL::PKey::RSA.new(self.serialized_private_key).public_key
end
end
# Sometimes we access the person in a strange way and need to do this
# @note we should make this method depricated.
#
# @return [Person]
def save_person!
self.person.save if self.person && self.person.changed?
self.person
end
# Set the User's email to the one they've been invited at, if the user
# is being created via an invitation.
#
# @return [User]
def infer_email_from_invitation_provider
self.email = self.invitation_identifier if self.invitation_service == 'email'
self
end
end

View file

@ -1,5 +1,5 @@
- @invs = @resource.invitations_to_me
-if @invs.count > 0
-unless @invs.first.admin?
!!!
%html
%head

View file

@ -0,0 +1,17 @@
class AddFieldsToInvitations < ActiveRecord::Migration
def self.up
add_column :invitations, :service, :string
add_column :invitations, :identifier, :string
add_column :invitations, :admin, :boolean, :default => false
change_column :invitations, :recipient_id, :integer, :null => true
change_column :invitations, :sender_id, :integer, :null => true
end
def self.down
remove_column :invitations, :service
remove_column :invitations, :identifier
remove_column :invitations, :admin
change_column :invitations, :recipient_id, :integer, :null => false
change_column :invitations, :sender_id, :integer, :null => false
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20110815210933) do
ActiveRecord::Schema.define(:version => 20110816061820) do
create_table "aspect_memberships", :force => true do |t|
t.integer "aspect_id", :null => false
@ -99,11 +99,14 @@ ActiveRecord::Schema.define(:version => 20110815210933) do
create_table "invitations", :force => true do |t|
t.text "message"
t.integer "sender_id", :null => false
t.integer "recipient_id", :null => false
t.integer "sender_id"
t.integer "recipient_id"
t.integer "aspect_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "service"
t.string "identifier"
t.boolean "admin", :default => false
end
add_index "invitations", ["aspect_id"], :name => "index_invitations_on_aspect_id"

View file

@ -35,13 +35,15 @@ Given /^a user named "([^\"]*)" with email "([^\"]*)"$/ do |name, email|
end
Given /^I have been invited by an admin$/ do
@me = Invitation.create_invitee(:service => 'email', :identifier => "new_invitee@example.com")
i = Invitation.create!(:admin => true, :service => 'email', :identifier => "new_invitee@example.com")
@me = i.attach_recipient!
end
Given /^I have been invited by a user$/ do
@inviter = Factory(:user)
aspect = @inviter.aspects.create(:name => "Rocket Scientists")
@me = @inviter.invite_user(aspect.id, 'email', "new_invitee@example.com", "Hey, tell me about your rockets!")
i = Invitation.create!(:aspect => aspect, :sender => @inviter, :service => 'email', :identifier => "new_invitee@example.com", :message =>"Hey, tell me about your rockets!")
@me = i.attach_recipient!
end
When /^I click on my name$/ do

View file

@ -21,9 +21,17 @@ module RakeHelpers
churn_through = n
backer_name = backers[n+offset][1].to_s.strip
backer_email = backers[n+offset][0].to_s.strip
unless User.find_by_email(backer_email) || User.find_by_invitation_identifier(backer_email)
possible_user = User.find_by_email(backer_email)
possible_invite = Invitation.find_by_identifier(backer_email)
possible_user ||= possible_invite.recipient if possible_invite.present?
unless possible_user
puts "#{n}: sending email to: #{backer_name} #{backer_email}" unless Rails.env == 'test'
Invitation.create_invitee(:service => 'email', :identifier => backer_email, :name => backer_name ) unless test
unless test
i = Invitation.new(:service => 'email', :identifier => backer_email, :admin => true)
i.send!
end
else
puts "user with the email exists: #{backer_email} , #{backer_name} " unless Rails.env == 'test'
end

View file

@ -85,19 +85,11 @@ describe AdminsController do
end
it 'invites a new user' do
Invitation.should_receive(:create_invitee).with(:service => 'email', :identifier => 'bob@moms.com')
Invitation.should_receive(:create)
get :admin_inviter, :identifier => 'bob@moms.com'
response.should redirect_to user_search_path
flash.notice.should include("invitation sent")
end
it 'passes an existing user to create_invitee' do
Factory.create(:user, :email => 'bob@moms.com')
bob = User.where(:email => 'bob@moms.com').first
Invitation.should_receive(:find_existing_user).with('email', 'bob@moms.com').and_return(bob)
Invitation.should_receive(:create_invitee).with(:service => 'email', :identifier => 'bob@moms.com', :existing_user => bob)
get :admin_inviter, :identifier => 'bob@moms.com'
end
end
end

View file

@ -11,6 +11,7 @@ describe InvitationsController do
AppConfig[:open_invitations] = true
@user = alice
@aspect = @user.aspects.first
@invite = {:invite_message=>"test", :aspects=> @aspect.id.to_s, :email=>"abc@example.com"}
request.env["devise.mapping"] = Devise.mappings[:user]
Webfinger.stub_chain(:new, :fetch).and_return(Factory(:person))
@ -19,43 +20,37 @@ describe InvitationsController do
describe "#create" do
before do
sign_in :user, @user
@invite = {:invite_message=>"test", :aspect_id=> @aspect.id.to_s, :email=>"abc@example.com"}
@controller.stub!(:current_user).and_return(@user)
request.env["HTTP_REFERER"]= 'http://test.host/cats/foo'
end
it 'calls the resque job Job::InviteUser' do
Resque.should_receive(:enqueue)
post :create, :user => @invite
it 'saves and invitation' do
expect {
post :create, :user => @invite
}.should change(Invitation, :count).by(1)
end
it 'handles a comma seperated list of emails' do
Resque.should_receive(:enqueue).twice()
post :create, :user => @invite.merge(
expect{
post :create, :user => @invite.merge(
:email => "foofoofoofoo@example.com, mbs@gmail.com")
}.should change(Invitation, :count).by(2)
end
it 'handles a comma seperated list of emails with whitespace' do
Resque.should_receive(:enqueue).twice()
post :create, :user => @invite.merge(
:email => "foofoofoofoo@example.com , mbs@gmail.com")
end
it 'displays a message that tells the user how many invites were sent, and which REJECTED' do
post :create, :user => @invite.merge(
:email => "mbs@gmail.com, foo@bar.com, foo.com, lala@foo, cool@bar.com")
flash[:error].should_not be_empty
flash[:error].should =~ /foo\.com/
flash[:error].should =~ /lala@foo/
expect {
post :create, :user => @invite.merge(
:email => "foofoofoofoo@example.com , mbs@gmail.com")
}.should change(Invitation, :count).by(2)
end
it "allows invitations without if invitations are open" do
open_bit = AppConfig[:open_invitations]
AppConfig[:open_invitations] = true
Resque.should_receive(:enqueue).once
post :create, :user => @invite
expect{
post :create, :user => @invite
}.to change(Invitation, :count).by(1)
AppConfig[:open_invitations] = open_bit
end
@ -67,16 +62,19 @@ describe InvitationsController do
it 'strips out your own email' do
lambda {
post :create, :user => @invite.merge(:email => @user.email)
}.should_not change(User, :count)
}.should_not change(Invitation, :count)
Resque.should_receive(:enqueue).once
post :create, :user => @invite.merge(:email => "hello@example.org, #{@user.email}")
expect{
post :create, :user => @invite.merge(:email => "hello@example.org, #{@user.email}")
}.should change(Invitation, :count).by(1)
end
end
describe "#update" do
before do
@invited_user = @user.invite_user(@aspect.id, 'email', "a@a.com")
invite = Factory(:invitation, :sender => @user, :service => 'email', :identifier => "a@a.com")
@invited_user = invite.attach_recipient!
@accept_params = {:user=>
{:password_confirmation =>"password",
:email => "a@a.com",
@ -137,7 +135,8 @@ describe InvitationsController do
@controller.stub!(:current_user).and_return(@user)
request.env["HTTP_REFERER"]= 'http://test.host/cats/foo'
@invited_user = @user.invite_user(@aspect.id, 'email', "a@a.com", "")
invite = Factory(:invitation, :sender => @user, :service => 'email', :identifier => "a@a.com")
@invited_user = invite.attach_recipient!
end
it 'calls resend invitation if one exists' do
@ -148,12 +147,24 @@ describe InvitationsController do
end
it 'does not send an invitation for a different user' do
@user2 = bob
@aspect2 = @user2.aspects.create(:name => "cats")
@user2.invite_user(@aspect2.id, 'email', "b@b.com", "")
invitation2 = @user2.reload.invitations_from_me.first
invitation2 = Factory(:invitation, :sender => bob, :service => 'email', :identifier => "a@a.com")
Resque.should_not_receive(:enqueue)
put :resend, :id => invitation2.id
put :resend, :id => invitation2.id
end
end
describe '#extract_messages' do
before do
sign_in alice
end
it 'displays a message that tells the user how many invites were sent, and which REJECTED' do
post :create, :user => @invite.merge(
:email => "mbs@gmail.com, foo@bar.com, foo.com, lala@foo, cool@bar.com")
flash[:notice].should_not be_empty
flash[:notice].should =~ /foo\.com/
flash[:notice].should =~ /lala@foo/
end
end
end

View file

@ -146,7 +146,7 @@ describe ServicesController do
end
it 'does not create a duplicate invitation' do
inv = Invitation.create!(:sender_id => @user.id, :recipient_id => eve.id, :aspect_id => @user.aspects.first.id)
inv = Invitation.create!(:sender => @user, :recipient => eve, :aspect => @user.aspects.first, :identifier => eve.email)
@invite_params[:invitation_id] = inv.id
lambda {

View file

@ -21,7 +21,7 @@ Factory.define :person do |p|
p.sequence(:url) { |n| AppConfig[:pod_url] }
p.serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export
p.after_build do |person|
person.profile ||= Factory.build(:profile, :person => person)
person.profile = Factory.build(:profile, :person => person) unless person.profile.first_name.present?
end
p.after_create do |person|
person.profile.save
@ -96,6 +96,15 @@ Factory.define :reshare do |r|
r.association(:author, :factory => :person)
end
Factory.define :invitation do |i|
i.service "email"
i.identifier "bob.smith@smith.com"
i.association :sender, :factory => :user_with_aspect
i.after_build do |i|
i.aspect = i.sender.aspects.first
end
end
Factory.define :service do |service|
service.nickname "sirrobertking"
service.type "Services::Twitter"

View file

@ -14,8 +14,9 @@ describe RakeHelpers do
Devise.mailer.deliveries = []
end
it 'should send emails to each backer' do
Invitation.should_receive(:create_invitee).exactly(3).times
process_emails(@csv, 100, 1, false)
expect{
process_emails(@csv, 100, 1, false)
}.to change(User, :count).by(3)
end
it 'should not send the email to the same email twice' do

View file

@ -1,4 +1,4 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# Copyright (c) 2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
@ -6,7 +6,6 @@ require 'spec_helper'
describe Invitation do
let(:user) { alice }
let(:aspect) { user.aspects.first }
before do
@email = 'maggie@example.com'
@ -14,292 +13,130 @@ describe Invitation do
end
describe 'validations' do
before do
aspect
@invitation = Invitation.new(:sender => user, :recipient => eve, :aspect => aspect)
@invitation = Factory.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first)
end
it 'is valid' do
@invitation.sender.should == user
@invitation.recipient.should == eve
@invitation.aspect.should == aspect
@invitation.aspect.should == user.aspects.first
@invitation.should be_valid
end
it 'is from a user' do
@invitation.sender = nil
@invitation.should_not be_valid
end
it 'is to a user' do
@invitation.recipient = nil
@invitation.should_not be_valid
end
it 'is into an aspect' do
@invitation.aspect = nil
it 'ensures the sender is placing the recipient into one of his aspects' do
@invitation.aspect = Factory(:aspect)
@invitation.should_not be_valid
end
end
it 'has a message' do
@invitation = Invitation.new(:sender => user, :recipient => eve, :aspect => aspect)
@invitation = Factory.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first)
@invitation.message = "!"
@invitation.message.should == "!"
end
describe '.find_existing_user' do
let(:inv) { Invitation.find_existing_user(@type, @identifier) }
context 'send a request to an existing' do
context 'active user' do
it 'by email' do
@identifier = alice.email
@type = 'email'
inv.should == alice
end
it 'by service' do
uid = '123324234'
alice.services << Services::Facebook.new(:uid => uid)
alice.save
@type = 'facebook'
@identifier = uid
inv.should == alice
end
end
context 'invited user' do
it 'by email' do
@identifier = alice.email
@type = 'email'
alice.invitation_identifier = @identifier
alice.invitation_service = @type
alice.save
inv.should == alice
end
it 'by service' do
fb_id = 'abc123'
alice.invitation_service = 'facebook'
alice.invitation_identifier = fb_id
alice.save
@identifier = fb_id
@type = 'facebook'
inv.should == alice
end
end
describe 'the invite process' do
before do
end
end
describe '.invite' do
it 'creates an invitation' do
it 'works for a new user' do
invite = Invitation.new(:sender => alice, :aspect => alice.aspects.first, :service => 'email', :identifier => 'foo@bar.com')
lambda {
Invitation.invite(:service => 'email', :identifier => @email, :from => user, :into => aspect)
}.should change(Invitation, :count).by(1)
end
it 'associates the invitation with the inviter' do
lambda {
Invitation.invite(:service => 'email', :identifier => @email, :from => user, :into => aspect)
}.should change { user.reload.invitations_from_me.count }.by(1)
end
it 'associates the invitation with the invitee' do
new_user = Invitation.invite(:service => 'email', :identifier => @email, :from => user, :into => aspect)
new_user.invitations_to_me.count.should == 1
end
it 'creates a user' do
lambda {
Invitation.invite(:from => user, :service => 'email', :identifier => @email, :into => aspect)
invite.save
invite.send!
}.should change(User, :count).by(1)
end
it 'returns the new user' do
new_user = Invitation.invite(:from => user, :service => 'email', :identifier => @email, :into => aspect)
new_user.is_a?(User).should be_true
new_user.email.should == @email
it 'works for a current user(with the right email)' do
invite = Invitation.create(:sender => alice, :aspect => alice.aspects.first, :service => 'email', :identifier => bob.email)
lambda {
invite.send!
}.should_not change(User, :count)
end
it 'adds the inviter to the invited_user' do
new_user = Invitation.invite(:from => user, :service => 'email', :identifier => @email, :into => aspect)
new_user.invitations_to_me.first.sender.should == user
it 'works for a current user(with the same fb id)' do
bob.services << Factory.build(:service, :type => "Services::Facebook")
invite = Invitation.create(:sender => alice, :aspect => alice.aspects.first, :service => 'facebook', :identifier => bob.services.first.uid)
lambda {
invite.send!
}.should_not change(User, :count)
end
it 'adds an optional message' do
message = "How've you been?"
new_user = Invitation.invite(:from => user, :service => 'email', :identifier => @email, :into => aspect, :message => message)
new_user.invitations_to_me.first.message.should == message
it 'handles the case when that user has an invite but not a user' do
pending
end
it 'sends a contact request to a user with that email into the aspect' do
user.should_receive(:share_with).with(eve.person, aspect)
Invitation.invite(:from => user, :service => 'email', :identifier => eve.email, :into => aspect)
it 'handles the case where that user has an invite but has not yet accepted' do
pending
end
context 'invalid email' do
it 'return a user with errors' do
new_user = Invitation.invite(:service => 'email', :identifier => "fkjlsdf", :from => user, :into => aspect)
new_user.should have(1).errors_on(:email)
new_user.should_not be_persisted
end
it 'generate the invitation token and pass it to the user' do
end
end
describe '.create_invitee' do
context "when we're resending an invitation" do
before do
@valid_params = {:from => user,
:service => 'email',
:identifier => @email,
:into => aspect,
:message => @message}
@invitee = Invitation.create_invitee(:service => 'email', :identifier => @email)
@valid_params[:existing_user] = @invitee
end
it "does not create a user" do
expect { Invitation.create_invitee(@valid_params) }.should_not change(User, :count)
end
it "sends mail" do
expect {
Invitation.create_invitee(@valid_params)
}.should change { Devise.mailer.deliveries.size }.by(1)
end
it "does not set the key" do
expect {
Invitation.create_invitee(@valid_params)
}.should_not change { @invitee.reload.serialized_private_key }
end
it "does not change the invitation token" do
old_token = @invitee.invitation_token
Invitation.create_invitee(@valid_params)
@invitee.reload.invitation_token.should == old_token
end
end
context 'with an inviter' do
before do
@message = "whatever"
@valid_params = {:from => user, :service => 'email', :identifier => @email, :into => aspect, :message => @message}
end
it "sends mail" do
expect {
Invitation.create_invitee(@valid_params)
}.should change { Devise.mailer.deliveries.size }.by(1)
end
it "includes the message in the email" do
Invitation.create_invitee(@valid_params)
Devise.mailer.deliveries.last.to_s.should include(@message)
end
it "has no translation missing" do
Invitation.create_invitee(@valid_params)
Devise.mailer.deliveries.last.body.raw_source.should_not match(/(translation_missing.+)/)
end
it "doesn't create a user if the email is invalid" do
new_user = Invitation.create_invitee(@valid_params.merge(:identifier => 'fdfdfdfdf'))
new_user.should_not be_persisted
new_user.should have(1).error_on(:email)
end
it "does not save a user with an empty string email" do
@valid_params[:service] = 'facebook'
@valid_params[:identifier] = '3423423'
Invitation.create_invitee(@valid_params)
@valid_params[:identifier] = 'dfadsfdas'
expect { Invitation.create_invitee(@valid_params) }.should_not raise_error
end
end
context 'with no inviter' do
it 'sends an email that includes the right things' do
Invitation.create_invitee(:service => 'email', :identifier => @email)
Devise.mailer.deliveries.first.to_s.should include("Email not displaying correctly?")
end
it 'creates a user' do
expect {
Invitation.create_invitee(:service => 'email', :identifier => @email)
}.should change(User, :count).by(1)
end
it 'sends email to the invited user' do
expect {
Invitation.create_invitee(:service => 'email', :identifier => @email)
}.should change { Devise.mailer.deliveries.size }.by(1)
end
it 'does not create an invitation' do
expect {
Invitation.create_invitee(:service => 'email', :identifier => @email)
}.should_not change(Invitation, :count)
end
end
end
describe '.resend' do
describe '.batch_invite' do
before do
aspect
user.invite_user(aspect.id, 'email', "a@a.com", "")
@invitation = user.reload.invitations_from_me.first
@emails = ['max@foo.com', 'bob@mom.com']
@opts = {:aspect => eve.aspects.first, :sender => eve, :service => 'email'}
end
it 'returns an array of invites based on the emails passed in' do
invites = Invitation.batch_invite(@emails, @opts)
invites.count.should be 2
invites.all?{|x| x.persisted?}.should be_true
end
it 'shares with people who are already on the pod and does not create an invite for them' do
Factory(:user, :email => @emails.first)
invites = nil
expect{
invites = Invitation.batch_invite(@emails, @opts)
}.to change(eve.contacts, :count).by(1)
invites.count.should be 1
end
end
describe '#resend' do
before do
@invitation = Factory(:invitation, :sender => alice, :aspect => alice.aspects.first, :service => 'email', :identifier => 'a@a.com')
end
it 'sends another email' do
lambda { @invitation.resend }.should change(Devise.mailer.deliveries, :count).by(1)
end
end
describe '#share_with!' do
before do
@new_user = Invitation.invite(:from => user, :service => 'email', :identifier => @email, :into => aspect)
acceptance_params = {:invitation_token => "abc",
:username => "user",
:email => @email,
:password => "secret",
:password_confirmation => "secret",
:person => {:profile => {:first_name => "Bob", :last_name => "Smith"}}}
@new_user.setup(acceptance_params)
@new_user.person.save
@new_user.save
@invitation = @new_user.invitations_to_me.first
end
it 'destroys the invitation' do
lambda {
@invitation.share_with!
}.should change(Invitation, :count).by(-1)
end
it 'creates a contact for the inviter and invitee' do
lambda {
@invitation.share_with!
}.should change(Contact, :count).by(2)
@invitation.resend
}.should change(Devise.mailer.deliveries, :count).by(1)
end
end
describe '#recipient_identifier' do
it 'calls email if the invitation_service is email' do
alice.invite_user(aspect.id, 'email', "a@a.com", "")
invitation = alice.reload.invitations_from_me.first
invitation.recipient_identifier.should == 'a@a.com'
email = 'abc@abc.com'
invitation = Factory(:invitation, :sender => alice, :service => 'email', :identifier => email, :aspect => alice.aspects.first)
invitation.recipient_identifier.should == email
end
it 'gets the name if the invitation_service is facebook' do
alice.services << Services::Facebook.new(:uid => "13234895")
alice.reload.services(true).first.service_users.create(:uid => "23526464", :photo_url => 'url', :name => "Remote User")
alice.invite_user(aspect.id, 'facebook', "23526464", '')
invitation = alice.reload.invitations_from_me.first
invitation.recipient_identifier.should == "Remote User"
end
it 'does not error if the facebook user is not recorded' do
alice.services << Services::Facebook.new(:uid => "13234895")
alice.reload.services(true).first.service_users.create(:uid => "23526464", :photo_url => 'url', :name => "Remote User")
alice.invite_user(aspect.id, 'facebook', "23526464", '')
alice.services.first.service_users.delete_all
invitation = alice.reload.invitations_from_me.first
invitation.recipient_identifier.should == "A Facebook user"
context 'facebook' do
before do
@uid = '23526464'
@service = "facebook"
alice.services << Services::Facebook.new(:uid => "13234895")
alice.reload.services(true).first.service_users.create(:uid => @uid, :photo_url => 'url', :name => "Remote User")
end
it 'gets the name if the invitation_service is facebook' do
invitation = Factory(:invitation, :sender => alice, :identifier => @uid, :service => @service, :aspect => alice.aspects.first)
invitation.recipient_identifier.should == "Remote User"
end
it 'does not error if the facebook user is not recorded' do
invitation = Factory(:invitation, :sender => alice, :identifier => @uid, :service => @service, :aspect => alice.aspects.first)
alice.services.first.service_users.delete_all
invitation.recipient_identifier.should == "A Facebook user"
end
end
end
end

View file

@ -4,20 +4,14 @@ describe Job::Mail::InviteUserByEmail do
before do
@sender = alice
@email = 'bob@bob.com'
@aspect_id = alice.aspects.first.id
@aspect = alice.aspects.first
@message = 'invite message'
User.stub(:find){ |id|
if id == @sender.id
@sender
else
nil
end
}
end
it 'calls invite_user with email param' do
@sender.should_receive(:invite_user).with(@aspect_id, 'email', @email, @message)
Job::Mail::InviteUserByEmail.perform(@sender.id, @email, @aspect_id, @message)
invitation = Invitation.create(:sender => @sender, :identifier => @email, :service => "email", :aspect => @aspect, :message => @message)
invitation.should_receive(:send!)
Invitation.stub(:find).and_return(invitation)
Job::Mail::InviteUserByEmail.perform(invitation.id)
end
end

View file

@ -5,17 +5,13 @@
require 'spec_helper'
describe Job::ResendInvitation do
describe '#perfom_delegate' do
describe '#perfom' do
it 'should call .resend on the object' do
user = alice
aspect = user.aspects.create(:name => "cats")
user.invite_user(aspect.id, 'email', "a@a.com", "")
invitation = user.reload.invitations_from_me.first
invite = Factory(:invitation, :service => 'email', :identifier => 'foo@bar.com')
#Notification.should_receive(:notify).with(instance_of(User), instance_of(StatusMessage), instance_of(Person))
Invitation.stub(:where).with(:id => invitation.id ).and_return([invitation])
invitation.should_receive(:resend)
Job::ResendInvitation.perform(invitation.id)
Invitation.stub(:find).and_return(invite)
invite.should_receive(:resend)
Job::ResendInvitation.perform(invite.id)
end
end
end

View file

@ -11,6 +11,15 @@ describe Person do
@person = Factory.create(:person)
end
it 'always has a profile' do
Person.new.profile.should_not be_nil
end
it 'does not save automatically' do
Person.new.persisted?.should be_false
Person.new.profile.persisted?.should be_false
end
context 'scopes' do
describe '.for_json' do
it 'does not select public keys' do
@ -144,7 +153,7 @@ describe Person do
end
end
describe 'xml' do
describe 'XML' do
before do
@xml = @person.to_xml.to_s
end

View file

@ -1,90 +0,0 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
describe User do
context "creating invites" do
before do
@aspect = eve.aspects.first
@email = "bob@bob.com"
end
it 'requires your aspect' do
lambda {
eve.invite_user(alice.aspects.first.id, "email", "maggie@example.com")
}.should raise_error ActiveRecord::RecordNotFound
end
it 'takes a service parameter' do
@invite_params = {:service => 'email'}
Invitation.should_receive(:invite).with(hash_including(@invite_params))
eve.invite_user(@aspect.id, 'email', @email)
end
it 'takes an indentifier parameter' do
@invite_params = {:identifier => @email}
Invitation.should_receive(:invite).with(hash_including(@invite_params))
eve.invite_user(@aspect.id, 'email', @email)
end
it 'calls Invitation.invite' do
Invitation.should_receive(:invite)
eve.invite_user(@aspect.id, 'email', @email)
end
it 'has an invitation' do
eve.invite_user(@aspect.id, 'email', @email).invitations_to_me.count.should == 1
end
it 'creates it with an email' do
eve.invite_user(@aspect.id, 'email', @email).email.should == @email
end
it "throws if you try to add someone you're connected to" do
connect_users(eve, @aspect, alice, alice.aspects.first)
lambda {
eve.invite_user(@aspect.id, 'email', alice.email)
}.should raise_error ActiveRecord::RecordNotUnique
end
it 'does not invite people I already invited' do
eve.invite_user(@aspect.id, 'email', "email1@example.com")
lambda {
eve.invite_user(@aspect.id, 'email', "email1@example.com")
}.should raise_error /You already invited this person/
end
end
describe "#accept_invitation!" do
before do
invite_pre = Invitation.invite(:from => eve, :service => 'email', :identifier => 'invitee@example.org', :into => eve.aspects.first).reload
@person_count = Person.count
@invited_user = invite_pre.accept_invitation!(:invitation_token => "abc",
:email => "a@a.com",
:username => "user",
:password => "secret",
:password_confirmation => "secret",
:person => {:profile => {:first_name => "Bob",
:last_name => "Smith"}} )
end
context 'after invitation acceptance' do
it 'destroys the invitations' do
@invited_user.invitations_to_me.count.should == 0
end
it "should create the person with the passed in params" do
Person.count.should == @person_count + 1
@invited_user.person.profile.first_name.should == "Bob"
end
it 'resolves incoming invitations into contact requests' do
eve.contacts.where(:person_id => @invited_user.person.id).count.should == 1
end
end
end
end

View file

@ -318,6 +318,76 @@ describe User do
end
end
describe '.find_by_invitation' do
let(:invited_user) {
inv = Factory.build(:invitation, :recipient => @recipient, :service => @type, :identifier => @identifier)
User.find_by_invitation(inv)
}
context 'send a request to an existing' do
before do
@recipient = alice
end
context 'active user' do
it 'by service' do
@type = 'facebook'
@identifier = '123456'
@recipient.services << Services::Facebook.new(:uid => @identifier)
@recipient.save
invited_user.should == @recipient
end
it 'by email' do
@type = 'email'
@identifier = alice.email
invited_user.should == @recipient
end
end
context 'invited user' do
it 'by service and identifier' do
@identifier = alice.email
@type = 'email'
invited_user.should == alice
end
end
context 'not on server (not yet invited)' do
it 'returns nil' do
@recipient = nil
@identifier = 'foo@bar.com'
@type = 'email'
invited_user.should be_nil
end
end
end
end
describe '.find_or_create_by_invitation' do
end
describe '.create_from_invitation!' do
before do
@identifier = 'max@foobar.com'
@inv = Factory.build(:invitation, :admin => true, :service => 'email', :identifier => @identifier)
@user = User.create_from_invitation!(@inv)
end
it 'creates a persisted user' do
@user.should be_persisted
end
it 'sets the email if the service is email' do
@user.email.should == @inv.identifier
end
end
describe 'update_user_preferences' do
before do
@pref_count = UserPreference::VALID_EMAIL_TYPES.count
@ -484,14 +554,14 @@ describe User do
describe '#destroy' do
it 'removes invitations from the user' do
alice.invite_user alice.aspects.first.id, 'email', 'blah@blah.blah'
Factory(:invitation, :sender => alice)
lambda {
alice.destroy
}.should change {alice.invitations_from_me(true).count }.by(-1)
end
it 'removes invitations to the user' do
Invitation.create(:sender_id => eve.id, :recipient_id => alice.id, :aspect_id => eve.aspects.first.id)
Invitation.create!(:sender => eve, :recipient => alice, :identifier => alice.email, :aspect => eve.aspects.first)
lambda {
alice.destroy
}.should change {alice.invitations_to_me(true).count }.by(-1)
@ -810,6 +880,52 @@ describe User do
end
end
describe "#accept_invitation!" do
before do
fantasy_resque do
@invitation = Factory.create(:invitation, :sender => eve, :identifier => 'invitee@example.org', :aspect => eve.aspects.first)
end
@invitation.reload
@form_params = {:invitation_token => "abc",
:email => "a@a.com",
:username => "user",
:password => "secret",
:password_confirmation => "secret",
:person => {:profile => {:first_name => "Bob",
:last_name => "Smith"}}}
end
context 'after invitation acceptance' do
it 'destroys the invitations' do
user = @invitation.recipient.accept_invitation!(@form_params)
user.invitations_to_me.count.should == 0
end
it "should create the person with the passed in params" do
lambda {
@invitation.recipient.accept_invitation!(@form_params)
}.should change(Person, :count).by(1)
end
it 'resolves incoming invitations into contact requests' do
user = @invitation.recipient.accept_invitation!(@form_params)
eve.contacts.where(:person_id => user.person.id).count.should == 1
end
end
context 'from an admin' do
it 'should work' do
i = nil
fantasy_resque do
i = Invitation.create!(:admin => true, :service => 'email', :identifier => "new_invitee@example.com")
end
i.reload
i.recipient.accept_invitation!(@form_params)
end
end
end
describe '#retract' do
before do
@retraction = mock