kill services users with fire. we need this feature, but we need to just start from scratch because this is redonkalonk

This commit is contained in:
Maxwell Salzberg 2012-05-10 12:31:51 -07:00
parent 7a256d7810
commit 06f389231a
21 changed files with 34 additions and 514 deletions

View file

@ -63,11 +63,6 @@ class ServicesController < ApplicationController
@service.destroy
flash[:notice] = I18n.t 'services.destroy.success'
redirect_to services_url
end
end
def finder
@finder = true
@service = current_user.services.where(:type => "Services::#{params[:provider].titleize}").first
@friends = @service ? @service.finder(:remote => params[:remote]).paginate( :page => params[:page], :per_page => 15) : []
end
end

View file

@ -3,19 +3,4 @@
# the COPYRIGHT file.
class SessionsController < Devise::SessionsController
after_filter :enqueue_update, :only => :create
protected
def enqueue_update
begin
if current_user
current_user.services.each do |s|
Resque.enqueue(Jobs::UpdateServiceUsers, s.id) if s.respond_to? :save_friends
end
end
rescue
end
end
end
end

View file

@ -1,18 +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 Jobs
class UpdateServiceUsers < Base
@queue = :http_service
def self.perform(service_id)
service = Service.find(service_id)
begin
service.save_friends
rescue SocketError
nil
end
end
end
end

View file

@ -7,7 +7,6 @@ class Service < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :uid, :scope => :type
has_many :service_users, :dependent => :destroy
def self.titles(service_strings)
service_strings.map{|s| "Services::#{s.titleize}"}

View file

@ -1,45 +0,0 @@
class ServiceUser < ActiveRecord::Base
belongs_to :person
belongs_to :contact
belongs_to :service
belongs_to :invitation
before_save :attach_local_models
scope :with_local_people, joins(:person).merge(Person.local)
scope :with_remote_people, joins(:person).merge(Person.remote)
def already_invited?
self.invitation_id.present?
end
def on_diaspora?
self.person_id.present?
end
def self.username_of_service_user_by_uid(uid)
if su = ServiceUser.find_by_uid(uid)
su.username
else
nil
end
end
def attach_local_models
service_for_uid = Services::Facebook.where(:type => service.type.to_s, :uid => self.uid).first
if !service_for_uid.blank? && (service_for_uid.user.person.profile.searchable)
self.person = service_for_uid.user.person
else
self.person = nil
end
if self.person
self.contact = self.service.user.contact_for(self.person)
end
self.invitation = Invitation.where(:sender_id => self.service.user_id,
:service => self.service.provider,
:identifier => self.uid).first
end
end

View file

@ -2,6 +2,7 @@ require 'uri'
class Services::Facebook < Service
include Rails.application.routes.url_helpers
OVERRIDE_FIELDS_ON_FB_UPDATE = [:contact_id, :person_id, :request_id, :invitation_id, :photo_url, :name, :username]
MAX_CHARACTERS = 420
def provider
@ -34,59 +35,7 @@ class Services::Facebook < Service
super(post, MAX_CHARACTERS, url)
end
def finder(opts = {})
Rails.logger.debug("event=friend_finder type=facebook sender_id=#{self.user_id}")
prevent_service_users_from_being_empty
result = if opts[:local]
self.service_users.with_local_people
elsif opts[:remote]
self.service_users.with_remote_people
else
self.service_users
end
result.includes(:contact => :aspects, :person => :profile).order('service_users.person_id DESC, service_users.name')
end
def save_friends
url = "https://graph.facebook.com/me/friends?fields[]=name&fields[]=picture&access_token=#{URI.escape(self.access_token)}"
response = Faraday.get(url)
data = JSON.parse(response.body)['data']
return unless data
data.map!{ |p|
su = ServiceUser.new(:service_id => self.id, :uid => p["id"], :photo_url => p["picture"], :name => p["name"], :username => p["username"])
su.attach_local_models
su
}
if postgres?
# Take the naive approach to inserting our new visibilities for now.
data.each do |su|
if existing = ServiceUser.find_by_uid(su.uid)
update_hash = OVERRIDE_FIELDS_ON_FB_UPDATE.inject({}) do |acc, element|
acc[element] = su.send(element)
acc
end
existing.update_attributes(update_hash)
else
su.save
end
end
else
ServiceUser.import(data, :on_duplicate_key_update => OVERRIDE_FIELDS_ON_FB_UPDATE + [:updated_at])
end
end
def profile_photo_url
"https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}"
end
private
OVERRIDE_FIELDS_ON_FB_UPDATE = [:contact_id, :person_id, :request_id, :invitation_id, :photo_url, :name, :username]
def prevent_service_users_from_being_empty
Resque.enqueue(Jobs::UpdateServiceUsers, self.id)
end
end
"https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}"
end
end

