bumped carrierwave, photos can now be downloaded from a url, fetching profile photo job
This commit is contained in:
parent
c60adda3a9
commit
d51516fff3
15 changed files with 221 additions and 45 deletions
2
Gemfile
2
Gemfile
|
|
@ -40,7 +40,7 @@ gem 'sqlite3' if ENV['DB'] == 'all' || ENV['DB'] == 'sqlite'
|
||||||
# file uploading
|
# file uploading
|
||||||
|
|
||||||
gem 'aws', '2.3.32' # upgrade to 2.4 breaks 1.8 >.<
|
gem 'aws', '2.3.32' # upgrade to 2.4 breaks 1.8 >.<
|
||||||
gem 'carrierwave', '0.5.2'
|
gem 'carrierwave', '0.5.3'
|
||||||
gem 'excon', '0.2.4'
|
gem 'excon', '0.2.4'
|
||||||
gem 'fastercsv', '1.5.4', :require => false
|
gem 'fastercsv', '1.5.4', :require => false
|
||||||
gem 'fog', '0.3.25'
|
gem 'fog', '0.3.25'
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ GEM
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (>= 0.5.4)
|
rack-test (>= 0.5.4)
|
||||||
selenium-webdriver (>= 0.0.3)
|
selenium-webdriver (>= 0.0.3)
|
||||||
carrierwave (0.5.2)
|
carrierwave (0.5.3)
|
||||||
activesupport (~> 3.0)
|
activesupport (~> 3.0)
|
||||||
cgi_multipart_eof_fix (2.5.0)
|
cgi_multipart_eof_fix (2.5.0)
|
||||||
chef (0.9.12)
|
chef (0.9.12)
|
||||||
|
|
@ -485,7 +485,7 @@ DEPENDENCIES
|
||||||
capistrano (= 2.5.19)
|
capistrano (= 2.5.19)
|
||||||
capistrano-ext (= 1.2.1)
|
capistrano-ext (= 1.2.1)
|
||||||
capybara (~> 0.3.9)
|
capybara (~> 0.3.9)
|
||||||
carrierwave (= 0.5.2)
|
carrierwave (= 0.5.3)
|
||||||
chef (= 0.9.12)
|
chef (= 0.9.12)
|
||||||
client_side_validations
|
client_side_validations
|
||||||
cloudfiles (= 1.4.10)
|
cloudfiles (= 1.4.10)
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,23 @@ class ServicesController < ApplicationController
|
||||||
:uid => auth['uid'])
|
:uid => auth['uid'])
|
||||||
current_user.services << service
|
current_user.services << service
|
||||||
|
|
||||||
current_user.update_profile(current_user.person.profile.from_omniauth_hash(user))
|
if service.persisted?
|
||||||
|
fetch_photo = current_user.person.profile.image_url.blank?
|
||||||
|
|
||||||
pp "YAY"
|
current_user.update_profile(current_user.person.profile.from_omniauth_hash(user))
|
||||||
debugger
|
Resque.enqueue(Jobs::FetchProfilePhoto, current_user.id, service.id, user["image"]) if fetch_photo
|
||||||
Resque.enqueue(Jobs::FetchProfilePhoto, current_user.id, service.id)
|
|
||||||
|
flash[:notice] = I18n.t 'services.create.success'
|
||||||
|
else
|
||||||
|
flash[:error] = I18n.t 'services.create.failure'
|
||||||
|
|
||||||
|
if existing_service = Service.where(:type => service.type.to_s, :uid => service.uid).first
|
||||||
|
flash[:error] << I18n.t('services.create.already_authorized',
|
||||||
|
:diaspora_id => existing_service.user.person.profile.diaspora_handle,
|
||||||
|
:service_name => provider.camelize )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
flash[:notice] = I18n.t 'services.create.success'
|
|
||||||
if current_user.getting_started
|
if current_user.getting_started
|
||||||
redirect_to getting_started_path
|
redirect_to getting_started_path
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,17 @@
|
||||||
module Jobs
|
module Jobs
|
||||||
class FetchProfilePhoto < Base
|
class FetchProfilePhoto < Base
|
||||||
@queue = :photos
|
@queue = :photos
|
||||||
def self.perform(user_id, service_id)
|
def self.perform(user_id, service_id, fallback_image_url = nil)
|
||||||
user = User.find(user_id)
|
|
||||||
service = Service.find(service_id)
|
service = Service.find(service_id)
|
||||||
|
|
||||||
@photo = Photo.new
|
image_url = service.profile_photo_url
|
||||||
@photo.author = user.person
|
image_url ||= fallback_image_url
|
||||||
@photo.diaspora_handle = user.person.diaspora_handle
|
|
||||||
@photo.random_string = ActiveSupport::SecureRandom.hex(10)
|
return unless image_url
|
||||||
@photo.remote_unprocessed_image_url = service.profile_photo_url
|
|
||||||
|
user = User.find(user_id)
|
||||||
|
|
||||||
|
@photo = Photo.diaspora_initialize(:author => user.person, :image_url => image_url, :pending => true)
|
||||||
@photo.save!
|
@photo.save!
|
||||||
|
|
||||||
profile_params = {:image_url => @photo.url(:thumb_large),
|
profile_params = {:image_url => @photo.url(:thumb_large),
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,19 @@ class Photo < ActiveRecord::Base
|
||||||
photo.pending = params[:pending] if params[:pending]
|
photo.pending = params[:pending] if params[:pending]
|
||||||
photo.diaspora_handle = photo.author.diaspora_handle
|
photo.diaspora_handle = photo.author.diaspora_handle
|
||||||
|
|
||||||
image_file = params.delete(:user_file)
|
|
||||||
photo.random_string = ActiveSupport::SecureRandom.hex(10)
|
photo.random_string = ActiveSupport::SecureRandom.hex(10)
|
||||||
photo.unprocessed_image.store! image_file
|
|
||||||
|
if params[:user_file]
|
||||||
|
image_file = params.delete(:user_file)
|
||||||
|
photo.unprocessed_image.store! image_file
|
||||||
|
|
||||||
|
elsif params[:image_url]
|
||||||
|
photo.remote_unprocessed_image_url = params[:image_url]
|
||||||
|
photo.unprocessed_image.store!
|
||||||
|
end
|
||||||
|
|
||||||
photo.update_remote_path
|
photo.update_remote_path
|
||||||
|
|
||||||
photo
|
photo
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ class Service < ActiveRecord::Base
|
||||||
truncated = "#{truncated} #{url}" unless url.blank?
|
truncated = "#{truncated} #{url}" unless url.blank?
|
||||||
return truncated
|
return truncated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def profile_photo_url
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
require File.join(Rails.root, 'app/models/services/facebook')
|
require File.join(Rails.root, 'app/models/services/facebook')
|
||||||
require File.join(Rails.root, 'app/models/services/twitter')
|
require File.join(Rails.root, 'app/models/services/twitter')
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ class Services::Facebook < Service
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def profile_photo_url
|
||||||
|
"https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
OVERRIDE_FIELDS_ON_FB_UPDATE = [:contact_id, :person_id, :request_id, :invitation_id, :photo_url, :name, :username]
|
OVERRIDE_FIELDS_ON_FB_UPDATE = [:contact_id, :person_id, :request_id, :invitation_id, :photo_url, :name, :username]
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,7 @@ class Services::Twitter < Service
|
||||||
Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}")
|
Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}")
|
||||||
message = public_message(post, url)
|
message = public_message(post, url)
|
||||||
|
|
||||||
twitter_key = SERVICES['twitter']['consumer_key']
|
configure_twitter
|
||||||
twitter_consumer_secret = SERVICES['twitter']['consumer_secret']
|
|
||||||
|
|
||||||
if twitter_consumer_secret.blank? || twitter_consumer_secret.blank?
|
|
||||||
Rails.logger.info "you have a blank twitter key or secret.... you should look into that"
|
|
||||||
end
|
|
||||||
|
|
||||||
Twitter.configure do |config|
|
|
||||||
config.consumer_key = twitter_key
|
|
||||||
config.consumer_secret = twitter_consumer_secret
|
|
||||||
config.oauth_token = self.access_token
|
|
||||||
config.oauth_token_secret = self.access_secret
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Twitter.update(message)
|
Twitter.update(message)
|
||||||
|
|
@ -35,6 +23,25 @@ class Services::Twitter < Service
|
||||||
end
|
end
|
||||||
|
|
||||||
def profile_photo_url
|
def profile_photo_url
|
||||||
"http://api.twitter.com/1/users/profile_image?screen_name=#{nickname}&size=bigger"
|
configure_twitter
|
||||||
|
|
||||||
|
Twitter.profile_image(nickname, :size => "original")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def configure_twitter
|
||||||
|
twitter_key = SERVICES['twitter']['consumer_key']
|
||||||
|
twitter_consumer_secret = SERVICES['twitter']['consumer_secret']
|
||||||
|
|
||||||
|
if twitter_consumer_secret.blank? || twitter_consumer_secret.blank?
|
||||||
|
Rails.logger.info "you have a blank twitter key or secret.... you should look into that"
|
||||||
|
end
|
||||||
|
|
||||||
|
Twitter.configure do |config|
|
||||||
|
config.consumer_key = twitter_key
|
||||||
|
config.consumer_secret = twitter_consumer_secret
|
||||||
|
config.oauth_token = self.access_token
|
||||||
|
config.oauth_token_secret = self.access_secret
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -692,6 +692,8 @@ en:
|
||||||
no_services: 'You have not connected any services yet.'
|
no_services: 'You have not connected any services yet.'
|
||||||
create:
|
create:
|
||||||
success: "Authentication successful."
|
success: "Authentication successful."
|
||||||
|
failure: "Authentication failed."
|
||||||
|
already_authorized: "A user with diaspora id %{diaspora_id} already authorized that %{service_name} account."
|
||||||
destroy:
|
destroy:
|
||||||
success: "Successfully deleted authentication."
|
success: "Successfully deleted authentication."
|
||||||
failure:
|
failure:
|
||||||
|
|
|
||||||
|
|
@ -65,15 +65,43 @@ describe ServicesController do
|
||||||
@user.reload.services.first.class.name.should == "Services::Twitter"
|
@user.reload.services.first.class.name.should == "Services::Twitter"
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'queues a job to save user photo' do
|
it 'returns error if the service is connected with that uid' do
|
||||||
request.env['omniauth.auth'] = omniauth_auth
|
request.env['omniauth.auth'] = omniauth_auth
|
||||||
|
|
||||||
|
Services::Twitter.create!(:nickname => omniauth_auth["user_info"]['nickname'],
|
||||||
|
:access_token => omniauth_auth['credentials']['token'],
|
||||||
|
:access_secret => omniauth_auth['credentials']['secret'],
|
||||||
|
:uid => omniauth_auth['uid'],
|
||||||
|
:user => bob)
|
||||||
|
|
||||||
post :create, :provider => 'twitter'
|
post :create, :provider => 'twitter'
|
||||||
|
|
||||||
#service_stub = stub.as_null_object
|
flash[:error].include?(bob.person.profile.diaspora_handle).should be_true
|
||||||
Services::Twitter.any_instance.stub(:profile_photo_url).and_return("http://api.service.com/profile_photo.jpeg")
|
end
|
||||||
#Services::Twitter.should_receive(:new).and_return(service_stub)
|
|
||||||
Resque.should_receive(:enqueue).with(Jobs::FetchProfilePhoto, @user.id, "http://api.service.com/profile_photo.jpeg")
|
context "photo fetching" do
|
||||||
|
before do
|
||||||
|
omniauth_auth
|
||||||
|
omniauth_auth["user_info"].merge!({"image" => "https://service.com/fallback_lowres.jpg"})
|
||||||
|
|
||||||
|
request.env['omniauth.auth'] = omniauth_auth
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not queue a job if the profile photo is not updated' do
|
||||||
|
@user.person.profile.stub(:image_url).and_return("/some/image_url.jpg")
|
||||||
|
|
||||||
|
Resque.should_not_receive(:enqueue)
|
||||||
|
|
||||||
|
post :create, :provider => 'twitter'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'queues a job to save user photo if the photo does not exist' do
|
||||||
|
@user.person.profile.stub(:image_url).and_return(nil)
|
||||||
|
|
||||||
|
Resque.should_receive(:enqueue).with(Jobs::FetchProfilePhoto, @user.id, anything(), "https://service.com/fallback_lowres.jpg")
|
||||||
|
|
||||||
|
post :create, :provider => 'twitter'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
58
spec/models/jobs/fetch_profile_photo_spec.rb
Normal file
58
spec/models/jobs/fetch_profile_photo_spec.rb
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Jobs::FetchProfilePhoto do
|
||||||
|
before do
|
||||||
|
@user = alice
|
||||||
|
@service = Factory.create(:service, :user => alice)
|
||||||
|
|
||||||
|
@url = "https://service.com/user/profile_image"
|
||||||
|
|
||||||
|
@service.stub(:profile_photo_url).and_return(@url)
|
||||||
|
@user.stub(:update_profile)
|
||||||
|
|
||||||
|
User.stub(:find).and_return(@user)
|
||||||
|
Service.stub(:find).and_return(@service)
|
||||||
|
|
||||||
|
@photo_stub = stub
|
||||||
|
@photo_stub.stub(:save!).and_return(true)
|
||||||
|
@photo_stub.stub(:url).and_return("image.jpg")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'saves the profile image' do
|
||||||
|
@photo_stub.should_receive(:save!).and_return(true)
|
||||||
|
Photo.should_receive(:diaspora_initialize).with(hash_including(:author => @user.person, :image_url => @url, :pending => true)).and_return(@photo_stub)
|
||||||
|
|
||||||
|
Jobs::FetchProfilePhoto.perform(@user.id, @service.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "service does not have a profile_photo_url" do
|
||||||
|
it "does nothing without fallback" do
|
||||||
|
@service.stub!(:profile_photo_url).and_return(nil)
|
||||||
|
Photo.should_not_receive(:diaspora_initialize)
|
||||||
|
|
||||||
|
Jobs::FetchProfilePhoto.perform(@user.id, @service.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fetches fallback if it's provided" do
|
||||||
|
@photo_stub.should_receive(:save!).and_return(true)
|
||||||
|
@service.stub!(:profile_photo_url).and_return(nil)
|
||||||
|
Photo.should_receive(:diaspora_initialize).with(hash_including(:author => @user.person, :image_url => "https://service.com/fallback_lowres.jpg", :pending => true)).and_return(@photo_stub)
|
||||||
|
|
||||||
|
Jobs::FetchProfilePhoto.perform(@user.id, @service.id, "https://service.com/fallback_lowres.jpg")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it 'updates the profile' do
|
||||||
|
@photo_stub.stub(:url).and_return("large.jpg", "medium.jpg", "small.jpg")
|
||||||
|
|
||||||
|
Photo.should_receive(:diaspora_initialize).and_return(@photo_stub)
|
||||||
|
@user.should_receive(:update_profile).with(hash_including({
|
||||||
|
:image_url => "large.jpg",
|
||||||
|
:image_url_medium => "medium.jpg",
|
||||||
|
:image_url_small => "small.jpg"
|
||||||
|
}))
|
||||||
|
|
||||||
|
Jobs::FetchProfilePhoto.perform(@user.id, @service.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -55,17 +55,52 @@ describe Photo do
|
||||||
|
|
||||||
describe '#diaspora_initialize' do
|
describe '#diaspora_initialize' do
|
||||||
before do
|
before do
|
||||||
image = File.open(@fixture_name)
|
@image = File.open(@fixture_name)
|
||||||
@photo = Photo.diaspora_initialize(
|
@photo = Photo.diaspora_initialize(
|
||||||
:author => @user.person, :user_file => image)
|
:author => @user.person, :user_file => @image)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets the persons diaspora handle' do
|
it 'sets the persons diaspora handle' do
|
||||||
@photo2.diaspora_handle.should == @user.person.diaspora_handle
|
@photo.diaspora_handle.should == @user.person.diaspora_handle
|
||||||
end
|
end
|
||||||
it 'builds the photo without saving' do
|
|
||||||
@photo.created_at.nil?.should be_true
|
it 'sets the random prefix' do
|
||||||
@photo.unprocessed_image.read.nil?.should be_false
|
photo_stub = stub.as_null_object
|
||||||
|
photo_stub.should_receive(:random_string=)
|
||||||
|
Photo.stub(:new).and_return(photo_stub)
|
||||||
|
|
||||||
|
Photo.diaspora_initialize(
|
||||||
|
:author => @user.person, :user_file => @image)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with user file" do
|
||||||
|
it 'builds the photo without saving' do
|
||||||
|
@photo.created_at.nil?.should be_true
|
||||||
|
@photo.unprocessed_image.read.nil?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with a url" do
|
||||||
|
it 'saves the photo' do
|
||||||
|
url = "https://service.com/user/profile_image"
|
||||||
|
|
||||||
|
photo_stub = stub.as_null_object
|
||||||
|
photo_stub.should_receive(:remote_unprocessed_image_url=).with(url)
|
||||||
|
Photo.stub(:new).and_return(photo_stub)
|
||||||
|
|
||||||
|
Photo.diaspora_initialize(
|
||||||
|
:author => @user.person, :image_url => url)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with neither" do
|
||||||
|
it 'does not return a valid object' do
|
||||||
|
pending
|
||||||
|
Photo.diaspora_initialize(
|
||||||
|
:author => @user.person).valid?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#update_remote_path' do
|
describe '#update_remote_path' do
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,8 @@ describe Service do
|
||||||
@service.destroy
|
@service.destroy
|
||||||
}.should change(ServiceUser, :count).by(-1)
|
}.should change(ServiceUser, :count).by(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'by default has no profile photo url' do
|
||||||
|
Service.new.profile_photo_url.should == nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -122,4 +122,13 @@ JSON
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#profile_photo_url" do
|
||||||
|
it 'returns a large profile photo url' do
|
||||||
|
@service.uid = "abc123"
|
||||||
|
@service.access_token = "token123"
|
||||||
|
@service.profile_photo_url.should ==
|
||||||
|
"https://graph.facebook.com/abc123/picture?type=large&access_token=token123"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,13 @@ describe Services::Twitter do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#profile_photo_url" do
|
describe "#profile_photo_url" do
|
||||||
it 'returns the bigger profile photo' do
|
it 'returns the original profile photo url' do
|
||||||
|
stub_request(:get, "https://api.twitter.com/1/users/profile_image/joindiaspora.json?size=original").
|
||||||
|
to_return(:status => 302, :body => "", :headers => {:location => "http://a2.twimg.com/profile_images/uid/avatar.png"})
|
||||||
|
|
||||||
@service.nickname = "joindiaspora"
|
@service.nickname = "joindiaspora"
|
||||||
@service.profile_photo_url.should ==
|
@service.profile_photo_url.should ==
|
||||||
"http://api.twitter.com/1/users/profile_image?screen_name=joindiaspora&size=bigger"
|
"http://a2.twimg.com/profile_images/uid/avatar.png"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue