From 159fce3ef2955234d500ed56b8fdb6d800e69535 Mon Sep 17 00:00:00 2001 From: danielgrippi Date: Mon, 15 Aug 2011 23:05:14 -0700 Subject: [PATCH] refactor wip --- app/models/invitation.rb | 121 +++++++++++++++++++++++++++------------ app/models/user.rb | 85 ++++++++++++++++++++------- 2 files changed, 149 insertions(+), 57 deletions(-) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index 04c29b4b7..9a2ea2f5e 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -10,21 +10,98 @@ class Invitation < ActiveRecord::Base validates_presence_of :sender, :recipient, - :aspect + :aspect, + :identifier, + :service + + attr_accessible :sender, :recipient, :aspect, :service, :identifier + + before_validation :attach_recipent, :on => :create + before_create :ensure_not_inviting_self + + validate :valid_identifier? + validates_uniqueness_of :sender, :scope => :recipient + + + def identifier=(ident) + ident.downcase! if ident + ident + end + + def not_inviting_yourself + if self.identifier == self.sender.email + errors[:base] << 'You can not invite yourself' + end + end + + def attach_recipient + self.recipient = User.find_or_create_by_invitation(self) + end + + def skip_invitation? + + end + + def valid_identifier? + if self.service == 'email' + unless self.identifier.match(Devise.email_regexp) + errors[:base] << 'You can not invite yourself' + end + end + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # @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 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" - # Check whether or not the existing User has already been invited; # and if so, start sharing with the Person. elsif not existing_user.invited? @@ -48,18 +125,6 @@ class Invitation < ActiveRecord::Base # @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 - end # @params opts [Hash] Takes :from, :existing_user, :service, :identifier, :message # @return [User] @@ -71,25 +136,9 @@ class Invitation < ActiveRecord::Base 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 - 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! diff --git a/app/models/user.rb b/app/models/user.rb index 9206d0f77..7263f787a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -59,24 +59,40 @@ 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 + + + def self.find_or_create_by_invitation(invitation) + service = invitation.service + identifier = invitation.identifier + + unless existing_user = User.joins(:invitations) + .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 + + if existing_user + return existing_user + else + + end 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.create_from_invitation! + user = User.new + user.generate_keys + user.generate_invitation_token + + # 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,6 +307,8 @@ class User < ActiveRecord::Base end end + + ###Invitations############ def invite_user(aspect_id, service, identifier, invite_message = "") if aspect = aspects.find(aspect_id) @@ -355,13 +373,12 @@ class User < ActiveRecord::Base opts[:person][:profile] = Profile.new(opts[:person][:profile]) end + #TODO make this User#person= 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.generate_keys self end @@ -379,10 +396,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 +446,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