From 324f14c719de2c1873c52748ccd191ce5158790c Mon Sep 17 00:00:00 2001 From: ilya Date: Tue, 12 Oct 2010 18:23:59 -0700 Subject: [PATCH 01/13] setting the token to nil on accept of invite --- app/models/user.rb | 5 +- config/locales/devise.en.yml | 46 --------------- config/locales/devise/devise.en.yml | 56 ++++++++++--------- .../invitations_controller_spec.rb | 25 +++++++++ 4 files changed, 59 insertions(+), 73 deletions(-) delete mode 100644 config/locales/devise.en.yml create mode 100644 spec/controllers/invitations_controller_spec.rb diff --git a/app/models/user.rb b/app/models/user.rb index 12322dca6..cb0604e91 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -266,8 +266,7 @@ class User end end - ###Helpers############ - + ###Invitations############ def accept_invitation!( opts = {} ) if self.invited? self.username = opts[:username] @@ -283,11 +282,13 @@ class User person_hash = opts.delete(:person) self.person = Person.create(person_hash) self.person.save + self.invitation_token = nil self.save self end end + ###Helpers############ def self.instantiate!( opts = {} ) opts[:person][:diaspora_handle] = "#{opts[:username]}@#{APP_CONFIG[:terse_pod_url]}" opts[:person][:url] = APP_CONFIG[:pod_url] diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml deleted file mode 100644 index 07a2611d0..000000000 --- a/config/locales/devise.en.yml +++ /dev/null @@ -1,46 +0,0 @@ -en: - errors: - messages: - not_found: "not found" - already_confirmed: "was already confirmed" - not_locked: "was not locked" - - devise: - failure: - unauthenticated: 'You need to sign in or sign up before continuing.' - unconfirmed: 'You have to confirm your account before continuing.' - locked: 'Your account is locked.' - invalid: 'Invalid email or password.' - invalid_token: 'Invalid authentication token.' - timeout: 'Your session expired, please sign in again to continue.' - inactive: 'Your account was not activated yet.' - sessions: - signed_in: 'Signed in successfully.' - signed_out: 'Signed out successfully.' - passwords: - send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' - updated: 'Your password was changed successfully. You are now signed in.' - confirmations: - send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' - confirmed: 'Your account was successfully confirmed. You are now signed in.' - registrations: - signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' - updated: 'You updated your account successfully.' - destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' - unlocks: - send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' - unlocked: 'Your account was successfully unlocked. You are now signed in.' - invitations: - send_instructions: 'Your invitation has been sent.' - invitation_token_invalid: 'The invitation token provided is not valid!' - updated: 'Your password was set successfully. You are now signed in.' - mailer: - confirmation_instructions: - subject: 'Confirmation instructions' - reset_password_instructions: - subject: 'Reset password instructions' - unlock_instructions: - subject: 'Unlock Instructions' - invitation: - subject: 'A friend wants you to join Diaspora!' - diff --git a/config/locales/devise/devise.en.yml b/config/locales/devise/devise.en.yml index 06308488b..07a2611d0 100644 --- a/config/locales/devise/devise.en.yml +++ b/config/locales/devise/devise.en.yml @@ -1,7 +1,3 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - en: errors: messages: @@ -11,30 +7,40 @@ en: devise: failure: - unauthenticated: "You need to sign in or sign up before continuing." - unconfirmed: "You have to confirm your account before continuing." - locked: "Your account is locked." - invalid: "Invalid email or password." - invalid_token: "Invalid authentication token." - timeout: "Your session expired, please sign in again to continue." - inactive: "Your account was not activated yet." + unauthenticated: 'You need to sign in or sign up before continuing.' + unconfirmed: 'You have to confirm your account before continuing.' + locked: 'Your account is locked.' + invalid: 'Invalid email or password.' + invalid_token: 'Invalid authentication token.' + timeout: 'Your session expired, please sign in again to continue.' + inactive: 'Your account was not activated yet.' sessions: - signed_in: "Signed in successfully." - signed_out: "Signed out successfully." + signed_in: 'Signed in successfully.' + signed_out: 'Signed out successfully.' passwords: - send_instructions: "You will receive an email with instructions about how to reset your password in a few minutes." - updated: "Your password was changed successfully. You are now signed in." + send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' + updated: 'Your password was changed successfully. You are now signed in.' confirmations: - send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." - confirmed: "Your account was successfully confirmed. You are now signed in." + send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' + confirmed: 'Your account was successfully confirmed. You are now signed in.' registrations: - signed_up: "You have signed up successfully. If enabled, a confirmation was sent to your e-mail." - updated: "You updated your account successfully." - destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon." + signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.' + updated: 'You updated your account successfully.' + destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' unlocks: - send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes." - unlocked: "Your account was successfully unlocked. You are now signed in." + send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' + unlocked: 'Your account was successfully unlocked. You are now signed in.' + invitations: + send_instructions: 'Your invitation has been sent.' + invitation_token_invalid: 'The invitation token provided is not valid!' + updated: 'Your password was set successfully. You are now signed in.' mailer: - confirmation_instructions: "Confirmation instructions" - reset_password_instructions: "Reset password instructions" - unlock_instructions: "Unlock Instructions" + confirmation_instructions: + subject: 'Confirmation instructions' + reset_password_instructions: + subject: 'Reset password instructions' + unlock_instructions: + subject: 'Unlock Instructions' + invitation: + subject: 'A friend wants you to join Diaspora!' + diff --git a/spec/controllers/invitations_controller_spec.rb b/spec/controllers/invitations_controller_spec.rb new file mode 100644 index 000000000..ff87b4bcc --- /dev/null +++ b/spec/controllers/invitations_controller_spec.rb @@ -0,0 +1,25 @@ +# 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 InvitationsController do + render_views + let(:user) {Factory.create :user} + + before do + sign_in :user, user + end + + context 'inviting another user' do + it 'should create an invited user and add keep track of an invitor' do + debugger + params = {"user" => {"email" => "test@example.com"}} + post :create, params + #invitee = inviter.invite_user(:email => "test@example.com") + #invitee.inviters.includes?(inviter).should be true + end + end + +end From 3f9a51fa3fb783ea0fe71aa8cc2dc4da542fd067 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 10:27:29 -0700 Subject: [PATCH 02/13] First attempt at detecting called port with getopts --- script/server | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/script/server b/script/server index 130b61220..5edce844a 100755 --- a/script/server +++ b/script/server @@ -3,10 +3,19 @@ # Start diaspora websocket and main services # -# Is someone listening on 3000 already? (ipv4 only test ?) -services=$( netstat -nl | grep '[^:]:3000[ \t]') +# Is someone listening on the port already? (ipv4 only test ?) +PORT=3000 +while getopts ":p:" OPTION +do + if OPTION='p' + then + PORT=$OPTARG + fi +done + +services=$( netstat -nl | grep '[^:]:'+ $PORT +'[ \t]') test -n "$services" && { - echo "Warning: something is already using port 3000" + echo "Warning: something is already using port " + $PORT echo " $services" } From 9e27c802c3ea50274f7017139445974dd88fed78 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 10:47:21 -0700 Subject: [PATCH 03/13] Got port check in bash script working --- script/server | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/server b/script/server index 5edce844a..b03370533 100755 --- a/script/server +++ b/script/server @@ -13,10 +13,11 @@ do fi done -services=$( netstat -nl | grep '[^:]:'+ $PORT +'[ \t]') +services=$( netstat -nl | grep '[^:]:'$PORT'[ \t]') test -n "$services" && { echo "Warning: something is already using port " + $PORT echo " $services" + exit } From 9898c8b15850603fe40789d9b8c8865ecbb974e8 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 11:07:26 -0700 Subject: [PATCH 04/13] Typo in script/server --- script/server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/server b/script/server index b03370533..42238e052 100755 --- a/script/server +++ b/script/server @@ -15,7 +15,7 @@ done services=$( netstat -nl | grep '[^:]:'$PORT'[ \t]') test -n "$services" && { - echo "Warning: something is already using port " + $PORT + echo "Warning: something is already using port "$PORT echo " $services" exit } From 9a1590fa0233fe0131b9a5f755a00dfc5f62068b Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 11:18:06 -0700 Subject: [PATCH 05/13] Move user module requires out to the user modules definition file --- app/models/user.rb | 8 ++------ lib/diaspora/user.rb | 11 +++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 lib/diaspora/user.rb diff --git a/app/models/user.rb b/app/models/user.rb index 12322dca6..92f4f92a4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,9 +2,7 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -require File.join(Rails.root, 'lib/diaspora/user/friending') -require File.join(Rails.root, 'lib/diaspora/user/querying') -require File.join(Rails.root, 'lib/diaspora/user/receiving') +require File.join(Rails.root, 'lib/diaspora/user') require File.join(Rails.root, 'lib/salmon/salmon') class InvitedUserValidator < ActiveModel::Validator @@ -20,9 +18,7 @@ end class User include MongoMapper::Document plugin MongoMapper::Devise - include Diaspora::UserModules::Friending - include Diaspora::UserModules::Querying - include Diaspora::UserModules::Receiving + include Diaspora::UserModules include Encryptor::Private QUEUE = MessageHandler.new diff --git a/lib/diaspora/user.rb b/lib/diaspora/user.rb new file mode 100644 index 000000000..94da947f8 --- /dev/null +++ b/lib/diaspora/user.rb @@ -0,0 +1,11 @@ +require File.join(Rails.root, 'lib/diaspora/user/friending') +require File.join(Rails.root, 'lib/diaspora/user/querying') +require File.join(Rails.root, 'lib/diaspora/user/receiving') + +module Diaspora + module UserModules + include Friending + include Querying + include Receiving + end +end From 3274f109e5c6051f9d1e8c15d981544e21c4da22 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 11:30:22 -0700 Subject: [PATCH 06/13] Reorganize gitignore --- .gitignore | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 8482dc230..999b067f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,17 @@ +# Configuration files +config/app_config.yml +config/fb_config.yml +config/initializers/secret_token.rb .bundle + +# Uploded files and local files +log/* +public/uploads/* +public/source.tar +tmp/**/* +db/*.sqlite3 + +# Temporary files of every sort .DS_Store .idea .rvmrc @@ -8,17 +21,6 @@ *.swp *~ bin/* -config/app_config.yml -config/fb_config.yml -config/initializers/secret_token.rb -db/*.sqlite3 -log/* nbproject -gpg/diaspora-development/*.gpg -gpg/diaspora-production/*.gpg -gpg/*/random_seed patches-* -public/uploads/* -public/source.tar -tmp/**/* capybara-*.html From 3b8998ab71baac653c38af6be09148a958a41b90 Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 13 Oct 2010 13:29:45 -0700 Subject: [PATCH 07/13] Invitations contains the inviters --- app/controllers/invitations_controller.rb | 11 ++++++++ app/models/user.rb | 25 +++++++++++++++++++ .../mailer/invitation.html.haml | 2 +- spec/models/user/invite_spec.rb | 25 ++++++++++++++++--- 4 files changed, 58 insertions(+), 5 deletions(-) rename app/views/{users => devise}/mailer/invitation.html.haml (58%) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 852904458..e7b2c0262 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -3,6 +3,17 @@ # the COPYRIGHT file. class InvitationsController < Devise::InvitationsController + def create + self.resource = current_user.invite_user(params[resource_name]) + + if resource.errors.empty? + set_flash_message :notice, :send_instructions#, :email => self.resource.email + redirect_to after_sign_in_path_for(resource_name) + else + render_with_scope :new + end + end + def update begin user = User.find_by_invitation_token(params["user"]["invitation_token"]) diff --git a/app/models/user.rb b/app/models/user.rb index 7e6d18f90..152591f1f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,6 +29,7 @@ class User key :invitation_token, String key :invitation_sent_at, DateTime + key :inviter_ids, Array key :friend_ids, Array key :pending_request_ids, Array key :visible_post_ids, Array @@ -36,6 +37,7 @@ class User one :person, :class_name => 'Person', :foreign_key => :owner_id + many :inviters, :in => :inviter_ids, :class_name => 'User' many :friends, :in => :friend_ids, :class_name => 'Person' many :visible_people, :in => :visible_person_ids, :class_name => 'Person' # One of these needs to go many :pending_requests, :in => :pending_request_ids, :class_name => 'Request' @@ -263,6 +265,29 @@ class User end ###Invitations############ + def invite_user( opts = {} ) + invited_user = User.invite!(:email => opts[:email], :inviter => self) + #invited_user.inviters << self + #invited_user.save! + invited_user + end + + def self.invite!(attributes={}) + inviter = attributes.delete(:inviter) + invitable = find_or_initialize_with_error_by(:email, attributes.delete(:email)) + invitable.attributes = attributes + invitable.inviters << inviter + + if invitable.new_record? + invitable.errors.clear if invitable.email.try(:match, Devise.email_regexp) + else + invitable.errors.add(:email, :taken) unless invitable.invited? + end + + invitable.invite! if invitable.errors.empty? + invitable + end + def accept_invitation!( opts = {} ) if self.invited? self.username = opts[:username] diff --git a/app/views/users/mailer/invitation.html.haml b/app/views/devise/mailer/invitation.html.haml similarity index 58% rename from app/views/users/mailer/invitation.html.haml rename to app/views/devise/mailer/invitation.html.haml index 884a8fc27..a6c82a3b0 100644 --- a/app/views/users/mailer/invitation.html.haml +++ b/app/views/devise/mailer/invitation.html.haml @@ -1,7 +1,7 @@ %p Hello #{@resource.email}! %p - Someone has invited you to #{root_url}, you can accept it through the link below. + #{(@resource.inviters.count == 1)? ( @resource.inviters.first.real_name " has") : (@resource.inviters.map{|inv| inv.real_name}.join(",") + " have")} invited you to #{root_url}, you can accept it through the link below. %p= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token) %p If you don't want to accept the invitation, please ignore this email. diff --git a/spec/models/user/invite_spec.rb b/spec/models/user/invite_spec.rb index 1bb2bf0f6..25d08e897 100644 --- a/spec/models/user/invite_spec.rb +++ b/spec/models/user/invite_spec.rb @@ -5,18 +5,34 @@ require 'spec_helper' describe User do - let!(:invited_user) { create_user_with_invitation("abc")} + let(:inviter) {Factory.create :user} + let!(:invited_user) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter)} + + context "creating invites" do + it 'should invite the user' do + pending "weird wrong number of arguments error (0 for 2), which changes if you put in two args" + #User.should_receive(:invite!).and_return(invited_user) + inviter.invite_user(:email => "email@example.com") + end + + it 'should add the inviter to the invited_user' do + User.should_receive(:invite!).and_return(invited_user) + invited_user = inviter.invite_user(:email => "email@example.com") + invited_user.reload + invited_user.inviters.include?(inviter).should be true + end + end context "the acceptance of an invitation" do it "should create the person with the passed in params" do - Person.count.should be 0 + person_count = Person.count u = invited_user.accept_invitation!(:invitation_token => "abc", :username => "user", :password => "secret", :password_confirmation => "secret", :person => {:profile => {:first_name => "Bob", :last_name => "Smith"}} ) - Person.count.should be 1 + Person.count.should be person_count + 1 u.person.profile.first_name.should == "Bob" end end @@ -25,11 +41,12 @@ describe User do end def create_user_with_invitation(invitation_token, attributes={}) + inviter = attributes.delete(:inviter) user = User.new({:password => nil, :password_confirmation => nil}.update(attributes)) - #puts user.inspect #user.skip_confirmation! user.invitation_token = invitation_token user.invitation_sent_at = Time.now.utc + user.inviters << inviter user.save(:validate => false) user end From 0c5d197295d81084e97fb735f63f35f5bbf4b888 Mon Sep 17 00:00:00 2001 From: Alec Leamas Date: Wed, 13 Oct 2010 22:40:49 +0200 Subject: [PATCH 08/13] README update on Gemfile.lock problem, blocking. --- pkg/fedora/README.md | 4 ++++ pkg/ubuntu/README.md | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/pkg/fedora/README.md b/pkg/fedora/README.md index c0b29d3d2..346730a3a 100644 --- a/pkg/fedora/README.md +++ b/pkg/fedora/README.md @@ -1,5 +1,9 @@ ## Diaspora RPM tools +NOTE: This does not work ATM, see discussions on Gemfile.lock in +attached to a commit 12/10 (yea, I know, you calll it 10/12, but you +are wrong ;) + Creates diaspora source tarballs and RPM packages An alternative to the capistrano system, providing classic, binary RPM diff --git a/pkg/ubuntu/README.md b/pkg/ubuntu/README.md index f50897b24..b676ebf0c 100644 --- a/pkg/ubuntu/README.md +++ b/pkg/ubuntu/README.md @@ -1,5 +1,10 @@ ## Package-oriented install for ubuntu. +NOTE: This does not work ATM, see discussions on Gemfile.lock in +attached to a commit 12/10 (yea, I know, you calll it 10/12, but you +are wrong ;) + + Here are somediaspora-installdiaspora-install scripts to install diaspora on Ubuntu. They are designed to work as a first step towards packaging, but should be usable as is. From 51a02409c867eb0e7e3965f13a48e7fb6b154bcd Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 15:18:27 -0700 Subject: [PATCH 09/13] Another try at script server fix --- script/server | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/script/server b/script/server index 42238e052..c60add75c 100755 --- a/script/server +++ b/script/server @@ -7,19 +7,20 @@ PORT=3000 while getopts ":p:" OPTION do - if OPTION='p' + if [ $OPTION == 'p' ] then PORT=$OPTARG fi done -services=$( netstat -nl | grep '[^:]:'$PORT'[ \t]') +services=$( netstat -nl | grep ":$PORT[ \t]") + test -n "$services" && { echo "Warning: something is already using port "$PORT echo " $services" exit } - +exit # Check if Mongo is running From fd88e24a55fc5d3f14abd6c5a10e405b7f3be5ff Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 16:16:22 -0700 Subject: [PATCH 10/13] Forgot to commit a line --- script/server | 1 - 1 file changed, 1 deletion(-) diff --git a/script/server b/script/server index c60add75c..2649ed677 100755 --- a/script/server +++ b/script/server @@ -20,7 +20,6 @@ test -n "$services" && { echo " $services" exit } -exit # Check if Mongo is running From 3fb2ee6e1b833abb35ac77a6d1941a825762f9aa Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 13 Oct 2010 16:28:56 -0700 Subject: [PATCH 11/13] adding spec for password confirmation fail --- spec/models/user_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index dfb0f685c..8da51bc4a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -22,6 +22,20 @@ describe User do user.valid? user.username.should == "someuppercase" end + + it "confirms the password" do + pending "I cannot figure out why this doesn't work. --Raphael" + user = User.instantiate!( + :email => "tom@tom.joindiaspora.com", + :username => "tom", + :password => "evankorth", + :password_confirmation => "potatoes", + :person => Person.new( + :profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" )) + ) + user.created_at.should be_nil + user.valid?.should be_false + end end describe '#diaspora_handle' do From 36b9f66f6055a6533b8ac2e33dfbbc247948d63d Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 13 Oct 2010 16:52:18 -0700 Subject: [PATCH 12/13] the invited user keeps track of who invited them, limit on invites, removed the invites controller test --- app/controllers/application_controller.rb | 7 ++++++ app/controllers/invitations_controller.rb | 19 ++++++++------ app/models/user.rb | 19 ++++++++++---- app/views/aspects/manage.html.haml | 1 + app/views/devise/mailer/invitation.html.haml | 2 +- app/views/shared/_aspect_friends.haml | 2 ++ config/locales/diaspora/en.yml | 8 ++++++ .../invitations_controller_spec.rb | 25 ------------------- spec/models/user/invite_spec.rb | 23 ++++++++++++++++- 9 files changed, 67 insertions(+), 39 deletions(-) delete mode 100644 spec/controllers/invitations_controller_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 82a8f7cd1..65b57b252 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base before_filter :set_friends_and_status, :except => [:create, :update] before_filter :count_requests before_filter :fb_user_info + before_filter :set_invites layout :layout_by_resource @@ -37,6 +38,12 @@ class ApplicationController < ActionController::Base @request_count = Request.for_user(current_user).size if current_user end + def set_invites + if current_user + @invites = current_user.invites + end + end + def fb_user_info if current_user @access_token = warden.session[:access_token] diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index e7b2c0262..92da135d8 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -4,14 +4,19 @@ class InvitationsController < Devise::InvitationsController def create - self.resource = current_user.invite_user(params[resource_name]) - - if resource.errors.empty? - set_flash_message :notice, :send_instructions#, :email => self.resource.email - redirect_to after_sign_in_path_for(resource_name) - else - render_with_scope :new + begin + self.resource = current_user.invite_user(params[resource_name]) + flash[:notice] = I18n.t 'invitations.create.sent' + rescue RuntimeError => e + if e.message == "You have no invites" + flash[:error] = I18n.t 'invitations.create.no_more' + elsif e.message == "You already invited this person" + flash[:error] = I18n.t 'invitations.create.already_sent' + else + raise e + end end + redirect_to after_sign_in_path_for(resource_name) end def update diff --git a/app/models/user.rb b/app/models/user.rb index 152591f1f..795d610cb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -27,6 +27,7 @@ class User key :username, :unique => true key :serialized_private_key, String + key :invites, Integer, :default => 5 key :invitation_token, String key :invitation_sent_at, DateTime key :inviter_ids, Array @@ -266,17 +267,25 @@ class User ###Invitations############ def invite_user( opts = {} ) - invited_user = User.invite!(:email => opts[:email], :inviter => self) - #invited_user.inviters << self - #invited_user.save! - invited_user + if self.invites > 0 + invited_user = User.invite!(:email => opts[:email], :inviter => self) + self.invites = self.invites - 1 + self.save! + invited_user + else + raise "You have no invites" + end end def self.invite!(attributes={}) inviter = attributes.delete(:inviter) invitable = find_or_initialize_with_error_by(:email, attributes.delete(:email)) invitable.attributes = attributes - invitable.inviters << inviter + if invitable.inviters.include?(inviter) + raise "You already invited this person" + else + invitable.inviters << inviter + end if invitable.new_record? invitable.errors.clear if invitable.email.try(:match, Devise.email_regexp) diff --git a/app/views/aspects/manage.html.haml b/app/views/aspects/manage.html.haml index 85296669f..472d8241f 100644 --- a/app/views/aspects/manage.html.haml +++ b/app/views/aspects/manage.html.haml @@ -26,6 +26,7 @@ %li.grey Drag to ignore/remove %h3= link_to "Invite a friend!", "#invite_user_pane", :id => "invite_user_button", :class => "invite_user_button", :title => "Invite a friend" + %h3= "You have #{@invites} invites." .yo{ :style => "display:none;"} #invite_user_pane diff --git a/app/views/devise/mailer/invitation.html.haml b/app/views/devise/mailer/invitation.html.haml index a6c82a3b0..03b6a5d26 100644 --- a/app/views/devise/mailer/invitation.html.haml +++ b/app/views/devise/mailer/invitation.html.haml @@ -1,7 +1,7 @@ %p Hello #{@resource.email}! %p - #{(@resource.inviters.count == 1)? ( @resource.inviters.first.real_name " has") : (@resource.inviters.map{|inv| inv.real_name}.join(",") + " have")} invited you to #{root_url}, you can accept it through the link below. + #{(@resource.inviters.count == 1)? ( @resource.inviters.first.real_name + " has") : (@resource.inviters.map{|inv| inv.real_name}.join(",") + " have")} invited you to #{root_url}, you can accept it through the link below. %p= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token) %p If you don't want to accept the invitation, please ignore this email. diff --git a/app/views/shared/_aspect_friends.haml b/app/views/shared/_aspect_friends.haml index 343272dff..a37068577 100644 --- a/app/views/shared/_aspect_friends.haml +++ b/app/views/shared/_aspect_friends.haml @@ -24,6 +24,8 @@ %br = link_to "Invite a friend!", "#invite_user_pane", :id => "invite_user_button", :class => "invite_user_button", :title => "Invite a friend" +%br += "You have #{@invites} invites." .yo{ :style => "display:none;"} #invite_user_pane = render "invitations/new" diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 554f8bcb8..1dd33bb3f 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -154,6 +154,14 @@ en: sign_up: "Sign up" create: success: "You've joined Diaspora!" + invitations: + create: + sent: 'Your invitation has been sent.' + no_more: 'You have no more invitations.' + already_sent: 'You already invited this person.' + invitation_token_invalid: 'The invitation token provided is not valid!' + updated: 'Your password was set successfully. You are now signed in.' + status_messages: new_status_message: tell_me_something_good: "tell me something good" diff --git a/spec/controllers/invitations_controller_spec.rb b/spec/controllers/invitations_controller_spec.rb deleted file mode 100644 index ff87b4bcc..000000000 --- a/spec/controllers/invitations_controller_spec.rb +++ /dev/null @@ -1,25 +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 InvitationsController do - render_views - let(:user) {Factory.create :user} - - before do - sign_in :user, user - end - - context 'inviting another user' do - it 'should create an invited user and add keep track of an invitor' do - debugger - params = {"user" => {"email" => "test@example.com"}} - post :create, params - #invitee = inviter.invite_user(:email => "test@example.com") - #invitee.inviters.includes?(inviter).should be true - end - end - -end diff --git a/spec/models/user/invite_spec.rb b/spec/models/user/invite_spec.rb index 25d08e897..117bb5b37 100644 --- a/spec/models/user/invite_spec.rb +++ b/spec/models/user/invite_spec.rb @@ -6,7 +6,11 @@ require 'spec_helper' describe User do let(:inviter) {Factory.create :user} - let!(:invited_user) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter)} + let(:inviter_with_3_invites) {Factory.create :user, :invites => 3} + let!(:invited_user) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter)} + let(:invited_user1) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter_with_3_invites)} + let(:invited_user2) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter_with_3_invites)} + let(:invited_user3) { create_user_with_invitation("abc", :email => "email@example.com", :inviter => inviter_with_3_invites)} context "creating invites" do it 'should invite the user' do @@ -23,6 +27,23 @@ describe User do end end + context "limit on invites" do + it 'does not invite users after 3 invites' do + User.stub!(:invite!).and_return(invited_user1,invited_user2,invited_user3) + inviter_with_3_invites.invite_user(:email => "email1@example.com") + inviter_with_3_invites.invite_user(:email => "email2@example.com") + inviter_with_3_invites.invite_user(:email => "email3@example.com") + proc{inviter_with_3_invites.invite_user(:email => "email4@example.com")}.should raise_error /You have no invites/ + end + + it 'does not invite people I already invited' do + pending "this is really weird to test without the actual method working" + User.stub!(:invite!).and_return(invited_user1,invited_user1) + inviter_with_3_invites.invite_user(:email => "email1@example.com") + proc{inviter_with_3_invites.invite_user(:email => "email1@example.com")}.should raise_error /You already invited that person/ + end + end + context "the acceptance of an invitation" do it "should create the person with the passed in params" do person_count = Person.count From d0c6f12ea8a6d8f8fd7116c91cd1690dacbbeb1a Mon Sep 17 00:00:00 2001 From: ilya Date: Wed, 13 Oct 2010 18:43:22 -0700 Subject: [PATCH 13/13] added another attack vector spec --- app/controllers/users_controller.rb | 4 --- app/views/devise/mailer/invitation.html.haml | 2 +- spec/models/user/attack_vectors_spec.rb | 29 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 030cfe56d..0956c28cc 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -78,10 +78,6 @@ class UsersController < ApplicationController send_data( File.open(tar_path).read, :filename => "#{current_user.id}.tar" ) end - def invite - User.invite!(:email => params[:email]) - end - private def prep_image_url(params) url = APP_CONFIG[:pod_url].chop if APP_CONFIG[:pod_url][-1,1] == '/' diff --git a/app/views/devise/mailer/invitation.html.haml b/app/views/devise/mailer/invitation.html.haml index 03b6a5d26..86b01d97a 100644 --- a/app/views/devise/mailer/invitation.html.haml +++ b/app/views/devise/mailer/invitation.html.haml @@ -6,4 +6,4 @@ %p If you don't want to accept the invitation, please ignore this email. %br/ - Your account won't be created until you access the link above and set your password. + Your account won't be created until you access the link above and sign up. diff --git a/spec/models/user/attack_vectors_spec.rb b/spec/models/user/attack_vectors_spec.rb index 2918cf1ca..625969bef 100644 --- a/spec/models/user/attack_vectors_spec.rb +++ b/spec/models/user/attack_vectors_spec.rb @@ -21,7 +21,7 @@ describe User do end context 'malicious friend attack vector' do - it 'ovewrites messages with a different user' do + it 'overwrites messages with a different user' do original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id user.receive_salmon(user2.salmon(original_message).xml_for(user.person)) @@ -34,7 +34,7 @@ describe User do user.raw_visible_posts.first.message.should == "store this!" end - it 'ovewrites messages which apear to be from the same user' do + it 'overwrites messages which apear to be from the same user' do original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id user.receive_salmon(user2.salmon(original_message).xml_for(user.person)) user.raw_visible_posts.count.should be 1 @@ -47,7 +47,7 @@ describe User do user.raw_visible_posts.first.message.should == "store this!" end - it 'overites another persons profile' do + it 'should not overwrite another persons profile profile' do profile = user2.profile.clone profile.first_name = "Not BOB" @@ -57,6 +57,29 @@ describe User do user2.reload user2.profile.first_name.should == "Robert" end + + it 'should not overwrite another persons profile through comment' do + pending + user_status = user.post(:status_message, :message => "hi", :to => 'all') + comment = Comment.new(:person_id => user3.person.id, :text => "hey", :post => user_status) + + comment.creator_signature = comment.sign_with_key(user3.encryption_key) + comment.post_creator_signature = comment.sign_with_key(user.encryption_key) + person = user3.person + original_url = person.url + original_id = person.id + puts original_url + + comment.person.url = "http://bad.com/" + user3.delete + person.delete + + comment.to_diaspora_xml.include?("bad.com").should be true + user2.receive_salmon(user.salmon(comment).xml_for(user2.person)) + + comment.person.url.should == original_url + Person.first(:id => original_id).url.should == original_url + end end end