View file

@ -3,7 +3,7 @@
-# the COPYRIGHT file.
%ul#aspect_nav.left_nav
%li.all_aspects{:class => ("active" if params["set"] != "all" && params["set"] != "only_sharing" && !@spotlight && !@finder)}
%li.all_aspects{:class => ("active" if params["set"] != "all" && params["set"] != "only_sharing" && !@spotlight)}
%a.home_selector{:href => contacts_path, :class => ("sub_selected" if params["a_id"])}
= t('contacts.index.my_contacts')
.contact_count

View file

@ -1,27 +0,0 @@
.stream_element{:id => friend.id}
.float-right
- if friend.on_diaspora?
= aspect_membership_dropdown(contact_proxy(friend), friend.person, 'left')
- else
= render 'shared/aspect_dropdown', :selected_aspects => contact_proxy(friend).aspects, :person => friend.person, :hang => 'left', :dropdown_class => 'inviter', :service_uid => friend.uid
.media
- if friend.on_diaspora?
.img
= person_image_link(friend.person, :size => :thumb_small)
- else
.img
= image_tag(friend.photo_url, :class => 'avatar')
.content
%span.from.name
- if friend.on_diaspora?
= link_to friend.name, local_or_remote_person_path(friend.person)
- else
= friend.name
.info
- if friend.person
= friend.person.diaspora_handle
- else
=t('.not_on_diaspora')

View file

@ -1,35 +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.
- content_for :head do
= javascript_include_tag :finder
#section_header
%h2
= t('contacts.index.title')
= render 'shared/contact_sidebar'
.span-18.last.searchable
/= search_field_tag :contact_search, "", :id => "contact_list_search", :class => 'contact_list_search', :results => 5, :placeholder => t('search')
%h3
= t('.service_friends', :service => params[:provider].titleize)
#people_stream.stream.contacts
- if @friends.size > 0
= render :partial => 'remote_friend', :collection => @friends, :as => :friend
= will_paginate @friends
- elsif @service
.no_contacts
%br
%br
%h4
= t('.fetching_contacts', :service => params[:provider].titleize)
- else
.no_contacts
= link_to(image_tag("social_media_logos/facebook-48x48.png"), "/auth/facebook")
%br
%br
%h4
= link_to t('services.index.connect_to_facebook'), '/auth/facebook'

View file

@ -1,5 +0,0 @@
- post.photos.each do |photo|
= image_tag(photo.url(:scaled_full))
%br
%br
= auto_link(post.text, :link => :urls)

View file

@ -11,6 +11,3 @@
- if AppConfig[:community_spotlight]
%li{:class => ("active" if @spotlight)}
= link_to t('contacts.spotlight.community_spotlight'), community_spotlight_path, :class => "element_selector"
%li{:class => ("active" if @finder)}
= link_to "Facebook Friends", friend_finder_path('facebook'), :class => "element_selector"

View file

