jsmestad-frankie 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ doc
2
+ pkg
3
+ *.log
data/CHANGELOG ADDED
@@ -0,0 +1,11 @@
1
+ v0.3.0 Updated to work with Sinatra 0.9.x and facebooker 1.0.2, thanks to mjfreshyfresh
2
+
3
+ v0.2.5. Bugfix for fb_url_for helper method
4
+
5
+ v0.2.4. Add fb_url_for helper method to create link URL's that have proper Facebook application reference included
6
+
7
+ v0.2.3. Correct README and fix Sinatra version dependency in gem
8
+
9
+ v0.2.2. Updated to deal with session change in Sinatra, plus misc bug fixes with Facebooker integration
10
+
11
+ v0.2.0. Converted codebase to become Ruby Gem
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Ron Evans
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ bin/tunnel
2
+ CHANGELOG
3
+ lib/frankie.rb
4
+ LICENSE
5
+ Manifest
6
+ Rakefile
7
+ README.rdoc
8
+ test/frankie_test.rb
9
+ test/helper.rb
data/README.rdoc ADDED
@@ -0,0 +1,79 @@
1
+ = Frankie
2
+
3
+ Frankie (http://facethesinatra.com) is a plugin for the Sinatra web framework (http://sinatrarb.com) that allows you to easily create a Facebook application by using the Facebooker gem.
4
+
5
+ Written by Ron Evans (http://www.deadprogrammersociety.com)
6
+
7
+ Based on merb_facebooker (http://github.com/vanpelt/merb_facebooker) by Chris Van Pelt, which was based on
8
+ the Rails classes in Facebooker (http://facebooker.rubyforge.org/) by Mike Mangino, Shane Vitarana, & Chad Fowler
9
+
10
+ 2/20/2009 - Now updated to Sinatra 0.9 and facebooker thanks to mjfreshyfresh.
11
+
12
+ Thanks, everyone!
13
+
14
+ = Here is a very simple example application:
15
+
16
+ require 'rubygems'
17
+ require 'frankie'
18
+
19
+ configure do
20
+ set_option :sessions, true
21
+ load_facebook_config "./config/facebooker.yml", Sinatra.env
22
+ end
23
+
24
+ ## facebooker helpers
25
+ before do
26
+ ensure_authenticated_to_facebook
27
+ ensure_application_is_installed_by_facebook_user
28
+ end
29
+
30
+ ## the site
31
+ get '/' do
32
+ body "<h1>Hello #{session[:facebook_session].user.name} and welcome to frankie!</h1>"
33
+ end
34
+
35
+
36
+ = How to use frankie
37
+ - Install the frankie gem (which will install both Sinatra and Facebooker if you do not already have them)
38
+ sudo gem install frankie
39
+
40
+ - Create the application directories for your new app
41
+ mkdir myapp
42
+ cd myapp
43
+ mkdir config
44
+
45
+ - Put your facebooker.yml file into the /myapp/config directory, and set the values to your information. Here is a simple example of the file:
46
+
47
+ development:
48
+ api_key: apikeyhere
49
+ secret_key: secretkeyhere
50
+ canvas_page_name: yourcanvashere
51
+ callback_url: http://localhost:4567
52
+ test:
53
+ api_key: apikeyhere
54
+ secret_key: secretkeyhere
55
+ canvas_page_name: yourcanvashere
56
+ callback_url: http://localhost:4567
57
+ production:
58
+ api_key: apikeyhere
59
+ secret_key: secretkeyhere
60
+ canvas_page_name: yourcanvashere
61
+ callback_url: http://yourrealserver.com
62
+
63
+
64
+ - Make sure you have setup your Facebook application on the facebook site. Google "setup new facebook application" if you are unsure how to do this. I recommend starting with an IFrame application. A more advanced and cooler approach uses a tunneling script, which is included with Frankie. You do need to have "autossh" installed in order to use it, as well as a publicly addressable server. From a command prompt type tunnel <host> <remote_port> <local_port> like this:
65
+
66
+ tunnel app.myhost.com 10000 4567
67
+
68
+ You will also need to make sure your server's /etc/ssh/sshd_config contains the following line:
69
+
70
+ GatewayPorts clientspecified
71
+
72
+ Thanks to the many people like Evan Weaver, Blake Mizerany, and whoever else that have provided the code used in this tunneling script.
73
+
74
+ - Create your application, based on the sample above, and then run it:
75
+ ruby sample.rb
76
+
77
+ - Test your app by going to http://apps.facebook.com/yourappname
78
+
79
+ Have fun!
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+ require 'spec/rake/spectask'
5
+
6
+ task :default => :test
7
+
8
+ GEM = "frankie"
9
+ AUTHORS = ["Ron Evans", "Justin Smestad"]
10
+ EMAIL = "justin.smestad@gmail.com"
11
+ HOMEPAGE = "http://facethesinatra.com"
12
+ SUMMARY = "Easy creation of Facebook applications in Ruby using plugin for Sinatra web framework that integrates with Facebooker gem."
13
+
14
+ begin
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = GEM
18
+ gem.summary = SUMMARY
19
+ gem.email = EMAIL
20
+ gem.homepage = HOMEPAGE
21
+ gem.authors = AUTHORS
22
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
23
+
24
+ gem.add_dependency "sinatra", ">= 0.9.2"
25
+ gem.add_dependency 'facebooker', ">= 0.9.5"
26
+ end
27
+ rescue LoadError
28
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
29
+ end
30
+
31
+ Rake::TestTask.new do |t|
32
+ ENV['SINATRA_ENV'] = 'test'
33
+ t.pattern = File.dirname(__FILE__) + "/test/*_test.rb"
34
+ end
35
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.0
data/bin/tunnel ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ host, remote_port, local_port = ARGV
4
+ raise 'You must specify at least a hostname - i.e. tunnel myhost.com' unless host
5
+ remote_port ||= 10000
6
+ local_port ||= 4567
7
+ puts "Tunneling #{host}:#{remote_port} to 0.0.0.0:#{local_port}"
8
+ begin
9
+ exec "autossh -M 48484 -nNT -g -R *:#{remote_port}:0.0.0.0:#{local_port} #{host}"
10
+ rescue
11
+ raise "Tunnel failed to start. Do you have autossh installed?"
12
+ end
data/frankie.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{frankie}
5
+ s.version = "0.4.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ron Evans", "Justin Smestad"]
9
+ s.date = %q{2009-06-25}
10
+ s.default_executable = %q{tunnel}
11
+ s.email = %q{justin.smestad@gmail.com}
12
+ s.executables = ["tunnel"]
13
+ s.extra_rdoc_files = [
14
+ "LICENSE",
15
+ "README.rdoc"
16
+ ]
17
+ s.files = [
18
+ ".DS_Store",
19
+ ".gitignore",
20
+ "CHANGELOG",
21
+ "LICENSE",
22
+ "Manifest",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/tunnel",
27
+ "frankie.gemspec",
28
+ "lib/frankie.rb",
29
+ "test/frankie_test.rb",
30
+ "test/helper.rb"
31
+ ]
32
+ s.homepage = %q{http://facethesinatra.com}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.4}
36
+ s.summary = %q{Easy creation of Facebook applications in Ruby using plugin for Sinatra web framework that integrates with Facebooker gem.}
37
+ s.test_files = [
38
+ "test/frankie_test.rb",
39
+ "test/helper.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<sinatra>, [">= 0.9.2"])
48
+ s.add_runtime_dependency(%q<facebooker>, [">= 0.9.5"])
49
+ else
50
+ s.add_dependency(%q<sinatra>, [">= 0.9.2"])
51
+ s.add_dependency(%q<facebooker>, [">= 0.9.5"])
52
+ end
53
+ else
54
+ s.add_dependency(%q<sinatra>, [">= 0.9.2"])
55
+ s.add_dependency(%q<facebooker>, [">= 0.9.5"])
56
+ end
57
+ end
data/lib/frankie.rb ADDED
@@ -0,0 +1,191 @@
1
+ # frankie - a plugin for sinatra that integrates with the facebooker gem
2
+ #
3
+ # written by Ron Evans (http://www.deadprogrammersociety.com)
4
+ #
5
+ # based on merb_facebooker (http://github.com/vanpelt/merb_facebooker)
6
+ # and the Rails classes in Facebooker (http://facebooker.rubyforge.org/) from Mike Mangino, Shane Vitarana, & Chad Fowler
7
+ #
8
+
9
+ require 'sinatra/base'
10
+ require 'yaml'
11
+ require 'uri'
12
+ gem 'mmangino-facebooker'
13
+ require 'facebooker'
14
+
15
+ module Frankie
16
+
17
+ module Configure
18
+ def load_facebook_config(file, env=:development)
19
+ if File.exist?(file)
20
+ yaml = YAML.load_file(file)[env.to_s]
21
+ ENV['FACEBOOK_API_KEY'] = yaml['api_key']
22
+ ENV['FACEBOOK_SECRET_KEY'] = yaml['secret_key']
23
+ ENV['FACEBOOKER_RELATIVE_URL_ROOT'] = yaml['canvas_page_name']
24
+ end
25
+ end
26
+ end
27
+
28
+ module Helpers
29
+ def facebook_session
30
+ @facebook_session
31
+ end
32
+
33
+ def facebook_session_parameters
34
+ {:fb_sig_session_key=>params["fb_sig_session_key"]}
35
+ end
36
+
37
+ def set_facebook_session
38
+ session_set = session_already_secured? || secure_with_token! || secure_with_facebook_params!
39
+ if session_set
40
+ capture_facebook_friends_if_available!
41
+ Facebooker::Session.current = facebook_session
42
+ end
43
+ session_set
44
+ end
45
+
46
+ def facebook_params
47
+ @facebook_params ||= verified_facebook_params
48
+ end
49
+
50
+ private
51
+
52
+ def session_already_secured?
53
+ (@facebook_session = session[:facebook_session]) && session[:facebook_session].secured?
54
+ end
55
+
56
+ def secure_with_token!
57
+ if params['auth_token']
58
+ @facebook_session = new_facebook_session
59
+ @facebook_session.auth_token = params['auth_token']
60
+ @facebook_session.secure!
61
+ session[:facebook_session] = @facebook_session
62
+ end
63
+ end
64
+
65
+ def secure_with_facebook_params!
66
+ return unless request_is_for_a_facebook_canvas?
67
+
68
+ if ['user', 'session_key'].all? {|element| facebook_params[element]}
69
+ @facebook_session = new_facebook_session
70
+ @facebook_session.secure_with!(facebook_params['session_key'], facebook_params['user'], facebook_params['expires'])
71
+ session[:facebook_session] = @facebook_session
72
+ end
73
+ end
74
+
75
+ def create_new_facebook_session_and_redirect!
76
+ session[:facebook_session] = new_facebook_session
77
+ throw :halt, do_redirect(session[:facebook_session].login_url) unless @installation_required
78
+ end
79
+
80
+ def new_facebook_session
81
+ Facebooker::Session.create(Facebooker::Session.api_key, Facebooker::Session.secret_key)
82
+ end
83
+
84
+ def capture_facebook_friends_if_available!
85
+ return unless request_is_for_a_facebook_canvas?
86
+ if friends = facebook_params['friends']
87
+ facebook_session.user.friends = friends.map do |friend_uid|
88
+ Facebooker::User.new(friend_uid, facebook_session)
89
+ end
90
+ end
91
+ end
92
+
93
+ def blank?(value)
94
+ (value == '0' || value.nil? || value == '')
95
+ end
96
+
97
+ def verified_facebook_params
98
+ facebook_sig_params = params.inject({}) do |collection, pair|
99
+ collection[pair.first.sub(/^fb_sig_/, '')] = pair.last if pair.first[0,7] == 'fb_sig_'
100
+ collection
101
+ end
102
+ verify_signature(facebook_sig_params, params['fb_sig'])
103
+ facebook_sig_params.inject(Hash.new) do |collection, pair|
104
+ collection[pair.first] = facebook_parameter_conversions[pair.first].call(pair.last)
105
+ collection
106
+ end
107
+ end
108
+
109
+ # 48.hours.ago in sinatra
110
+ def earliest_valid_session
111
+ now = Time.now
112
+ now -= (60 * 60 * 48)
113
+ now
114
+ end
115
+
116
+ def verify_signature(facebook_sig_params,expected_signature)
117
+ raw_string = facebook_sig_params.map{ |*args| args.join('=') }.sort.join
118
+ actual_sig = Digest::MD5.hexdigest([raw_string, Facebooker::Session.secret_key].join)
119
+ raise Facebooker::Session::IncorrectSignature if actual_sig != expected_signature
120
+ raise Facebooker::Session::SignatureTooOld if Time.at(facebook_sig_params['time'].to_f) < earliest_valid_session
121
+ true
122
+ end
123
+
124
+ def facebook_parameter_conversions
125
+ @facebook_parameter_conversions ||= Hash.new do |hash, key|
126
+ lambda{|value| value}
127
+ end.merge(
128
+ 'time' => lambda{|value| Time.at(value.to_f)},
129
+ 'in_canvas' => lambda{|value| !blank?(value)},
130
+ 'added' => lambda{|value| !blank?(value)},
131
+ 'expires' => lambda{|value| blank?(value) ? nil : Time.at(value.to_f)},
132
+ 'friends' => lambda{|value| value.split(/,/)}
133
+ )
134
+ end
135
+
136
+ def do_redirect(*args)
137
+ if request_is_for_a_facebook_canvas?
138
+ fbml_redirect_tag(args)
139
+ else
140
+ redirect args[0]
141
+ end
142
+ end
143
+
144
+ def fbml_redirect_tag(url)
145
+ "<fb:redirect url=\"#{url}\" />"
146
+ end
147
+
148
+ def request_is_for_a_facebook_canvas?
149
+ return false if params["fb_sig_in_canvas"].nil?
150
+ params["fb_sig_in_canvas"] == "1"
151
+ end
152
+
153
+ def application_is_installed?
154
+ facebook_params['added']
155
+ end
156
+
157
+ def ensure_authenticated_to_facebook
158
+ set_facebook_session || create_new_facebook_session_and_redirect!
159
+ end
160
+
161
+ def ensure_application_is_installed_by_facebook_user
162
+ @installation_required = true
163
+ authenticated_and_installed = ensure_authenticated_to_facebook && application_is_installed?
164
+ application_is_not_installed_by_facebook_user unless authenticated_and_installed
165
+ authenticated_and_installed
166
+ end
167
+
168
+ def application_is_not_installed_by_facebook_user
169
+ throw :halt, do_redirect(session[:facebook_session].install_url)
170
+ end
171
+
172
+ def set_fbml_format
173
+ params['format']="fbml" if request_is_for_a_facebook_canvas?
174
+ end
175
+
176
+ def fb_url_for(url)
177
+ url = "" if url == "/"
178
+ url = URI.escape(url)
179
+ return url if !request_is_for_a_facebook_canvas?
180
+ "http://apps.facebook.com/#{ENV['FACEBOOKER_RELATIVE_URL_ROOT']}/#{url}"
181
+ end
182
+ end
183
+
184
+ def self.registered(app)
185
+ app.configure Frankie::Configure
186
+ app.helpers Frankie::Helpers
187
+ end
188
+
189
+ end
190
+
191
+ Sinatra::Base.register Frankie
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "frankie" do
4
+ it "should be a placeholder for a real test" do
5
+ end
6
+ end
7
+
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require File.dirname(__FILE__) + '/../lib/frankie'
4
+ require 'sinatra/test/spec'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsmestad-frankie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Ron Evans
8
+ - Justin Smestad
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-06-25 00:00:00 -07:00
14
+ default_executable: tunnel
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: sinatra
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.9.2
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: facebooker
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.9.5
35
+ version:
36
+ description:
37
+ email: justin.smestad@gmail.com
38
+ executables:
39
+ - tunnel
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - LICENSE
44
+ - README.rdoc
45
+ files:
46
+ - .DS_Store
47
+ - .gitignore
48
+ - CHANGELOG
49
+ - LICENSE
50
+ - Manifest
51
+ - README.rdoc
52
+ - Rakefile
53
+ - VERSION
54
+ - bin/tunnel
55
+ - frankie.gemspec
56
+ - lib/frankie.rb
57
+ - test/frankie_test.rb
58
+ - test/helper.rb
59
+ has_rdoc: false
60
+ homepage: http://facethesinatra.com
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.2.0
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Easy creation of Facebook applications in Ruby using plugin for Sinatra web framework that integrates with Facebooker gem.
85
+ test_files:
86
+ - test/frankie_test.rb
87
+ - test/helper.rb