Merge pull request #6976 from SuperTux88/cleanup-invitations
Cleanup invitations
This commit is contained in:
commit
b2fa3357eb
22 changed files with 344 additions and 601 deletions
|
|
@ -138,6 +138,7 @@ The command will report queues that still have jobs and launch sidekiq process f
|
||||||
* Remove some unused routes [#6781](https://github.com/diaspora/diaspora/pull/6781)
|
* Remove some unused routes [#6781](https://github.com/diaspora/diaspora/pull/6781)
|
||||||
* Consolidate sidekiq queues [#6950](https://github.com/diaspora/diaspora/pull/6950)
|
* Consolidate sidekiq queues [#6950](https://github.com/diaspora/diaspora/pull/6950)
|
||||||
* Don't re-render the whole comment stream when adding comments [#6406](https://github.com/diaspora/diaspora/pull/6406)
|
* Don't re-render the whole comment stream when adding comments [#6406](https://github.com/diaspora/diaspora/pull/6406)
|
||||||
|
* Drop legacy invitation system [#6976](https://github.com/diaspora/diaspora/pull/6976)
|
||||||
|
|
||||||
## Bug fixes
|
## Bug fixes
|
||||||
* Destroy Participation when removing interactions with a post [#5852](https://github.com/diaspora/diaspora/pull/5852)
|
* Destroy Participation when removing interactions with a post [#5852](https://github.com/diaspora/diaspora/pull/5852)
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class InvitationsController < ApplicationController
|
class InvitationsController < ApplicationController
|
||||||
|
before_action :authenticate_user!
|
||||||
before_action :authenticate_user!, :only => [:new, :create]
|
before_action :check_invitations_available!, only: :create
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@invite_code = current_user.invitation_code
|
@invite_code = current_user.invitation_code
|
||||||
|
|
@ -14,79 +14,50 @@ class InvitationsController < ApplicationController
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
render 'invitations/new', layout: false
|
render "invitations/new", layout: false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# this is for legacy invites. We try to look the person who sent them the
|
|
||||||
# invite, and use their new invite code
|
|
||||||
# owe will be removing this eventually
|
|
||||||
# @depreciated
|
|
||||||
def edit
|
|
||||||
user = User.find_by_invitation_token(params[:invitation_token])
|
|
||||||
invitation_code = user.ugly_accept_invitation_code
|
|
||||||
redirect_to invite_code_path(invitation_code)
|
|
||||||
end
|
|
||||||
|
|
||||||
def email
|
|
||||||
@invitation_code =
|
|
||||||
if params[:invitation_token]
|
|
||||||
# this is for legacy invites.
|
|
||||||
user = User.find_by_invitation_token(params[:invitation_token])
|
|
||||||
|
|
||||||
user.ugly_accept_invitation_code if user
|
|
||||||
else
|
|
||||||
params[:invitation_code]
|
|
||||||
end
|
|
||||||
@inviter = user || InvitationCode.where(id: params[:invitation_code]).first.try(:user)
|
|
||||||
if @invitation_code.present?
|
|
||||||
render 'notifier/invite', :layout => false
|
|
||||||
else
|
|
||||||
flash[:error] = t('invitations.check_token.not_found')
|
|
||||||
|
|
||||||
redirect_to root_url
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
def create
|
||||||
emails = inviter_params[:emails].split(',').map(&:strip).uniq
|
emails = inviter_params[:emails].split(",").map(&:strip).uniq
|
||||||
|
|
||||||
valid_emails, invalid_emails = emails.partition { |email| valid_email?(email) }
|
valid_emails, invalid_emails = emails.partition {|email| valid_email?(email) }
|
||||||
|
|
||||||
session[:valid_email_invites] = valid_emails
|
session[:valid_email_invites] = valid_emails
|
||||||
session[:invalid_email_invites] = invalid_emails
|
session[:invalid_email_invites] = invalid_emails
|
||||||
|
|
||||||
unless valid_emails.empty?
|
unless valid_emails.empty?
|
||||||
Workers::Mail::InviteEmail.perform_async(valid_emails.join(','),
|
Workers::Mail::InviteEmail.perform_async(valid_emails.join(","), current_user.id, inviter_params)
|
||||||
current_user.id,
|
|
||||||
inviter_params)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if emails.empty?
|
if emails.empty?
|
||||||
flash[:error] = t('invitations.create.empty')
|
flash[:error] = t("invitations.create.empty")
|
||||||
elsif invalid_emails.empty?
|
elsif invalid_emails.empty?
|
||||||
flash[:notice] = t('invitations.create.sent', :emails => valid_emails.join(', '))
|
flash[:notice] = t("invitations.create.sent", emails: valid_emails.join(", "))
|
||||||
elsif valid_emails.empty?
|
elsif valid_emails.empty?
|
||||||
flash[:error] = t('invitations.create.rejected') + invalid_emails.join(', ')
|
flash[:error] = t("invitations.create.rejected", emails: invalid_emails.join(", "))
|
||||||
else
|
else
|
||||||
flash[:error] = t('invitations.create.sent', :emails => valid_emails.join(', '))
|
flash[:error] = t("invitations.create.sent", emails: valid_emails.join(", ")) + ". " +
|
||||||
flash[:error] << '. '
|
t("invitations.create.rejected", emails: invalid_emails.join(", "))
|
||||||
flash[:error] << t('invitations.create.rejected') + invalid_emails.join(', ')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :back
|
redirect_to :back
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_if_invites_open
|
|
||||||
unless AppConfig.settings.invitations.open?
|
|
||||||
flash[:error] = I18n.t 'invitations.create.no_more'
|
|
||||||
|
|
||||||
redirect_to :back
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def check_invitations_available!
|
||||||
|
return true if AppConfig.settings.enable_registrations? || current_user.invitation_code.can_be_used?
|
||||||
|
|
||||||
|
flash[:error] = if AppConfig.settings.invitations.open?
|
||||||
|
t("invitations.create.no_more")
|
||||||
|
else
|
||||||
|
t("invitations.create.closed")
|
||||||
|
end
|
||||||
|
redirect_to :back
|
||||||
|
end
|
||||||
|
|
||||||
def valid_email?(email)
|
def valid_email?(email)
|
||||||
User.email_regexp.match(email).present?
|
User.email_regexp.match(email).present?
|
||||||
end
|
end
|
||||||
|
|
@ -94,9 +65,9 @@ class InvitationsController < ApplicationController
|
||||||
def html_safe_string_from_session_array(key)
|
def html_safe_string_from_session_array(key)
|
||||||
return "" unless session[key].present?
|
return "" unless session[key].present?
|
||||||
return "" unless session[key].respond_to?(:join)
|
return "" unless session[key].respond_to?(:join)
|
||||||
value = session[key].join(', ').html_safe
|
value = session[key].join(", ").html_safe
|
||||||
session[key] = nil
|
session[key] = nil
|
||||||
return value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
def inviter_params
|
def inviter_params
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class RegistrationsController < Devise::RegistrationsController
|
class RegistrationsController < Devise::RegistrationsController
|
||||||
before_action :check_registrations_open_or_valid_invite!, :check_valid_invite!
|
before_action :check_registrations_open_or_valid_invite!
|
||||||
|
|
||||||
layout ->(c) { request.format == :mobile ? "application" : "with_header" }, :only => [:new]
|
layout -> { request.format == :mobile ? "application" : "with_header" }
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@user = User.build(user_params)
|
@user = User.build(user_params)
|
||||||
@user.process_invite_acceptence(invite) if invite.present?
|
|
||||||
|
|
||||||
if @user.sign_up
|
if @user.sign_up
|
||||||
flash[:notice] = I18n.t 'registrations.create.success'
|
flash[:notice] = t("registrations.create.success")
|
||||||
|
@user.process_invite_acceptence(invite) if invite.present?
|
||||||
@user.seed_aspects
|
@user.seed_aspects
|
||||||
@user.send_welcome_message
|
@user.send_welcome_message
|
||||||
sign_in_and_redirect(:user, @user)
|
sign_in_and_redirect(:user, @user)
|
||||||
|
|
@ -22,40 +22,30 @@ class RegistrationsController < Devise::RegistrationsController
|
||||||
|
|
||||||
flash.now[:error] = @user.errors.full_messages.join(" - ")
|
flash.now[:error] = @user.errors.full_messages.join(" - ")
|
||||||
logger.info "event=registration status=failure errors='#{@user.errors.full_messages.join(', ')}'"
|
logger.info "event=registration status=failure errors='#{@user.errors.full_messages.join(', ')}'"
|
||||||
render action: "new", layout: request.format == :mobile ? "application" : "with_header"
|
render action: "new"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_valid_invite!
|
|
||||||
return true if AppConfig.settings.enable_registrations? #this sucks
|
|
||||||
return true if invite && invite.can_be_used?
|
|
||||||
flash[:error] = t('registrations.invalid_invite')
|
|
||||||
redirect_to new_user_session_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_registrations_open_or_valid_invite!
|
def check_registrations_open_or_valid_invite!
|
||||||
return true if invite.present?
|
return true if AppConfig.settings.enable_registrations? || invite.try(:can_be_used?)
|
||||||
unless AppConfig.settings.enable_registrations?
|
|
||||||
flash[:error] = t('registrations.closed')
|
flash[:error] = params[:invite] ? t("registrations.invalid_invite") : t("registrations.closed")
|
||||||
redirect_to new_user_session_path
|
redirect_to new_user_session_path
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def invite
|
def invite
|
||||||
if params[:invite].present?
|
@invite ||= InvitationCode.find_by_token(params[:invite][:token]) if params[:invite].present?
|
||||||
@invite ||= InvitationCode.find_by_token(params[:invite][:token])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
helper_method :invite
|
helper_method :invite
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
params.require(:user).permit(:username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail, :invitation_service, :invitation_identifier, :show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id, :remember_me, :captcha, :captcha_key)
|
params.require(:user).permit(
|
||||||
|
:username, :email, :getting_started, :password, :password_confirmation, :language, :disable_mail,
|
||||||
|
:show_community_spotlight_in_stream, :auto_follow_back, :auto_follow_back_aspect_id,
|
||||||
|
:remember_me, :captcha, :captcha_key
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
|
||||||
# the COPYRIGHT file.
|
|
||||||
|
|
||||||
#TODO: kill me
|
|
||||||
class Invitation < ActiveRecord::Base
|
|
||||||
|
|
||||||
belongs_to :sender, :class_name => 'User'
|
|
||||||
belongs_to :recipient, :class_name => 'User'
|
|
||||||
belongs_to :aspect
|
|
||||||
|
|
||||||
before_validation :set_email_as_default_service
|
|
||||||
|
|
||||||
# before_create :share_with_exsisting_user, :if => :recipient_id?
|
|
||||||
validates :identifier, :presence => true
|
|
||||||
validates :service, :presence => true
|
|
||||||
validate :valid_identifier?
|
|
||||||
validate :recipient_not_on_pod?
|
|
||||||
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?
|
|
||||||
|
|
||||||
|
|
||||||
# @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 optsnes 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
|
|
||||||
users_on_pod.each{|u| opts[:sender].share_with(u.person, opts[:aspect])}
|
|
||||||
|
|
||||||
emails.map! do |e|
|
|
||||||
user = users_on_pod.find{|u| u.email == e}
|
|
||||||
Invitation.create(opts.merge(:identifier => e, :recipient => user))
|
|
||||||
end
|
|
||||||
emails
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Downcases the incoming service identifier and assigns it
|
|
||||||
#
|
|
||||||
# @param ident [String] Service identifier
|
|
||||||
# @see super
|
|
||||||
def identifier=(ident)
|
|
||||||
ident.downcase! if ident
|
|
||||||
super
|
|
||||||
end
|
|
||||||
|
|
||||||
# Determine if we want to skip emailing the recipient.
|
|
||||||
#
|
|
||||||
# @return [Boolean]
|
|
||||||
# @return [void]
|
|
||||||
def skip_email?
|
|
||||||
!email_like_identifer
|
|
||||||
end
|
|
||||||
|
|
||||||
# Find or create user, and send that resultant User an
|
|
||||||
# invitation.
|
|
||||||
#
|
|
||||||
# @return [Invitation] self
|
|
||||||
def send!
|
|
||||||
if email_like_identifer
|
|
||||||
EmailInviter.new(self.identifier, sender).send!
|
|
||||||
else
|
|
||||||
puts "broken facebook invitation_token"
|
|
||||||
end
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# converts a personal invitation to an admin invite
|
|
||||||
# used in account deletion
|
|
||||||
# @return [Invitation] self
|
|
||||||
def convert_to_admin!
|
|
||||||
self.admin = true
|
|
||||||
self.sender = nil
|
|
||||||
self.aspect = nil
|
|
||||||
self.save
|
|
||||||
self
|
|
||||||
end
|
|
||||||
# @return [Invitation] self
|
|
||||||
def resend
|
|
||||||
self.send!
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [String]
|
|
||||||
def recipient_identifier
|
|
||||||
case self.service
|
|
||||||
when 'email'
|
|
||||||
self.identifier
|
|
||||||
when'facebook'
|
|
||||||
I18n.t('invitations.a_facebook_user')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [String]
|
|
||||||
def email_like_identifer
|
|
||||||
case self.service
|
|
||||||
when 'email'
|
|
||||||
self.identifier
|
|
||||||
when 'facebook'
|
|
||||||
false
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def recipient_not_on_pod?
|
|
||||||
return true if self.recipient.nil?
|
|
||||||
if self.recipient.username?
|
|
||||||
errors[:recipient] << "The user '#{self.identifier}' (#{self.recipient.diaspora_handle}) is already on this pod, so we sent them a share request"
|
|
||||||
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
|
|
||||||
|
|
@ -12,7 +12,7 @@ class InvitationCode < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_be_used?
|
def can_be_used?
|
||||||
self.count > 0
|
count > 0 && AppConfig.settings.invitations.open?
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_invites!
|
def add_invites!
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class User < ActiveRecord::Base
|
||||||
scope :daily_actives, ->(time = Time.now) { logged_in_since(time - 1.day) }
|
scope :daily_actives, ->(time = Time.now) { logged_in_since(time - 1.day) }
|
||||||
scope :yearly_actives, ->(time = Time.now) { logged_in_since(time - 1.year) }
|
scope :yearly_actives, ->(time = Time.now) { logged_in_since(time - 1.year) }
|
||||||
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
|
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
|
||||||
scope :active, -> { joins(:person).where(people: {closed_account: false}).where.not(username: nil) }
|
scope :active, -> { joins(:person).where(people: {closed_account: false}) }
|
||||||
|
|
||||||
devise :token_authenticatable, :database_authenticatable, :registerable,
|
devise :token_authenticatable, :database_authenticatable, :registerable,
|
||||||
:recoverable, :rememberable, :trackable, :validatable,
|
:recoverable, :rememberable, :trackable, :validatable,
|
||||||
|
|
@ -34,7 +34,7 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
validate :unconfirmed_email_quasiuniqueness
|
validate :unconfirmed_email_quasiuniqueness
|
||||||
|
|
||||||
validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?}
|
validates :person, presence: true
|
||||||
validates_associated :person
|
validates_associated :person
|
||||||
validate :no_person_with_same_username
|
validate :no_person_with_same_username
|
||||||
|
|
||||||
|
|
@ -48,8 +48,6 @@ class User < ActiveRecord::Base
|
||||||
:first_name, :last_name, :gender, :participations, to: :person
|
:first_name, :last_name, :gender, :participations, to: :person
|
||||||
delegate :id, :guid, to: :person, prefix: true
|
delegate :id, :guid, to: :person, prefix: true
|
||||||
|
|
||||||
has_many :invitations_from_me, :class_name => 'Invitation', :foreign_key => :sender_id
|
|
||||||
has_many :invitations_to_me, :class_name => 'Invitation', :foreign_key => :recipient_id
|
|
||||||
has_many :aspects, -> { order('order_id ASC') }
|
has_many :aspects, -> { order('order_id ASC') }
|
||||||
|
|
||||||
belongs_to :auto_follow_back_aspect, :class_name => 'Aspect'
|
belongs_to :auto_follow_back_aspect, :class_name => 'Aspect'
|
||||||
|
|
@ -99,21 +97,11 @@ class User < ActiveRecord::Base
|
||||||
ConversationVisibility.where(person_id: self.person_id).sum(:unread)
|
ConversationVisibility.where(person_id: self.person_id).sum(:unread)
|
||||||
end
|
end
|
||||||
|
|
||||||
#@deprecated
|
|
||||||
def ugly_accept_invitation_code
|
|
||||||
begin
|
|
||||||
self.invitations_to_me.first.sender.invitation_code
|
|
||||||
rescue Exception => e
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_invite_acceptence(invite)
|
def process_invite_acceptence(invite)
|
||||||
self.invited_by = invite.user
|
self.invited_by = invite.user
|
||||||
invite.use!
|
invite.use! unless AppConfig.settings.enable_registrations?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def invitation_code
|
def invitation_code
|
||||||
InvitationCode.find_or_create_by(user_id: self.id)
|
InvitationCode.find_or_create_by(user_id: self.id)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#paste_link
|
#paste_link
|
||||||
= t('.paste_link')
|
= t('.paste_link')
|
||||||
%span#codes_left
|
%span#codes_left
|
||||||
= '(' + t('.codes_left', count: @invite_code.count) + ')'
|
= "(" + t(".codes_left", count: @invite_code.count) + ")" unless AppConfig.settings.enable_registrations?
|
||||||
.form-horizontal
|
.form-horizontal
|
||||||
.control-group
|
.control-group
|
||||||
= invite_link(@invite_code)
|
= invite_link(@invite_code)
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
= text_field_tag 'email_inviter[emails]', @invalid_emails, title: t('.comma_separated_plz'),
|
= text_field_tag 'email_inviter[emails]', @invalid_emails, title: t('.comma_separated_plz'),
|
||||||
placeholder: 'foo@bar.com, max@foo.com...', class: "form-control"
|
placeholder: 'foo@bar.com, max@foo.com...', class: "form-control"
|
||||||
#already_sent
|
#already_sent
|
||||||
= t('invitations.create.note_already_sent', emails: @valid_emails) unless @valid_emails.empty?
|
= t("invitations.create.note_already_sent", emails: @valid_emails) unless @valid_emails.empty?
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
%label.col-sm-2.control-label{ for: 'email_inviter_locale' }
|
%label.col-sm-2.control-label{ for: 'email_inviter_locale' }
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
|
||||||
# the COPYRIGHT file.
|
|
||||||
|
|
||||||
|
|
||||||
module Workers
|
|
||||||
class ResendInvitation < Base
|
|
||||||
sidekiq_options queue: :low
|
|
||||||
|
|
||||||
def perform(invitation_id)
|
|
||||||
inv = Invitation.find(invitation_id)
|
|
||||||
inv.resend
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -556,10 +556,11 @@ en:
|
||||||
invitations:
|
invitations:
|
||||||
create:
|
create:
|
||||||
sent: "Invitations have been sent to: %{emails}"
|
sent: "Invitations have been sent to: %{emails}"
|
||||||
rejected: "The following email addresses had problems: "
|
rejected: "The following email addresses had problems: %{emails}"
|
||||||
no_more: "You have no more invitations."
|
no_more: "You have no more invitations."
|
||||||
empty: "Please enter at least one email address."
|
empty: "Please enter at least one email address."
|
||||||
note_already_sent: "Invitations have already been sent to: %{emails}"
|
note_already_sent: "Invitations have already been sent to: %{emails}"
|
||||||
|
closed: "Invitations are closed on this diaspora* pod."
|
||||||
new:
|
new:
|
||||||
language: "Language"
|
language: "Language"
|
||||||
invite_someone_to_join: "Invite someone to join diaspora*!"
|
invite_someone_to_join: "Invite someone to join diaspora*!"
|
||||||
|
|
@ -571,9 +572,6 @@ en:
|
||||||
zero: "No invites left on this code"
|
zero: "No invites left on this code"
|
||||||
one: "One invite left on this code"
|
one: "One invite left on this code"
|
||||||
other: "%{count} invites left on this code"
|
other: "%{count} invites left on this code"
|
||||||
check_token:
|
|
||||||
not_found: "Invitation token not found"
|
|
||||||
a_facebook_user: "A Facebook user"
|
|
||||||
|
|
||||||
layouts:
|
layouts:
|
||||||
header:
|
header:
|
||||||
|
|
|
||||||
|
|
@ -122,11 +122,8 @@ Diaspora::Application.routes.draw do
|
||||||
post "/users" => "registrations#create", :as => :user_registration
|
post "/users" => "registrations#create", :as => :user_registration
|
||||||
end
|
end
|
||||||
|
|
||||||
#legacy routes to support old invite routes
|
get "users/invitations" => "invitations#new", :as => "new_user_invitation"
|
||||||
get 'users/invitation/accept' => 'invitations#edit'
|
post "users/invitations" => "invitations#create", :as => "user_invitation"
|
||||||
get 'invitations/email' => 'invitations#email', :as => 'invite_email'
|
|
||||||
get 'users/invitations' => 'invitations#new', :as => 'new_user_invitation'
|
|
||||||
post 'users/invitations' => 'invitations#create', :as => 'user_invitation'
|
|
||||||
|
|
||||||
get 'login' => redirect('/users/sign_in')
|
get 'login' => redirect('/users/sign_in')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
class CleanupInvitationColumnsFromUsers < ActiveRecord::Migration
|
||||||
|
class InvitationCode < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
|
||||||
|
class User < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
|
||||||
|
def change
|
||||||
|
remove_index :users, column: %i(invitation_service invitation_identifier),
|
||||||
|
name: :index_users_on_invitation_service_and_invitation_identifier,
|
||||||
|
unique: true, length: {invitation_service: 64}
|
||||||
|
remove_index :users, column: :invitation_token, name: :index_users_on_invitation_token
|
||||||
|
remove_index :users, column: :email, name: :index_users_on_email, length: 191
|
||||||
|
|
||||||
|
username_not_null
|
||||||
|
|
||||||
|
remove_column :users, :invitation_token, :string, limit: 60
|
||||||
|
remove_column :users, :invitation_sent_at, :datetime
|
||||||
|
remove_column :users, :invitation_service, :string, limit: 127
|
||||||
|
remove_column :users, :invitation_identifier, :string, limit: 127
|
||||||
|
remove_column :users, :invitation_limit, :integer
|
||||||
|
remove_column :users, :invited_by_type, :string
|
||||||
|
|
||||||
|
add_index :users, :email, name: :index_users_on_email, unique: true, length: 191
|
||||||
|
|
||||||
|
cleanup_invitations
|
||||||
|
end
|
||||||
|
|
||||||
|
def username_not_null
|
||||||
|
reversible do |dir|
|
||||||
|
dir.up do
|
||||||
|
User.delete_all(username: nil)
|
||||||
|
change_column :users, :username, :string, null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
dir.down do
|
||||||
|
change_column :users, :username, :string, null: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_invitations
|
||||||
|
reversible do |dir|
|
||||||
|
dir.up do
|
||||||
|
drop_table :invitations
|
||||||
|
|
||||||
|
# reset negative invitation counters
|
||||||
|
new_counter = AppConfig.settings.enable_registrations? ? AppConfig["settings.invitations.count"] : 0
|
||||||
|
InvitationCode.where("count < 0").update_all(count: new_counter)
|
||||||
|
end
|
||||||
|
|
||||||
|
dir.down do
|
||||||
|
create_invitations_table
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_invitations_table
|
||||||
|
# rubocop:disable Style/ExtraSpacing
|
||||||
|
create_table :invitations, force: :cascade do |t|
|
||||||
|
t.text :message, limit: 65_535
|
||||||
|
t.integer :sender_id, limit: 4
|
||||||
|
t.integer :recipient_id, limit: 4
|
||||||
|
t.integer :aspect_id, limit: 4
|
||||||
|
t.datetime :created_at, null: false
|
||||||
|
t.datetime :updated_at, null: false
|
||||||
|
t.string :service, limit: 255
|
||||||
|
t.string :identifier, limit: 255
|
||||||
|
t.boolean :admin, default: false
|
||||||
|
t.string :language, limit: 255, default: "en"
|
||||||
|
end
|
||||||
|
# rubocop:enable Style/ExtraSpacing
|
||||||
|
|
||||||
|
add_index :invitations, :aspect_id, name: :index_invitations_on_aspect_id, using: :btree
|
||||||
|
add_index :invitations, :recipient_id, name: :index_invitations_on_recipient_id, using: :btree
|
||||||
|
add_index :invitations, :sender_id, name: :index_invitations_on_sender_id, using: :btree
|
||||||
|
|
||||||
|
add_foreign_key :invitations, :users, column: :recipient_id, name: :invitations_recipient_id_fk, on_delete: :cascade
|
||||||
|
add_foreign_key :invitations, :users, column: :sender_id, name: :invitations_sender_id_fk, on_delete: :cascade
|
||||||
|
end
|
||||||
|
end
|
||||||
33
db/schema.rb
33
db/schema.rb
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20160807212443) do
|
ActiveRecord::Schema.define(version: 20160810230114) do
|
||||||
|
|
||||||
create_table "account_deletions", force: :cascade do |t|
|
create_table "account_deletions", force: :cascade do |t|
|
||||||
t.string "diaspora_handle", limit: 255
|
t.string "diaspora_handle", limit: 255
|
||||||
|
|
@ -178,23 +178,6 @@ ActiveRecord::Schema.define(version: 20160807212443) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "invitations", force: :cascade do |t|
|
|
||||||
t.text "message", limit: 65535
|
|
||||||
t.integer "sender_id", limit: 4
|
|
||||||
t.integer "recipient_id", limit: 4
|
|
||||||
t.integer "aspect_id", limit: 4
|
|
||||||
t.datetime "created_at", null: false
|
|
||||||
t.datetime "updated_at", null: false
|
|
||||||
t.string "service", limit: 255
|
|
||||||
t.string "identifier", limit: 255
|
|
||||||
t.boolean "admin", default: false
|
|
||||||
t.string "language", limit: 255, default: "en"
|
|
||||||
end
|
|
||||||
|
|
||||||
add_index "invitations", ["aspect_id"], name: "index_invitations_on_aspect_id", using: :btree
|
|
||||||
add_index "invitations", ["recipient_id"], name: "index_invitations_on_recipient_id", using: :btree
|
|
||||||
add_index "invitations", ["sender_id"], name: "index_invitations_on_sender_id", using: :btree
|
|
||||||
|
|
||||||
create_table "like_signatures", id: false, force: :cascade do |t|
|
create_table "like_signatures", id: false, force: :cascade do |t|
|
||||||
t.integer "like_id", limit: 4, null: false
|
t.integer "like_id", limit: 4, null: false
|
||||||
t.text "author_signature", limit: 65535, null: false
|
t.text "author_signature", limit: 65535, null: false
|
||||||
|
|
@ -624,15 +607,13 @@ ActiveRecord::Schema.define(version: 20160807212443) do
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "users", force: :cascade do |t|
|
create_table "users", force: :cascade do |t|
|
||||||
t.string "username", limit: 255
|
t.string "username", limit: 255, null: false
|
||||||
t.text "serialized_private_key", limit: 65535
|
t.text "serialized_private_key", limit: 65535
|
||||||
t.boolean "getting_started", default: true, null: false
|
t.boolean "getting_started", default: true, null: false
|
||||||
t.boolean "disable_mail", default: false, null: false
|
t.boolean "disable_mail", default: false, null: false
|
||||||
t.string "language", limit: 255
|
t.string "language", limit: 255
|
||||||
t.string "email", limit: 255, default: "", null: false
|
t.string "email", limit: 255, default: "", null: false
|
||||||
t.string "encrypted_password", limit: 255, default: "", null: false
|
t.string "encrypted_password", limit: 255, default: "", null: false
|
||||||
t.string "invitation_token", limit: 60
|
|
||||||
t.datetime "invitation_sent_at"
|
|
||||||
t.string "reset_password_token", limit: 255
|
t.string "reset_password_token", limit: 255
|
||||||
t.datetime "remember_created_at"
|
t.datetime "remember_created_at"
|
||||||
t.integer "sign_in_count", limit: 4, default: 0
|
t.integer "sign_in_count", limit: 4, default: 0
|
||||||
|
|
@ -642,11 +623,7 @@ ActiveRecord::Schema.define(version: 20160807212443) do
|
||||||
t.string "last_sign_in_ip", limit: 255
|
t.string "last_sign_in_ip", limit: 255
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.string "invitation_service", limit: 127
|
|
||||||
t.string "invitation_identifier", limit: 127
|
|
||||||
t.integer "invitation_limit", limit: 4
|
|
||||||
t.integer "invited_by_id", limit: 4
|
t.integer "invited_by_id", limit: 4
|
||||||
t.string "invited_by_type", limit: 255
|
|
||||||
t.string "authentication_token", limit: 30
|
t.string "authentication_token", limit: 30
|
||||||
t.string "unconfirmed_email", limit: 255
|
t.string "unconfirmed_email", limit: 255
|
||||||
t.string "confirm_email_token", limit: 30
|
t.string "confirm_email_token", limit: 30
|
||||||
|
|
@ -669,9 +646,7 @@ ActiveRecord::Schema.define(version: 20160807212443) do
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
|
add_index "users", ["authentication_token"], name: "index_users_on_authentication_token", unique: true, using: :btree
|
||||||
add_index "users", ["email"], name: "index_users_on_email", length: {"email"=>191}, using: :btree
|
add_index "users", ["email"], name: "index_users_on_email", unique: true, length: {"email"=>191}, using: :btree
|
||||||
add_index "users", ["invitation_service", "invitation_identifier"], name: "index_users_on_invitation_service_and_invitation_identifier", unique: true, length: {"invitation_service"=>64, "invitation_identifier"=>nil}, using: :btree
|
|
||||||
add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", using: :btree
|
|
||||||
add_index "users", ["username"], name: "index_users_on_username", unique: true, length: {"username"=>191}, using: :btree
|
add_index "users", ["username"], name: "index_users_on_username", unique: true, length: {"username"=>191}, using: :btree
|
||||||
|
|
||||||
add_foreign_key "aspect_memberships", "aspects", name: "aspect_memberships_aspect_id_fk", on_delete: :cascade
|
add_foreign_key "aspect_memberships", "aspects", name: "aspect_memberships_aspect_id_fk", on_delete: :cascade
|
||||||
|
|
@ -687,8 +662,6 @@ ActiveRecord::Schema.define(version: 20160807212443) do
|
||||||
add_foreign_key "conversation_visibilities", "people", name: "conversation_visibilities_person_id_fk", on_delete: :cascade
|
add_foreign_key "conversation_visibilities", "people", name: "conversation_visibilities_person_id_fk", on_delete: :cascade
|
||||||
add_foreign_key "conversations", "people", column: "author_id", name: "conversations_author_id_fk", on_delete: :cascade
|
add_foreign_key "conversations", "people", column: "author_id", name: "conversations_author_id_fk", on_delete: :cascade
|
||||||
add_foreign_key "id_tokens", "authorizations"
|
add_foreign_key "id_tokens", "authorizations"
|
||||||
add_foreign_key "invitations", "users", column: "recipient_id", name: "invitations_recipient_id_fk", on_delete: :cascade
|
|
||||||
add_foreign_key "invitations", "users", column: "sender_id", name: "invitations_sender_id_fk", on_delete: :cascade
|
|
||||||
add_foreign_key "like_signatures", "likes", name: "like_signatures_like_id_fk", on_delete: :cascade
|
add_foreign_key "like_signatures", "likes", name: "like_signatures_like_id_fk", on_delete: :cascade
|
||||||
add_foreign_key "like_signatures", "signature_orders", name: "like_signatures_signature_orders_id_fk"
|
add_foreign_key "like_signatures", "signature_orders", name: "like_signatures_signature_orders_id_fk"
|
||||||
add_foreign_key "likes", "people", column: "author_id", name: "likes_author_id_fk", on_delete: :cascade
|
add_foreign_key "likes", "people", column: "author_id", name: "likes_author_id_fk", on_delete: :cascade
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ Given /^I have been invited by an admin$/ do
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^I have been invited by "([^\"]+)"$/ do |email|
|
Given /^I have been invited by "([^\"]+)"$/ do |email|
|
||||||
|
AppConfig.settings.enable_registrations = false
|
||||||
@inviter = User.find_by_email(email)
|
@inviter = User.find_by_email(email)
|
||||||
@inviter_invite_count = @inviter.invitation_code.count
|
@inviter_invite_count = @inviter.invitation_code.count
|
||||||
i = EmailInviter.new("new_invitee@example.com", @inviter)
|
i = EmailInviter.new("new_invitee@example.com", @inviter)
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,9 @@ Before do |scenario|
|
||||||
page.driver.headers = if scenario.source_tag_names.include? "@mobile"
|
page.driver.headers = if scenario.source_tag_names.include? "@mobile"
|
||||||
{"User-Agent" => "Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0"}
|
{"User-Agent" => "Mozilla/5.0 (Mobile; rv:18.0) Gecko/18.0 Firefox/18.0"}
|
||||||
else
|
else
|
||||||
page.driver.headers = {}
|
{}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Reset overridden settings
|
||||||
|
AppConfig.reset_dynamic!
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ class AccountDeleter
|
||||||
#user deletion methods
|
#user deletion methods
|
||||||
remove_share_visibilities_on_contacts_posts
|
remove_share_visibilities_on_contacts_posts
|
||||||
delete_standard_user_associations
|
delete_standard_user_associations
|
||||||
disassociate_invitations
|
|
||||||
disconnect_contacts
|
disconnect_contacts
|
||||||
tombstone_user
|
tombstone_user
|
||||||
end
|
end
|
||||||
|
|
@ -45,12 +44,12 @@ class AccountDeleter
|
||||||
|
|
||||||
#user deletions
|
#user deletions
|
||||||
def normal_ar_user_associates_to_delete
|
def normal_ar_user_associates_to_delete
|
||||||
%i(tag_followings invitations_to_me services aspects user_preferences
|
%i(tag_followings services aspects user_preferences
|
||||||
notifications blocks authorizations o_auth_applications pairwise_pseudonymous_identifiers)
|
notifications blocks authorizations o_auth_applications pairwise_pseudonymous_identifiers)
|
||||||
end
|
end
|
||||||
|
|
||||||
def special_ar_user_associations
|
def special_ar_user_associations
|
||||||
%i(invitations_from_me person profile contacts auto_follow_back_aspect)
|
%i(person profile contacts auto_follow_back_aspect)
|
||||||
end
|
end
|
||||||
|
|
||||||
def ignored_ar_user_associations
|
def ignored_ar_user_associations
|
||||||
|
|
@ -70,12 +69,6 @@ class AccountDeleter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def disassociate_invitations
|
|
||||||
user.invitations_from_me.each do |inv|
|
|
||||||
inv.convert_to_admin!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def disconnect_contacts
|
def disconnect_contacts
|
||||||
user.contacts.destroy_all
|
user.contacts.destroy_all
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,6 @@ class EmailInviter
|
||||||
private
|
private
|
||||||
|
|
||||||
def mail(email)
|
def mail(email)
|
||||||
Notifier.invite(email, message, inviter, invitation_code, locale).deliver_now!
|
Notifier.invite(email, message, inviter, invitation_code, locale).deliver_now
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,164 +2,142 @@
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
|
|
||||||
describe InvitationsController, :type => :controller do
|
|
||||||
|
|
||||||
before do
|
|
||||||
AppConfig.settings.invitations.open = true
|
|
||||||
@user = alice
|
|
||||||
@invite = {'email_inviter' => {'message' => "test", 'emails' => "abc@example.com"}}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
describe InvitationsController, type: :controller do
|
||||||
describe "#create" do
|
describe "#create" do
|
||||||
|
let(:referer) { "http://test.host/cats/foo" }
|
||||||
|
let(:invite_params) { {email_inviter: {emails: "abc@example.com"}} }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in @user, scope: :user
|
sign_in alice, scope: :user
|
||||||
allow(@controller).to receive(:current_user).and_return(@user)
|
request.env["HTTP_REFERER"] = referer
|
||||||
@referer = 'http://test.host/cats/foo'
|
|
||||||
request.env["HTTP_REFERER"] = @referer
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context "no emails" do
|
context "no emails" do
|
||||||
before do
|
let(:invite_params) { {email_inviter: {emails: ""}} }
|
||||||
@invite = {'email_inviter' => {'message' => "test", 'emails' => ""}}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not create an EmailInviter' do
|
it "does not create an EmailInviter" do
|
||||||
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
|
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns to the previous page' do
|
it "returns to the previous page" do
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
expect(response).to redirect_to @referer
|
expect(response).to redirect_to referer
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'flashes an error' do
|
it "flashes an error" do
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
expect(flash[:error]).to eq(I18n.t("invitations.create.empty"))
|
expect(flash[:error]).to eq(I18n.t("invitations.create.empty"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'only valid emails' do
|
context "only valid emails" do
|
||||||
before do
|
let(:emails) { "mbs@gmail.com" }
|
||||||
@emails = 'mbs@gmail.com'
|
let(:invite_params) { {email_inviter: {emails: emails}} }
|
||||||
@invite = {'email_inviter' => {'message' => "test", 'emails' => @emails}}
|
|
||||||
|
it "creates an InviteEmail worker" do
|
||||||
|
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(
|
||||||
|
emails, alice.id, invite_params[:email_inviter]
|
||||||
|
)
|
||||||
|
post :create, invite_params
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates an InviteEmail worker' do
|
it "returns to the previous page on success" do
|
||||||
inviter = double(:emails => [@emails], :send! => true)
|
post :create, invite_params
|
||||||
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(@invite['email_inviter']['emails'], @user.id, @invite['email_inviter'])
|
expect(response).to redirect_to referer
|
||||||
post :create, @invite
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns to the previous page on success' do
|
it "flashes a notice" do
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
expect(response).to redirect_to @referer
|
expected = I18n.t("invitations.create.sent", emails: emails)
|
||||||
end
|
|
||||||
|
|
||||||
it 'flashes a notice' do
|
|
||||||
post :create, @invite
|
|
||||||
expected = I18n.t('invitations.create.sent', :emails => @emails.split(',').join(', '))
|
|
||||||
expect(flash[:notice]).to eq(expected)
|
expect(flash[:notice]).to eq(expected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'only invalid emails' do
|
context "only invalid emails" do
|
||||||
before do
|
let(:emails) { "invalid_email" }
|
||||||
@emails = 'invalid_email'
|
let(:invite_params) { {email_inviter: {emails: emails}} }
|
||||||
@invite = {'email_inviter' => {'message' => "test", 'emails' => @emails}}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not create an InviteEmail worker' do
|
it "does not create an InviteEmail worker" do
|
||||||
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
|
expect(Workers::Mail::InviteEmail).not_to receive(:perform_async)
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns to the previous page' do
|
it "returns to the previous page" do
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
expect(response).to redirect_to @referer
|
expect(response).to redirect_to referer
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'flashes an error' do
|
it "flashes an error" do
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
|
|
||||||
expected = I18n.t('invitations.create.rejected') + @emails.split(',').join(', ')
|
expected = I18n.t("invitations.create.rejected", emails: emails)
|
||||||
expect(flash[:error]).to eq(expected)
|
expect(flash[:error]).to eq(expected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'mixed valid and invalid emails' do
|
context "mixed valid and invalid emails" do
|
||||||
|
let(:valid_emails) { "foo@bar.com,mbs@gmail.com" }
|
||||||
|
let(:invalid_emails) { "invalid_email" }
|
||||||
|
let(:invite_params) { {email_inviter: {emails: valid_emails + "," + invalid_emails}} }
|
||||||
|
|
||||||
|
it "creates an InviteEmail worker" do
|
||||||
|
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(
|
||||||
|
valid_emails, alice.id, invite_params[:email_inviter]
|
||||||
|
)
|
||||||
|
post :create, invite_params
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns to the previous page" do
|
||||||
|
post :create, invite_params
|
||||||
|
expect(response).to redirect_to referer
|
||||||
|
end
|
||||||
|
|
||||||
|
it "flashes a notice" do
|
||||||
|
post :create, invite_params
|
||||||
|
expected = I18n.t("invitations.create.sent", emails: valid_emails.split(",").join(", ")) + ". " +
|
||||||
|
I18n.t("invitations.create.rejected", emails: invalid_emails)
|
||||||
|
expect(flash[:error]).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with registration disabled" do
|
||||||
before do
|
before do
|
||||||
@valid_emails = 'foo@bar.com,mbs@gmail.com'
|
AppConfig.settings.enable_registrations = false
|
||||||
@invalid_emails = 'invalid'
|
|
||||||
@invite = {'email_inviter' => {'message' => "test", 'emails' =>
|
|
||||||
@valid_emails + ',' + @invalid_emails}}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates an InviteEmail worker' do
|
it "displays an error if invitations are closed" do
|
||||||
inviter = double(:emails => [@emails], :send! => true)
|
|
||||||
expect(Workers::Mail::InviteEmail).to receive(:perform_async).with(@valid_emails, @user.id, @invite['email_inviter'])
|
|
||||||
post :create, @invite
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns to the previous page' do
|
|
||||||
post :create, @invite
|
|
||||||
expect(response).to redirect_to @referer
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'flashes a notice' do
|
|
||||||
post :create, @invite
|
|
||||||
expected = I18n.t('invitations.create.sent', :emails =>
|
|
||||||
@valid_emails.split(',').join(', ')) +
|
|
||||||
'. ' + I18n.t('invitations.create.rejected') +
|
|
||||||
@invalid_emails.split(',').join(', ')
|
|
||||||
expect(flash[:error]).to eq(expected)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'redirects if invitations are closed' do
|
|
||||||
AppConfig.settings.invitations.open = false
|
AppConfig.settings.invitations.open = false
|
||||||
|
|
||||||
post :create, @invite
|
post :create, invite_params
|
||||||
expect(response).to be_redirect
|
|
||||||
|
expect(flash[:error]).to eq(I18n.t("invitations.create.closed"))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "displays an error when no invitations are left" do
|
||||||
|
alice.invitation_code.update_attributes(count: 0)
|
||||||
|
|
||||||
|
post :create, invite_params
|
||||||
|
|
||||||
|
expect(flash[:error]).to eq(I18n.t("invitations.create.no_more"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#email' do
|
it "does not display an error when registration is open" do
|
||||||
|
AppConfig.settings.invitations.open = false
|
||||||
|
alice.invitation_code.update_attributes(count: 0)
|
||||||
|
|
||||||
it 'succeeds' do
|
post :create, invite_params
|
||||||
get :email, :invitation_code => "anycode"
|
|
||||||
expect(response).to be_success
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'legacy invite tokens' do
|
expect(flash[:error]).to be_nil
|
||||||
def get_email
|
|
||||||
get :email, :invitation_token => @invitation_token
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'invalid token' do
|
|
||||||
@invitation_token = "invalidtoken"
|
|
||||||
|
|
||||||
it 'redirects and flashes if the invitation token is invalid' do
|
|
||||||
get_email
|
|
||||||
|
|
||||||
expect(response).to be_redirect
|
|
||||||
expect(response).to redirect_to root_url
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'flashes an error if the invitation token is invalid' do
|
|
||||||
get_email
|
|
||||||
|
|
||||||
expect(flash[:error]).to eq(I18n.t("invitations.check_token.not_found"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#new' do
|
describe '#new' do
|
||||||
it 'renders' do
|
it 'renders' do
|
||||||
sign_in @user, scope: :user
|
sign_in alice, scope: :user
|
||||||
get :new
|
get :new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,47 +2,76 @@
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
|
|
||||||
describe RegistrationsController, type: :controller do
|
describe RegistrationsController, type: :controller do
|
||||||
before do
|
before do
|
||||||
request.env["devise.mapping"] = Devise.mappings[:user]
|
request.env["devise.mapping"] = Devise.mappings[:user]
|
||||||
@valid_params = {:user => {
|
|
||||||
:username => "jdoe",
|
|
||||||
:email => "jdoe@example.com",
|
|
||||||
:password => "password",
|
|
||||||
:password_confirmation => "password"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allow(Person).to receive(:find_or_fetch_by_identifier).and_return(FactoryGirl.create(:person))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#check_registrations_open!' do
|
let(:valid_params) {
|
||||||
|
{
|
||||||
|
user: {
|
||||||
|
username: "jdoe",
|
||||||
|
email: "jdoe@example.com",
|
||||||
|
password: "password",
|
||||||
|
password_confirmation: "password"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe "#check_registrations_open_or_valid_invite!" do
|
||||||
before do
|
before do
|
||||||
AppConfig.settings.enable_registrations = false
|
AppConfig.settings.enable_registrations = false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'redirects #new to the login page' do
|
it "redirects #new to the login page" do
|
||||||
get :new
|
get :new
|
||||||
expect(flash[:error]).to eq(I18n.t('registrations.closed'))
|
expect(flash[:error]).to eq(I18n.t("registrations.closed"))
|
||||||
expect(response).to redirect_to new_user_session_path
|
expect(response).to redirect_to new_user_session_path
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'redirects #create to the login page' do
|
it "redirects #create to the login page" do
|
||||||
post :create, @valid_params
|
post :create, valid_params
|
||||||
expect(flash[:error]).to eq(I18n.t('registrations.closed'))
|
expect(flash[:error]).to eq(I18n.t("registrations.closed"))
|
||||||
expect(response).to redirect_to new_user_session_path
|
expect(response).to redirect_to new_user_session_path
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not redirect if there is a valid invite token' do
|
it "does not redirect if there is a valid invite token" do
|
||||||
i = InvitationCode.create(:user => bob)
|
code = InvitationCode.create(user: bob)
|
||||||
get :new, :invite => {:token => i.token}
|
get :new, invite: {token: code.token}
|
||||||
expect(response).not_to be_redirect
|
expect(response).not_to be_redirect
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does redirect if there is an invalid invite token' do
|
it "does redirect if there is an invalid invite token" do
|
||||||
get :new, :invite => {:token => 'fssdfsd'}
|
get :new, invite: {token: "fssdfsd"}
|
||||||
expect(response).to be_redirect
|
expect(response).to redirect_to new_user_session_path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does redirect if there are no invites available with this code" do
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
code.update_attributes(count: 0)
|
||||||
|
|
||||||
|
get :new, invite: {token: code.token}
|
||||||
|
expect(response).to redirect_to new_user_session_path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does redirect when invitations are closed now" do
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
AppConfig.settings.invitations.open = false
|
||||||
|
|
||||||
|
get :new, invite: {token: code.token}
|
||||||
|
expect(response).to redirect_to new_user_session_path
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not redirect when the registration is open" do
|
||||||
|
AppConfig.settings.enable_registrations = true
|
||||||
|
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
code.update_attributes(count: 0)
|
||||||
|
|
||||||
|
get :new, invite: {token: code.token}
|
||||||
|
expect(response).not_to be_redirect
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -50,66 +79,95 @@ describe RegistrationsController, type: :controller do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
context "with valid parameters" do
|
context "with valid parameters" do
|
||||||
before do
|
|
||||||
AppConfig.settings.enable_registrations = true
|
|
||||||
user = FactoryGirl.build(:user)
|
|
||||||
allow(User).to receive(:build).and_return(user)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "creates a user" do
|
it "creates a user" do
|
||||||
expect {
|
expect {
|
||||||
get :create, @valid_params
|
get :create, valid_params
|
||||||
}.to change(User, :count).by(1)
|
}.to change(User, :count).by(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "assigns @user" do
|
it "assigns @user" do
|
||||||
get :create, @valid_params
|
get :create, valid_params
|
||||||
expect(assigns(:user)).to be_truthy
|
expect(assigns(:user)).to be_truthy
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets the flash" do
|
it "sets the flash" do
|
||||||
get :create, @valid_params
|
get :create, valid_params
|
||||||
expect(flash[:notice]).not_to be_blank
|
expect(flash[:notice]).not_to be_blank
|
||||||
end
|
end
|
||||||
|
|
||||||
it "redirects to the home path" do
|
it "redirects to the home path" do
|
||||||
get :create, @valid_params
|
get :create, valid_params
|
||||||
expect(response).to be_redirect
|
expect(response).to be_redirect
|
||||||
expect(response.location).to match /^#{stream_url}\??$/
|
expect(response.location).to match(/^#{getting_started_url}$/)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with invite code" do
|
||||||
|
it "reduces number of available invites when the registration is closed" do
|
||||||
|
AppConfig.settings.enable_registrations = false
|
||||||
|
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
get :create, valid_params.merge(invite: {token: code.token})
|
||||||
|
}.to change { code.reload.count }.by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't reduce number of available invites when the registration is open" do
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
get :create, valid_params.merge(invite: {token: code.token})
|
||||||
|
}.not_to change { code.reload.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "links inviter with the user" do
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
|
||||||
|
post :create, valid_params.merge(invite: {token: code.token})
|
||||||
|
|
||||||
|
expect(User.find_by(username: "jdoe").invited_by).to eq(bob)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with invalid parameters" do
|
context "with invalid parameters" do
|
||||||
before do
|
let(:invalid_params) { valid_params.deep_merge(user: {password_confirmation: "baddword"}) }
|
||||||
@invalid_params = @valid_params
|
|
||||||
@invalid_params[:user][:password_confirmation] = "baddword"
|
|
||||||
end
|
|
||||||
|
|
||||||
it "does not create a user" do
|
it "does not create a user" do
|
||||||
expect { get :create, @invalid_params }.not_to change(User, :count)
|
expect { get :create, invalid_params }.not_to change(User, :count)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not create a person" do
|
it "does not create a person" do
|
||||||
expect { get :create, @invalid_params }.not_to change(Person, :count)
|
expect { get :create, invalid_params }.not_to change(Person, :count)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "assigns @user" do
|
it "assigns @user" do
|
||||||
get :create, @invalid_params
|
get :create, invalid_params
|
||||||
expect(assigns(:user)).not_to be_nil
|
expect(assigns(:user)).not_to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it "sets the flash error" do
|
it "sets the flash error" do
|
||||||
get :create, @invalid_params
|
get :create, invalid_params
|
||||||
expect(flash[:error]).not_to be_blank
|
expect(flash[:error]).not_to be_blank
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "doesn't reduce number of available invites" do
|
||||||
|
AppConfig.settings.enable_registrations = false
|
||||||
|
|
||||||
|
code = InvitationCode.create(user: bob)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
get :create, invalid_params.merge(invite: {token: code.token})
|
||||||
|
}.not_to change { code.reload.count }
|
||||||
|
end
|
||||||
|
|
||||||
it "renders new" do
|
it "renders new" do
|
||||||
get :create, @invalid_params
|
get :create, invalid_params
|
||||||
expect(response).to render_template("registrations/new")
|
expect(response).to render_template("registrations/new")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "keeps invalid params in form" do
|
it "keeps invalid params in form" do
|
||||||
get :create, @invalid_params
|
get :create, invalid_params
|
||||||
expect(response.body).to match /jdoe@example.com/m
|
expect(response.body).to match /jdoe@example.com/m
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,18 @@ describe AccountDeleter do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#perform' do
|
describe '#perform' do
|
||||||
|
user_removal_methods = %i(
|
||||||
|
delete_standard_user_associations
|
||||||
|
remove_share_visibilities_on_contacts_posts
|
||||||
|
disconnect_contacts tombstone_user
|
||||||
|
)
|
||||||
|
|
||||||
|
person_removal_methods = %i(
|
||||||
user_removal_methods = [:delete_standard_user_associations,
|
delete_contacts_of_me
|
||||||
:disassociate_invitations,
|
delete_standard_person_associations
|
||||||
:remove_share_visibilities_on_contacts_posts,
|
tombstone_person_and_profile
|
||||||
:disconnect_contacts,
|
remove_conversation_visibilities
|
||||||
:tombstone_user]
|
)
|
||||||
|
|
||||||
person_removal_methods = [:delete_contacts_of_me,
|
|
||||||
:delete_standard_person_associations,
|
|
||||||
:tombstone_person_and_profile,
|
|
||||||
:remove_conversation_visibilities]
|
|
||||||
|
|
||||||
context "user deletion" do
|
context "user deletion" do
|
||||||
after do
|
after do
|
||||||
|
|
@ -110,15 +110,6 @@ describe AccountDeleter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#disassociate_invitations" do
|
|
||||||
it "sets invitations_from_me to be admin invitations" do
|
|
||||||
invites = [double]
|
|
||||||
allow(bob).to receive(:invitations_from_me).and_return(invites)
|
|
||||||
expect(invites.first).to receive(:convert_to_admin!)
|
|
||||||
@account_deletion.disassociate_invitations
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'person associations' do
|
context 'person associations' do
|
||||||
describe '#disconnect_contacts' do
|
describe '#disconnect_contacts' do
|
||||||
it "deletes all of user's contacts" do
|
it "deletes all of user's contacts" do
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
|
||||||
# the COPYRIGHT file.
|
|
||||||
|
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Invitation, :type => :model do
|
|
||||||
let(:user) { alice }
|
|
||||||
|
|
||||||
before do
|
|
||||||
@email = 'maggie@example.com'
|
|
||||||
Devise.mailer.deliveries = []
|
|
||||||
end
|
|
||||||
describe 'validations' do
|
|
||||||
before do
|
|
||||||
@invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => nil, :aspect => user.aspects.first, :language => "de")
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'is valid' do
|
|
||||||
expect(@invitation.sender).to eq(user)
|
|
||||||
expect(@invitation.recipient).to eq(nil)
|
|
||||||
expect(@invitation.aspect).to eq(user.aspects.first)
|
|
||||||
expect(@invitation.language).to eq("de")
|
|
||||||
expect(@invitation).to be_valid
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'ensures the sender is placing the recipient into one of his aspects' do
|
|
||||||
@invitation.aspect = FactoryGirl.build(:aspect)
|
|
||||||
expect(@invitation).not_to be_valid
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#language' do
|
|
||||||
it 'returns the correct language if the language is set' do
|
|
||||||
@invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first, :language => "de")
|
|
||||||
expect(@invitation.language).to eq("de")
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns en if no language is set' do
|
|
||||||
@invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first)
|
|
||||||
expect(@invitation.language).to eq("en")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'has a message' do
|
|
||||||
@invitation = FactoryGirl.build(:invitation, :sender => user, :recipient => eve, :aspect => user.aspects.first, :language => user.language)
|
|
||||||
@invitation.message = "!"
|
|
||||||
expect(@invitation.message).to eq("!")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
describe '.batch_invite' do
|
|
||||||
before do
|
|
||||||
@emails = ['max@foo.com', 'bob@mom.com']
|
|
||||||
@opts = {:aspect => eve.aspects.first, :sender => eve, :service => 'email', :language => eve.language}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns an array of invites based on the emails passed in' do
|
|
||||||
invites = Invitation.batch_invite(@emails, @opts)
|
|
||||||
expect(invites.count).to be 2
|
|
||||||
expect(invites.all?{|x| x.persisted?}).to be true
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'shares with people who are already on the pod' do
|
|
||||||
FactoryGirl.create(:user, :email => @emails.first)
|
|
||||||
invites = nil
|
|
||||||
expect{
|
|
||||||
invites = Invitation.batch_invite(@emails, @opts)
|
|
||||||
}.to change(eve.contacts, :count).by(1)
|
|
||||||
expect(invites.count).to be 2
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -566,20 +566,6 @@ describe User, :type => :model do
|
||||||
|
|
||||||
describe 'account deletion' do
|
describe 'account deletion' do
|
||||||
describe '#destroy' do
|
describe '#destroy' do
|
||||||
it 'removes invitations from the user' do
|
|
||||||
FactoryGirl.create(:invitation, :sender => alice)
|
|
||||||
expect {
|
|
||||||
alice.destroy
|
|
||||||
}.to change {alice.invitations_from_me(true).count }.by(-1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes invitations to the user' do
|
|
||||||
Invitation.new(:sender => eve, :recipient => alice, :identifier => alice.email, :aspect => eve.aspects.first).save(:validate => false)
|
|
||||||
expect {
|
|
||||||
alice.destroy
|
|
||||||
}.to change {alice.invitations_to_me(true).count }.by(-1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes all service connections' do
|
it 'removes all service connections' do
|
||||||
Services::Facebook.create(:access_token => 'what', :user_id => alice.id)
|
Services::Facebook.create(:access_token => 'what', :user_id => alice.id)
|
||||||
expect {
|
expect {
|
||||||
|
|
@ -960,10 +946,8 @@ describe User, :type => :model do
|
||||||
describe "#clearable_attributes" do
|
describe "#clearable_attributes" do
|
||||||
it 'returns the clearable fields' do
|
it 'returns the clearable fields' do
|
||||||
user = FactoryGirl.create :user
|
user = FactoryGirl.create :user
|
||||||
expect(user.send(:clearable_fields).sort).to eq(%w{
|
expect(user.send(:clearable_fields).sort).to eq(%w(
|
||||||
language
|
language
|
||||||
invitation_token
|
|
||||||
invitation_sent_at
|
|
||||||
reset_password_sent_at
|
reset_password_sent_at
|
||||||
reset_password_token
|
reset_password_token
|
||||||
remember_created_at
|
remember_created_at
|
||||||
|
|
@ -973,11 +957,7 @@ describe User, :type => :model do
|
||||||
current_sign_in_ip
|
current_sign_in_ip
|
||||||
hidden_shareables
|
hidden_shareables
|
||||||
last_sign_in_ip
|
last_sign_in_ip
|
||||||
invitation_service
|
|
||||||
invitation_identifier
|
|
||||||
invitation_limit
|
|
||||||
invited_by_id
|
invited_by_id
|
||||||
invited_by_type
|
|
||||||
authentication_token
|
authentication_token
|
||||||
auto_follow_back
|
auto_follow_back
|
||||||
auto_follow_back_aspect_id
|
auto_follow_back_aspect_id
|
||||||
|
|
@ -985,7 +965,7 @@ describe User, :type => :model do
|
||||||
confirm_email_token
|
confirm_email_token
|
||||||
last_seen
|
last_seen
|
||||||
color_theme
|
color_theme
|
||||||
}.sort)
|
).sort)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1110,9 +1090,6 @@ describe User, :type => :model do
|
||||||
|
|
||||||
describe "active" do
|
describe "active" do
|
||||||
before do
|
before do
|
||||||
invited_user = FactoryGirl.build(:user, username: nil)
|
|
||||||
invited_user.save(validate: false)
|
|
||||||
|
|
||||||
closed_account = FactoryGirl.create(:user)
|
closed_account = FactoryGirl.create(:user)
|
||||||
closed_account.person.lock_access!
|
closed_account.person.lock_access!
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
|
||||||
# the COPYRIGHT file.
|
|
||||||
|
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Workers::ResendInvitation do
|
|
||||||
describe '#perfom' do
|
|
||||||
it 'should call .resend on the object' do
|
|
||||||
invite = FactoryGirl.build(:invitation, :service => 'email', :identifier => 'foo@bar.com')
|
|
||||||
|
|
||||||
allow(Invitation).to receive(:find).and_return(invite)
|
|
||||||
expect(invite).to receive(:resend)
|
|
||||||
Workers::ResendInvitation.new.perform(invite.id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Loading…
Reference in a new issue