@ -0,0 +1,24 @@
class DropServiceUsers < ActiveRecord::Migration
def up
drop_table :services_users
end
def down
create_table :service_users do |t|
t.string :uid, :null => false
t.string :name, :null => false
t.string :photo_url, :null => false
t.integer :service_id, :null => false
t.integer :person_id
t.integer :contact_id
t.integer :request_id
t.integer :invitation_id
t.timestamps
end
add_index :service_users, :service_id
add_index :service_users, [:uid, :service_id], :unique => true
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120506053156) do
ActiveRecord::Schema.define(:version => 20120510184853) do
create_table "account_deletions", :force => true do |t|
t.string "diaspora_handle"
@ -107,8 +107,6 @@ ActiveRecord::Schema.define(:version => 20120506053156) do
t.datetime "updated_at"
end
add_index "conversations", ["author_id"], :name => "conversations_author_id_fk"
create_table "invitation_codes", :force => true do |t|
t.string "token"
t.integer "user_id"
@ -146,7 +144,6 @@ ActiveRecord::Schema.define(:version => 20120506053156) do
t.string "target_type", :limit => 60, :null => false
end
add_index "likes", ["author_id"], :name => "likes_author_id_fk"
add_index "likes", ["guid"], :name => "index_likes_on_guid", :unique => true
add_index "likes", ["target_id", "author_id", "target_type"], :name => "index_likes_on_target_id_and_author_id_and_target_type", :unique => true
add_index "likes", ["target_id"], :name => "index_likes_on_post_id"
@ -172,7 +169,6 @@ ActiveRecord::Schema.define(:version => 20120506053156) do
end
add_index "messages", ["author_id"], :name => "index_messages_on_author_id"
add_index "messages", ["conversation_id"], :name => "messages_conversation_id_fk"
create_table "notification_actors", :force => true do |t|
t.integer "notification_id"
@ -204,7 +200,7 @@ ActiveRecord::Schema.define(:version => 20120506053156) do
t.text "data", :null => false
end
add_index "o_embed_caches", ["url"], :name => "index_o_embed_caches_on_url", :length => {"url"=>255}
add_index "o_embed_caches", ["url"], :name => "index_o_embed_caches_on_url"
create_table "oauth_access_tokens", :force => true do |t|
t.integer "authorization_id", :null => false

View file

@ -41,17 +41,6 @@ connect_users(bob, bob.aspects.first, alice, alice.aspects.first)
connect_users(bob, bob.aspects.first, eve, eve.aspects.first)
puts "done!"
print "Adding Facebook contacts... "
bob_facebook = Factory(:service, :type => 'Services::Facebook', :user_id => bob.id, :uid => bob.username)
ServiceUser.import((1..40).map{|n| Factory.build(:service_user, :service => bob_facebook)} +
[Factory.build(:service_user, :service => bob_facebook, :uid => eve.username, :person => eve.person,
:contact => bob.contact_for(eve.person))])
eve_facebook = Factory(:service, :type => 'Services::Facebook', :user_id => eve.id, :uid => eve.username)
ServiceUser.import((1..40).map{|n| Factory.build(:service_user, :service => eve_facebook) } +
[Factory.build(:service_user, :service => eve_facebook, :uid => bob.username, :person => bob.person,
:contact => eve.contact_for(bob.person))])
puts "done!"

View file

@ -30,11 +30,4 @@ module Jobs
# don't post to services in cucumber
end
end
class UpdateServiceUsers < Base
@queue = :http_service
def self.perform(service_id)
# don't update services in cucumber
end
end
end
end

View file

@ -107,28 +107,4 @@ describe ServicesController do
end
end
describe '#finder' do
before do
@service1 = Services::Facebook.new
@user.services << @service1
@person = Factory(:person)
@user.services.stub!(:where).and_return([@service1])
@service_users = [ ServiceUser.create(:contact => @user.contact_for(bob.person), :name => "Robert Bobson", :photo_url => "cdn1.fb.com/pic1.jpg",
:service => @service1, :uid => "321" ).tap{|su| su.stub!(:person).and_return(bob.person)},
ServiceUser.create(:name => "Eve Doe", :photo_url => "cdn1.fb.com/pic1.jpg", :person => eve.person, :service => @service1,
:uid => 'sdfae').tap{|su| su.stub!(:person).and_return(eve.person)},
ServiceUser.create(:name => "Robert Bobson", :photo_url => "cdn1.fb.com/pic1.jpg", :service => @service1, :uid => "dsfasdfas")]
@service1.should_receive(:finder).and_return(@service_users)
end
it 'calls the finder method for the service for that user' do
get :finder, :provider => @service1.provider
response.should be_success
end
it 'has no translations missing' do
get :finder, :provider => @service1.provider
Nokogiri(response.body).css('.translation_missing').should be_empty
end
end
end

