Merge branch 'invite-refactor' note: this requires you to migrate your
database
This commit is contained in:
commit
57ee4cd8a9
25 changed files with 592 additions and 615 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- @invs = @resource.invitations_to_me
|
||||
-if @invs.count > 0
|
||||
-unless @invs.first.admin?
|
||||
!!!
|
||||
%html
|
||||
%head
|
||||
|
|
|
|||
17
db/migrate/20110816061820_add_fields_to_invitations.rb
Normal file
17
db/migrate/20110816061820_add_fields_to_invitations.rb
Normal 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
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue