fbdoorman 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +3 -0
- data/LICENSE +21 -0
- data/README.md +142 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/app/controllers/clearance/confirmations_controller.rb +76 -0
- data/app/controllers/clearance/facebook_controller.rb +66 -0
- data/app/controllers/clearance/passwords_controller.rb +85 -0
- data/app/controllers/clearance/sessions_controller.rb +67 -0
- data/app/controllers/clearance/users_controller.rb +36 -0
- data/app/models/clearance_mailer.rb +21 -0
- data/app/views/clearance_mailer/change_password.html.erb +9 -0
- data/app/views/clearance_mailer/confirmation.html.erb +5 -0
- data/app/views/facebook/_fbjs.html.erb +14 -0
- data/app/views/facebook/closed.html.erb +1 -0
- data/app/views/passwords/edit.html.erb +23 -0
- data/app/views/passwords/new.html.erb +15 -0
- data/app/views/sessions/new.html.erb +25 -0
- data/app/views/users/_form.html.erb +13 -0
- data/app/views/users/new.html.erb +6 -0
- data/generators/fbdoorman/USAGE +1 -0
- data/generators/fbdoorman/fbdoorman_generator.rb +68 -0
- data/generators/fbdoorman/lib/insert_commands.rb +33 -0
- data/generators/fbdoorman/lib/rake_commands.rb +22 -0
- data/generators/fbdoorman/templates/README +43 -0
- data/generators/fbdoorman/templates/clearance.rb +3 -0
- data/generators/fbdoorman/templates/facebook.yml +7 -0
- data/generators/fbdoorman/templates/factories.rb +13 -0
- data/generators/fbdoorman/templates/migrations/create_users.rb +24 -0
- data/generators/fbdoorman/templates/migrations/update_users.rb +44 -0
- data/generators/fbdoorman/templates/user.rb +3 -0
- data/lib/clearance/authentication.rb +143 -0
- data/lib/clearance/configuration.rb +25 -0
- data/lib/clearance/extensions/errors.rb +6 -0
- data/lib/clearance/extensions/rescue.rb +5 -0
- data/lib/clearance/routes.rb +55 -0
- data/lib/clearance/user.rb +207 -0
- data/lib/facebook_helpers.rb +48 -0
- data/lib/fbdoorman.rb +27 -0
- data/lib/mini_fb.rb +673 -0
- data/rails/init.rb +1 -0
- metadata +110 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module Clearance
|
4
|
+
module User
|
5
|
+
|
6
|
+
# Hook for all Clearance::User modules.
|
7
|
+
#
|
8
|
+
# If you need to override parts of Clearance::User,
|
9
|
+
# extend and include à la carte.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# extend ClassMethods
|
13
|
+
# include InstanceMethods
|
14
|
+
# include AttrAccessor
|
15
|
+
# include Callbacks
|
16
|
+
#
|
17
|
+
# @see ClassMethods
|
18
|
+
# @see InstanceMethods
|
19
|
+
# @see AttrAccessible
|
20
|
+
# @see AttrAccessor
|
21
|
+
# @see Validations
|
22
|
+
# @see Callbacks
|
23
|
+
def self.included(model)
|
24
|
+
model.extend(ClassMethods)
|
25
|
+
|
26
|
+
model.send(:include, InstanceMethods)
|
27
|
+
model.send(:include, AttrAccessor)
|
28
|
+
model.send(:include, Validations)
|
29
|
+
model.send(:include, Callbacks)
|
30
|
+
end
|
31
|
+
|
32
|
+
module AttrAccessor
|
33
|
+
# Hook for attr_accessor virtual attributes.
|
34
|
+
#
|
35
|
+
# :password, :password_confirmation
|
36
|
+
def self.included(model)
|
37
|
+
model.class_eval do
|
38
|
+
attr_accessor :password, :password_confirmation
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Validations
|
44
|
+
# Hook for validations.
|
45
|
+
#
|
46
|
+
# :email must be present, unique, formatted
|
47
|
+
#
|
48
|
+
# If password is required,
|
49
|
+
# :password must be present, confirmed
|
50
|
+
def self.included(model)
|
51
|
+
model.class_eval do
|
52
|
+
validates_presence_of :email, :unless => Proc.new { |user| !user.fbid.blank? }
|
53
|
+
validates_uniqueness_of :email, :case_sensitive => false, :allow_blank => true
|
54
|
+
validates_uniqueness_of :fbid, :unless => Proc.new { |user| user.fbid.blank? }
|
55
|
+
validates_format_of :email, :with => %r{.+@.+\..+}, :allow_blank => true
|
56
|
+
|
57
|
+
validates_presence_of :password, :unless => Proc.new { |user| !user.fbid.blank? } #:unless => :password_optional?
|
58
|
+
validates_confirmation_of :password, :unless => Proc.new { |user| !user.fbid.blank? }#:unless => :password_optional?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module Callbacks
|
64
|
+
# Hook for callbacks.
|
65
|
+
#
|
66
|
+
# salt, token, password encryption are handled before_save.
|
67
|
+
def self.included(model)
|
68
|
+
model.class_eval do
|
69
|
+
before_save :initialize_salt, :encrypt_password, :unless => Proc.new { |user| !user.fbid.blank? }
|
70
|
+
before_create :generate_confirmation_token,
|
71
|
+
:generate_remember_token
|
72
|
+
after_create :send_confirmation_email, :unless => (:email_confirmed? or Proc.new { |user| !user.fbid.blank? })
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module InstanceMethods
|
78
|
+
# Am I authenticated with given password?
|
79
|
+
#
|
80
|
+
# @param [String] plain-text password
|
81
|
+
# @return [true, false]
|
82
|
+
# @example
|
83
|
+
# user.authenticated?('password')
|
84
|
+
def authenticated?(password)
|
85
|
+
encrypted_password == encrypt(password)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Set the remember token.
|
89
|
+
#
|
90
|
+
# @deprecated Use {#reset_remember_token!} instead
|
91
|
+
def remember_me!
|
92
|
+
warn "[DEPRECATION] remember_me!: use reset_remember_token! instead"
|
93
|
+
reset_remember_token!
|
94
|
+
end
|
95
|
+
|
96
|
+
# Reset the remember token.
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
# user.reset_remember_token!
|
100
|
+
def reset_remember_token!
|
101
|
+
generate_remember_token
|
102
|
+
save(false)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Confirm my email.
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
# user.confirm_email!
|
109
|
+
def confirm_email!
|
110
|
+
self.email_confirmed = true
|
111
|
+
self.confirmation_token = nil
|
112
|
+
save(false)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Mark my account as forgotten password.
|
116
|
+
#
|
117
|
+
# @example
|
118
|
+
# user.forgot_password!
|
119
|
+
def forgot_password!
|
120
|
+
generate_confirmation_token
|
121
|
+
save(false)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Update my password.
|
125
|
+
#
|
126
|
+
# @param [String, String] password and password confirmation
|
127
|
+
# @return [true, false] password was updated or not
|
128
|
+
# @example
|
129
|
+
# user.update_password('new-password', 'new-password')
|
130
|
+
def update_password(new_password, new_password_confirmation)
|
131
|
+
self.password = new_password
|
132
|
+
self.password_confirmation = new_password_confirmation
|
133
|
+
if valid?
|
134
|
+
self.confirmation_token = nil
|
135
|
+
end
|
136
|
+
save
|
137
|
+
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
def generate_hash(string)
|
142
|
+
Digest::SHA1.hexdigest(string)
|
143
|
+
end
|
144
|
+
|
145
|
+
def initialize_salt
|
146
|
+
if new_record?
|
147
|
+
self.salt = generate_hash("--#{Time.now.utc}--#{password}--#{rand}--")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def encrypt_password
|
152
|
+
return if password.blank?
|
153
|
+
self.encrypted_password = encrypt(password)
|
154
|
+
end
|
155
|
+
|
156
|
+
def encrypt(string)
|
157
|
+
generate_hash("--#{salt}--#{string}--")
|
158
|
+
end
|
159
|
+
|
160
|
+
def generate_confirmation_token
|
161
|
+
self.confirmation_token = encrypt("--#{Time.now.utc}--#{password}--#{rand}--")
|
162
|
+
end
|
163
|
+
|
164
|
+
def generate_remember_token
|
165
|
+
self.remember_token = encrypt("--#{Time.now.utc}--#{encrypted_password}--#{id}--#{rand}--")
|
166
|
+
end
|
167
|
+
|
168
|
+
# Always false. Override to allow other forms of authentication
|
169
|
+
# (username, facebook, etc).
|
170
|
+
# @return [Boolean] true if the email field be left blank for this user
|
171
|
+
def email_optional?
|
172
|
+
false
|
173
|
+
end
|
174
|
+
|
175
|
+
# True if the password has been set and the password is not being
|
176
|
+
# updated. Override to allow other forms of # authentication (username,
|
177
|
+
# facebook, etc).
|
178
|
+
# @return [Boolean] true if the password field can be left blank for this user
|
179
|
+
def password_optional?
|
180
|
+
encrypted_password.present? && password.blank?
|
181
|
+
end
|
182
|
+
|
183
|
+
def password_required?
|
184
|
+
# warn "[DEPRECATION] password_required?: use !password_optional? instead"
|
185
|
+
!password_optional?
|
186
|
+
end
|
187
|
+
|
188
|
+
def send_confirmation_email
|
189
|
+
ClearanceMailer.deliver_confirmation self
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
module ClassMethods
|
194
|
+
# Authenticate with email and password.
|
195
|
+
#
|
196
|
+
# @param [String, String] email and password
|
197
|
+
# @return [User, nil] authenticated user or nil
|
198
|
+
# @example
|
199
|
+
# User.authenticate("email@example.com", "password")
|
200
|
+
def authenticate(email, password)
|
201
|
+
return nil unless user = find_by_email(email)
|
202
|
+
return user if user.authenticated?(password)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#Here I've written the code to offer methods to simplify FB connections, like login links for example
|
2
|
+
#OR methods required outside of the facebook controller inside the gem
|
3
|
+
|
4
|
+
def parse_fb_cookie
|
5
|
+
return MiniFB.parse_cookie_information FB_APP_ID, cookies
|
6
|
+
end
|
7
|
+
|
8
|
+
def user_from_fb?
|
9
|
+
if signed_in? then
|
10
|
+
return !current_user.fbid.blank? #If that's not blank then its a FB user
|
11
|
+
else return false end
|
12
|
+
end
|
13
|
+
|
14
|
+
#Si da false entonces el usuario se le deniega el acceso
|
15
|
+
def authenticated_fbu?
|
16
|
+
@fbcookie = parse_fb_cookie
|
17
|
+
if @fbcookie.nil? then return false end
|
18
|
+
begin
|
19
|
+
@uid = MiniFB.rest(@fbcookie["access_token"], "users.getLoggedInUser", {})
|
20
|
+
if @uid.to_hash["response"] == current_user.fbid then return true else return false end
|
21
|
+
rescue MiniFB::FaceBookError #Is this error happen the token expired
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
#The user is authenticated if the UID than own the token is the same as the one in current user
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_fb_cookie
|
28
|
+
cookies.delete("fbs_#{FB_APP_ID}".to_sym)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def facebook_js
|
33
|
+
render :partial => "facebook/fbjs"
|
34
|
+
end
|
35
|
+
|
36
|
+
#only shows the login button if there's no logged in user
|
37
|
+
def facebook_login
|
38
|
+
return "<fb:login-button></fb:login-button>"
|
39
|
+
end
|
40
|
+
|
41
|
+
def fb_signed_in?
|
42
|
+
if parse_fb_cookie.nil? then return false else return true end
|
43
|
+
end
|
44
|
+
|
45
|
+
#TBD: Save the url in the DB. 50x50 px
|
46
|
+
def facebook_pic_url
|
47
|
+
return "http://graph.facebook.com/#{current_user.fbid}/picture?type=square"
|
48
|
+
end
|
data/lib/fbdoorman.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'mini_fb'
|
2
|
+
require 'facebook_helpers'
|
3
|
+
require 'clearance/extensions/errors'
|
4
|
+
require 'clearance/extensions/rescue'
|
5
|
+
require 'clearance/configuration'
|
6
|
+
require 'clearance/routes'
|
7
|
+
require 'clearance/authentication'
|
8
|
+
require 'clearance/user'
|
9
|
+
|
10
|
+
|
11
|
+
#Load the configuration for miniFB
|
12
|
+
FB = YAML.load_file("#{RAILS_ROOT}/config/facebook.yml")
|
13
|
+
#Set the value in constants for easy use
|
14
|
+
FB_API_KEY = FB[:api_key]
|
15
|
+
FB_APP_ID = FB[:app_id]
|
16
|
+
FB_SECRET = FB[:secret]
|
17
|
+
|
18
|
+
#This routed will be name with clearance routes as /facebook
|
19
|
+
FB_CALLBACK_URL = "#{FB[:base_url]}/facebook"
|
20
|
+
#This routed will be name with clearance routes as /facebookclosed
|
21
|
+
FB_CLOSED_URL = "#{FB[:base_url]}/fbclosed"
|
22
|
+
|
23
|
+
FB_LOGGED_PATH = FB[:after_login_path]
|
24
|
+
FB_REGISTERED_PATH = FB[:after_register_path]
|
25
|
+
|
26
|
+
URL_AFTER_CREATE = FB[:url_after_create]
|
27
|
+
|