View file

@ -30,14 +30,6 @@ describe SessionsController do
response.should be_redirect
response.location.should match /^#{root_url}\??$/
end
it 'queues up an update job' do
service = Services::Facebook.new(:access_token => "yeah")
@user.services << service
Resque.should_receive(:enqueue).with(Jobs::UpdateServiceUsers, service.id)
post :create, {"user" => {"remember_me" => "0", "username" => @user.username, "password" => "evankorth"}}
end
end
describe "#destroy" do

View file

@ -1,18 +0,0 @@
require 'spec_helper'
describe Jobs::UpdateServiceUsers do
before do
@user = alice
@post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id)
@service = Services::Facebook.new(:access_token => "yeah")
@user.services << @service
end
it 'calls the update_friends for the service' do
Service.stub!(:find).and_return(@service)
@service.should_receive(:save_friends)
Jobs::UpdateServiceUsers.perform(@service.id)
end
end

View file

@ -18,17 +18,6 @@ describe Service do
alice.services.last.should be_invalid
end
it 'destroys the associated service_user' do
@service.service_users = [ServiceUser.create(:service_id => @service.id,
:uid => "abc123",
:photo_url => "a.jpg",
:name => "a",
:person_id => bob.person.id)]
lambda{
@service.destroy
}.should change(ServiceUser, :count).by(-1)
end
it 'by default has no profile photo url' do
Service.new.profile_photo_url.should be_nil
end

View file

@ -1,130 +0,0 @@
require 'spec_helper'
describe ServiceUser do
context 'scope' do
before do
@user = alice
@service = Services::Facebook.new(:access_token => "yeah")
@user.services << @service
@user2 = Factory(:user_with_aspect)
@user2_fb_id = '820651'
@user2_fb_name = 'Maxwell Salzberg'
@user2_fb_photo_url = 'http://cdn.fn.com/pic1.jpg'
@user2_service = Services::Facebook.create(:uid => @user2_fb_id, :access_token => "yo", :user_id => @user2.id)
@su = ServiceUser.new(:service_id => @service.id, :uid => @user2_fb_id, :name => @user2_fb_name,:photo_url => @user2_fb_photo_url)
@su.person = @user2.person
@su.save
end
describe 'with_local_people' do
it 'returns services with local people' do
ServiceUser.with_local_people.count.should == 1
ServiceUser.with_remote_people.count.should == 0
end
end
describe 'with_remote_people' do
it 'returns services with remote people' do
@user2_service.delete
p = @user2.person
p.owner_id = nil
p.save
ServiceUser.with_local_people.count.should == 0
ServiceUser.with_remote_people.count.should == 1
end
end
end
describe '#finder' do
before do
@user = alice
@post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id)
@service = Services::Facebook.new(:access_token => "yeah")
@user.services << @service
@user2 = Factory(:user_with_aspect)
@user2_fb_id = '820651'
@user2_fb_name = 'Maxwell Salzberg'
@user2_fb_photo_url = 'http://cdn.fn.com/pic1.jpg'
@user2_service = Services::Facebook.new(:uid => @user2_fb_id, :access_token => "yo")
@user2.services << @user2_service
@fb_list_hash = <<JSON
{
"data": [
{
"name": "#{@user2_fb_name}",
"id": "#{@user2_fb_id}",
"picture": ""
},
{
"name": "Person to Invite",
"id": "abc123",
"picture": "http://cdn.fn.com/pic1.jpg"
}
]
}
JSON
@web_mock = mock()
@web_mock.stub!(:body).and_return(@fb_list_hash)
RestClient.stub!(:get).and_return(@web_mock)
end
context 'lifecycle callbacks' do
before do
@su = ServiceUser.create(:service_id => @service.id, :uid => @user2_fb_id, :name => @user2_fb_name,
:photo_url => @user2_fb_photo_url)
end
it 'contains a name' do
@su.name.should == @user2_fb_name
end
it 'contains a photo url' do
@su.photo_url.should == @user2_fb_photo_url
end
it 'contains a FB id' do
@su.uid.should == @user2_fb_id
end
it 'contains a diaspora person object' do
@su.person.should == @user2.person
end
it 'queries for the correct service type' do
Services::Facebook.should_receive(:where).with(hash_including({:type => "Services::Facebook"})).and_return([])
@su.send(:attach_local_models)
end
it 'does not include the person if the search is disabled' do
p = @user2.person.profile
p.searchable = false
p.save
@su.save
@su.person.should be_nil
end
it 'contains a contact object if connected' do
connect_users(@user, @user.aspects.first, @user2, @user2.aspects.first)
@su.save
@su.contact.should == @user.reload.contact_for(@user2.person)
end
context 'already invited' do
before do
@user2.invitation_service = 'facebook'
@user2.invitation_identifier = @user2_fb_id
@user2.save!
end
it 'contains an invitation if invited' do
@inv = Invitation.create(:sender => @user, :recipient => @user2, :aspect => @user.aspects.first)
@su.save
@su.invitation_id.should == @inv.id
end
it 'does not find the user with a wrong identifier' do
@user2.invitation_identifier = 'dsaofhnadsoifnsdanf'
@user2.save
@inv = Invitation.create(:sender => @user, :recipient => @user2, :aspect => @user.aspects.first)
@su.save
@su.invitation_id.should be_nil
end
end
end
end
end

View file

@ -33,92 +33,6 @@ describe Services::Facebook do
end
end
context 'finder' do
before do
@user2 = Factory(:user_with_aspect)
@user2_fb_id = '820651'
@user2_fb_name = 'Maxwell Salzberg'
@user2_fb_photo_url = "http://cdn.fn.com/pic1.jpg"
@user2_service = Services::Facebook.new(:uid => @user2_fb_id, :access_token => "yo")
@user2.services << @user2_service
@fb_list_hash = <<JSON
{
"data": [
{
"name": "#{@user2_fb_name}",
"id": "#{@user2_fb_id}",
"picture": "#{@user2_fb_photo_url}"
},
{
"name": "Person to Invite",
"id": "abc123",
"picture": "http://cdn.fn.com/pic1.jpg"
}
]
}
JSON
stub_request(:get, "https://graph.facebook.com/me/friends?fields[]=name&fields[]=picture&access_token=yeah").
to_return(:body => @fb_list_hash)
end
describe '#save_friends' do
it 'requests a friend list' do
@service.save_friends
WebMock.should have_requested(:get, "https://graph.facebook.com/me/friends?fields[]=name&fields[]=picture&access_token=yeah")
end
it 'creates a service user objects' do
lambda{
@service.save_friends
}.should change(ServiceUser, :count).by(2)
end
it 'attaches local models' do
@service.save_friends
@service.service_users.where(:uid => @user2_fb_id).first.person.should == @user2.person
end
it 'overwrites local model information' do
@service.save_friends
su = @service.service_users.where(:uid => @user2_fb_id).first
su.person.should == @user2.person
su.contact.should == nil
connect_users_with_aspects(alice, @user2)
@service.save_friends
su.person.should == @user2.person
su.reload.contact.should == alice.contact_for(@user2.person)
end
end
describe '#finder' do
it 'does a synchronous call if it has not been called before' do
Resque.should_receive(:enqueue).with(Jobs::UpdateServiceUsers, @service.id)
@service.finder
end
context 'opts' do
it 'only local does not return people who are remote' do
@service.save_friends
@service.finder(:local => true).all.each{|su| su.person.should == @user2.person}
end
it 'does not return people who are remote' do
@service.save_friends
@service.finder(:remote => true).all.each{|su| su.person.should be_nil}
end
it 'does not return wrong service objects' do
su2 = ServiceUser.create(:service => @user2_service, :uid => @user2_fb_id, :name => @user2_fb_name, :photo_url => @user2_fb_photo_url)
su2.person.should == @user2.person
@service.finder(:local => true).all.each{|su| su.service.should == @service}
@service.finder(:remote => true).all.each{|su| su.service.should == @service}
@service.finder.each{|su| su.service.should == @service}
end
end
end
end
describe "#profile_photo_url" do
it 'returns a large profile photo url' do
@service.uid = "abc123"