sinatra-authentication-oran 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/Gemfile +33 -0
  2. data/History.txt +4 -0
  3. data/Manifest +26 -0
  4. data/Rakefile +43 -0
  5. data/TODO +53 -0
  6. data/UNLICENSE +24 -0
  7. data/example/database.yml +3 -0
  8. data/example/dm_extend_app.rb +26 -0
  9. data/example/dm_sinbook.rb +56 -0
  10. data/example/extend_views/edit.haml +42 -0
  11. data/example/extend_views/index.haml +31 -0
  12. data/example/extend_views/login.haml +21 -0
  13. data/example/extend_views/show.haml +9 -0
  14. data/example/extend_views/signup.haml +30 -0
  15. data/example/mm_app.rb +22 -0
  16. data/example/tc_app.rb +16 -0
  17. data/example/tc_sinbook.rb +62 -0
  18. data/lib/models/abstract_user.rb +95 -0
  19. data/lib/models/activerecord_user.rb +56 -0
  20. data/lib/models/ar_adapter.rb +66 -0
  21. data/lib/models/datamapper_user.rb +43 -0
  22. data/lib/models/dm_adapter.rb +61 -0
  23. data/lib/models/mm_adapter.rb +65 -0
  24. data/lib/models/mongoid_adapter.rb +67 -0
  25. data/lib/models/mongoid_user.rb +42 -0
  26. data/lib/models/mongomapper_user.rb +38 -0
  27. data/lib/models/rufus_tokyo_user.rb +206 -0
  28. data/lib/models/sequel_adapter.rb +68 -0
  29. data/lib/models/sequel_user.rb +53 -0
  30. data/lib/models/tc_adapter.rb +101 -0
  31. data/lib/sinatra-authentication-o.rb +305 -0
  32. data/lib/sinatra-authentication.rb +305 -0
  33. data/lib/sinatra-authentication/models.rb +5 -0
  34. data/lib/views/edit.haml +45 -0
  35. data/lib/views/edit.slim +46 -0
  36. data/lib/views/index.haml +29 -0
  37. data/lib/views/index.slim +30 -0
  38. data/lib/views/login.haml +24 -0
  39. data/lib/views/login.slim +25 -0
  40. data/lib/views/show.haml +9 -0
  41. data/lib/views/show.slim +10 -0
  42. data/lib/views/signup.haml +28 -0
  43. data/lib/views/signup.slim +33 -0
  44. data/readme.markdown +295 -0
  45. data/sinatra-authentication-oran.gemspec +137 -0
  46. data/spec/run_all_specs.rb +8 -0
  47. data/spec/unit/ar_model_spec.rb +3 -0
  48. data/spec/unit/dm_model_spec.rb +3 -0
  49. data/spec/unit/mm_model_spec.rb +3 -0
  50. data/spec/unit/mongoid_model_spec.rb +3 -0
  51. data/spec/unit/sequel_model_spec.rb +10 -0
  52. data/spec/unit/tc_model_spec.rb +3 -0
  53. data/spec/unit/user_specs.rb +119 -0
  54. data/test/activerecord_test.rb +5 -0
  55. data/test/datamapper_test.rb +5 -0
  56. data/test/lib/ar_app.rb +27 -0
  57. data/test/lib/dm_app.rb +20 -0
  58. data/test/lib/dm_extend_app.rb +27 -0
  59. data/test/lib/dm_sinbook.rb +54 -0
  60. data/test/lib/extend_views/edit.haml +46 -0
  61. data/test/lib/extend_views/index.haml +31 -0
  62. data/test/lib/extend_views/login.haml +21 -0
  63. data/test/lib/extend_views/show.haml +9 -0
  64. data/test/lib/extend_views/signup.haml +29 -0
  65. data/test/lib/helper.rb +16 -0
  66. data/test/lib/mm_app.rb +24 -0
  67. data/test/lib/mongoid_app.rb +28 -0
  68. data/test/lib/sequel_app.rb +21 -0
  69. data/test/lib/tc_app.rb +17 -0
  70. data/test/lib/tc_sinbook.rb +61 -0
  71. data/test/mongoid_test.rb +5 -0
  72. data/test/mongomapper_test.rb +40 -0
  73. data/test/route_tests.rb +29 -0
  74. data/test/rufus_tokyo_test.rb +5 -0
  75. data/test/sequel_test.rb +5 -0
  76. metadata +220 -0
@@ -0,0 +1,101 @@
1
+ module TcAdapter
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ base.class_eval {
5
+ include TcAdapter::InstanceMethods
6
+ alias :class_id :id
7
+ }
8
+ end
9
+
10
+ module ClassMethods
11
+ #TODO add pagination
12
+ def all
13
+ result = TcUser.query do |q|
14
+ q.order_by 'created_at_i', :numdesc
15
+ end
16
+
17
+ #these will be the same for all adapters, they should be defined in the user class, and these methods should have a different name?
18
+ result.collect {|instance| self.new instance }
19
+ end
20
+
21
+ def get(hash)
22
+ if hash[:id]
23
+ pk = hash[:id]
24
+ if pk.length > 0
25
+ result = TcUser.get(pk)
26
+ else
27
+ nil
28
+ end
29
+ else
30
+ result = TcUser.query do |q|
31
+ hash.each do |key, value|
32
+ q.add key.to_s, :streq, value.to_s
33
+ end
34
+ end[0]
35
+ end
36
+ #elsif hash[:email]
37
+ # result = TcUser.query do |q|
38
+ # q.add 'email', :streq, hash[:email]
39
+ # end[0]
40
+ #the zero is because this returns an array but get should return the first result
41
+ #end
42
+
43
+ if result
44
+ self.new result
45
+ else
46
+ nil
47
+ end
48
+ end
49
+
50
+ def set(attributes)
51
+ user = TcUser.query do |q|
52
+ q.add 'email', :streq, attributes['email']
53
+ end
54
+
55
+ if user == [] #no user
56
+ self.new TcUser.set(attributes)
57
+ else
58
+ if attributes['email'].length == 0
59
+ error = 'You need to provide an email address'
60
+ else
61
+ error = 'That email is already taken'
62
+ end
63
+
64
+ TcUser.new(attributes, error)
65
+ end
66
+ end
67
+
68
+ def set!(attributes)
69
+ self.new TcUser.set!(attributes)
70
+ end
71
+
72
+ def delete(pk)
73
+ #true or false
74
+ !!TcUser.delete(pk)
75
+ end
76
+ end
77
+
78
+ module InstanceMethods
79
+ def update(attributes)
80
+ @instance.update attributes
81
+ end
82
+
83
+ def errors
84
+ @instance.errors.join(', ')
85
+ end
86
+
87
+ def valid
88
+ @instance.errors.length == 0
89
+ end
90
+
91
+ def method_missing(meth, *args, &block)
92
+ #cool I just found out * on an array turn the array into a list of args for a function
93
+ @instance.send(meth, *args, &block)
94
+ end
95
+
96
+ #this was the only thing that didn't get passed on to method_missing because this is a method of object doh
97
+ def id
98
+ @instance.id
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,305 @@
1
+ require 'sinatra/base'
2
+ require File.expand_path("../models/abstract_user", __FILE__)
3
+
4
+ module Sinatra
5
+ module SinatraAuthentication
6
+ def self.registered(app)
7
+ #INVESTIGATE
8
+ #the possibility of sinatra having an array of view_paths to load from
9
+ #PROBLEM
10
+ #sinatra 9.1.1 doesn't have multiple view capability anywhere
11
+ #so to get around I have to do it totally manually by
12
+ #loading the view from this path into a string and rendering it
13
+ app.set :sinatra_authentication_view_path, File.expand_path('../views/', __FILE__)
14
+ unless defined?(options.template_engine)
15
+ app.set :template_engine, :slim
16
+ end
17
+
18
+ app.get '/users/?' do
19
+ login_required
20
+ redirect "/" unless current_user.admin?
21
+
22
+ @users = User.all
23
+ if @users != []
24
+ send options.template_engine, get_view_as_string("index.#{options.template_engine}"), :layout => use_layout?
25
+ else
26
+ redirect '/signup'
27
+ end
28
+ end
29
+
30
+ app.get '/users/:id/?' do
31
+ login_required
32
+
33
+ @user = User.get(:id => params[:id])
34
+ send options.template_engine, get_view_as_string("show.#{options.template_engine}"), :layout => use_layout?
35
+ end
36
+
37
+ #convenience for ajax but maybe entirely stupid and unnecesary
38
+ app.get '/logged_in' do
39
+ if session[:user]
40
+ "true"
41
+ else
42
+ "false"
43
+ end
44
+ end
45
+
46
+ app.get '/login/?' do
47
+ if session[:user]
48
+ redirect '/'
49
+ else
50
+ send options.template_engine, get_view_as_string("login.#{options.template_engine}"), :layout => use_layout?
51
+ end
52
+ end
53
+
54
+ app.post '/login/?' do
55
+ if user = User.authenticate(params[:name], params[:password])
56
+ session[:user] = user.id
57
+
58
+ if Rack.const_defined?('Flash')
59
+ flash[:notice] = "Login successful."
60
+ end
61
+
62
+ if session[:return_to]
63
+ redirect_url = session[:return_to]
64
+ session[:return_to] = false
65
+ redirect redirect_url
66
+ else
67
+ redirect '/'
68
+ end
69
+ else
70
+ if Rack.const_defined?('Flash')
71
+ flash[:error] = "The email or password you entered is incorrect."
72
+ end
73
+ redirect '/login'
74
+ end
75
+ end
76
+
77
+ app.get '/logout/?' do
78
+ session[:user] = nil
79
+ if Rack.const_defined?('Flash')
80
+ flash[:notice] = "Logout successful."
81
+ end
82
+ return_to = ( session[:return_to] ? session[:return_to] : '/' )
83
+ redirect return_to
84
+ end
85
+
86
+ app.get '/signup/?' do
87
+ if session[:user]
88
+ redirect '/'
89
+ else
90
+ send options.template_engine, get_view_as_string("signup.#{options.template_engine}"), :layout => use_layout?
91
+ end
92
+ end
93
+
94
+ app.post '/signup/?' do
95
+ @user = User.set(params[:user])
96
+ if @user.valid && @user.id
97
+ session[:user] = @user.id
98
+ if Rack.const_defined?('Flash')
99
+ flash[:notice] = "Account created."
100
+ end
101
+ redirect '/'
102
+ else
103
+ if Rack.const_defined?('Flash')
104
+ flash[:error] = "There were some problems creating your account: #{@user.errors}."
105
+ end
106
+ redirect '/signup?' + hash_to_query_string(params['user'])
107
+ end
108
+ end
109
+
110
+ app.get '/users/:id/edit/?' do
111
+ login_required
112
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
113
+ @user = User.get(:id => params[:id])
114
+ send options.template_engine, get_view_as_string("edit.#{options.template_engine}"), :layout => use_layout?
115
+ end
116
+
117
+ app.post '/users/:id/edit/?' do
118
+ login_required
119
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
120
+
121
+ user = User.get(:id => params[:id])
122
+ user_attributes = params[:user]
123
+ if params[:user][:password] == ""
124
+ user_attributes.delete("password")
125
+ user_attributes.delete("password_confirmation")
126
+ end
127
+
128
+ if user.update(user_attributes)
129
+ if Rack.const_defined?('Flash')
130
+ flash[:notice] = 'Account updated.'
131
+ end
132
+ redirect '/'
133
+ else
134
+ if Rack.const_defined?('Flash')
135
+ flash[:error] = "Whoops, looks like there were some problems with your updates: #{user.errors}."
136
+ end
137
+ redirect "/users/#{user.id}/edit?" + hash_to_query_string(user_attributes)
138
+ end
139
+ end
140
+
141
+ app.get '/users/:id/delete/?' do
142
+ login_required
143
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
144
+
145
+ if User.delete(params[:id])
146
+ if Rack.const_defined?('Flash')
147
+ flash[:notice] = "User deleted."
148
+ end
149
+ else
150
+ if Rack.const_defined?('Flash')
151
+ flash[:error] = "Deletion failed."
152
+ end
153
+ end
154
+ redirect '/'
155
+ end
156
+
157
+
158
+ if Sinatra.const_defined?('FacebookObject')
159
+ app.get '/connect/?' do
160
+ if fb[:user]
161
+ if current_user.class != GuestUser
162
+ user = current_user
163
+ else
164
+ user = User.get(:fb_uid => fb[:user])
165
+ end
166
+
167
+ if user
168
+ if !user.fb_uid || user.fb_uid != fb[:user]
169
+ user.update :fb_uid => fb[:user]
170
+ end
171
+ session[:user] = user.id
172
+ else
173
+ user = User.set!(:fb_uid => fb[:user])
174
+ session[:user] = user.id
175
+ end
176
+ end
177
+ redirect '/'
178
+ end
179
+
180
+ app.get '/receiver' do
181
+ %[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
182
+ <html xmlns="http://www.w3.org/1999/xhtml" >
183
+ <body>
184
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
185
+ </body>
186
+ </html>]
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ module Helpers
193
+ def hash_to_query_string(hash)
194
+ hash.collect {|k,v| "#{k}=#{v}"}.join('&')
195
+ end
196
+
197
+ def login_required
198
+ #not as efficient as checking the session. but this inits the fb_user if they are logged in
199
+ if current_user.class != GuestUser
200
+ return true
201
+ else
202
+ session[:return_to] = request.fullpath
203
+ redirect '/login'
204
+ return false
205
+ end
206
+ end
207
+
208
+ def current_user
209
+ if session[:user]
210
+ User.get(:id => session[:user])
211
+ else
212
+ GuestUser.new
213
+ end
214
+ end
215
+
216
+ def logged_in?
217
+ !!session[:user]
218
+ end
219
+
220
+ def use_layout?
221
+ !request.xhr?
222
+ end
223
+
224
+ #BECAUSE sinatra 9.1.1 can't load views from different paths properly
225
+ def get_view_as_string(filename)
226
+ view = File.join(settings.sinatra_authentication_view_path, filename)
227
+ data = ""
228
+ f = File.open(view, "r")
229
+ f.each_line do |line|
230
+ data += line
231
+ end
232
+ return data
233
+ end
234
+
235
+ def render_login_logout(html_attributes = {:class => ""})
236
+ css_classes = html_attributes.delete(:class)
237
+ parameters = ''
238
+ html_attributes.each_pair do |attribute, value|
239
+ parameters += "#{attribute}=\"#{value}\" "
240
+ end
241
+
242
+ result = "<div id='sinatra-authentication-login-logout' >"
243
+ if logged_in?
244
+ logout_parameters = html_attributes
245
+ # a tad janky?
246
+ logout_parameters.delete(:rel)
247
+ result += "<a href='/users/#{current_user.id}/edit' class='#{css_classes} sinatra-authentication-edit' #{parameters}>Edit account</a> "
248
+ if Sinatra.const_defined?('FacebookObject')
249
+ if fb[:user]
250
+ result += "<a href='javascript:FB.Connect.logoutAndRedirect(\"/logout\");' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
251
+ else
252
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
253
+ end
254
+ else
255
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
256
+ end
257
+ else
258
+ result += "<a href='/signup' class='#{css_classes} sinatra-authentication-signup' #{parameters}>Signup</a> "
259
+ result += "<a href='/login' class='#{css_classes} sinatra-authentication-login' #{parameters}>Login</a>"
260
+ end
261
+
262
+ result += "</div>"
263
+ end
264
+
265
+ if Sinatra.const_defined?('FacebookObject')
266
+ def render_facebook_connect_link(text = 'Login using facebook', options = {:size => 'small'})
267
+ if options[:size] == 'small'
268
+ size = 'Small'
269
+ elsif options[:size] == 'medium'
270
+ size = 'Medium'
271
+ elsif options[:size] == 'large'
272
+ size = 'Large'
273
+ elsif options[:size] == 'xlarge'
274
+ size = 'BigPun'
275
+ else
276
+ size = 'Small'
277
+ end
278
+
279
+ %[<a href="#" onclick="FB.Connect.requireSession(function(){document.location = '/connect';}); return false;" class="fbconnect_login_button FBConnectButton FBConnectButton_#{size}">
280
+ <span id="RES_ID_fb_login_text" class="FBConnectButton_Text">
281
+ #{text}
282
+ </span>
283
+ </a>]
284
+ end
285
+ end
286
+ end
287
+
288
+ register SinatraAuthentication
289
+ end
290
+
291
+ class GuestUser
292
+ def guest?
293
+ true
294
+ end
295
+
296
+ def permission_level
297
+ 0
298
+ end
299
+
300
+ # current_user.admin? returns false. current_user.has_a_baby? returns false.
301
+ # (which is a bit of an assumption I suppose)
302
+ def method_missing(m, *args)
303
+ return false
304
+ end
305
+ end
@@ -0,0 +1,305 @@
1
+ require 'sinatra/base'
2
+ require File.expand_path("../models/abstract_user", __FILE__)
3
+
4
+ module Sinatra
5
+ module SinatraAuthentication
6
+ def self.registered(app)
7
+ #INVESTIGATE
8
+ #the possibility of sinatra having an array of view_paths to load from
9
+ #PROBLEM
10
+ #sinatra 9.1.1 doesn't have multiple view capability anywhere
11
+ #so to get around I have to do it totally manually by
12
+ #loading the view from this path into a string and rendering it
13
+ app.set :sinatra_authentication_view_path, File.expand_path('../views/', __FILE__)
14
+ unless defined?(options.template_engine)
15
+ app.set :template_engine, :slim
16
+ end
17
+
18
+ app.get '/users/?' do
19
+ login_required
20
+ redirect "/" unless current_user.admin?
21
+
22
+ @users = User.all
23
+ if @users != []
24
+ send options.template_engine, get_view_as_string("index.#{options.template_engine}"), :layout => use_layout?
25
+ else
26
+ redirect '/signup'
27
+ end
28
+ end
29
+
30
+ app.get '/users/:id/?' do
31
+ login_required
32
+
33
+ @user = User.get(:id => params[:id])
34
+ send options.template_engine, get_view_as_string("show.#{options.template_engine}"), :layout => use_layout?
35
+ end
36
+
37
+ #convenience for ajax but maybe entirely stupid and unnecesary
38
+ app.get '/logged_in' do
39
+ if session[:user]
40
+ "true"
41
+ else
42
+ "false"
43
+ end
44
+ end
45
+
46
+ app.get '/login/?' do
47
+ if session[:user]
48
+ redirect '/'
49
+ else
50
+ send options.template_engine, get_view_as_string("login.#{options.template_engine}"), :layout => use_layout?
51
+ end
52
+ end
53
+
54
+ app.post '/login/?' do
55
+ if user = User.authenticate(params[:name], params[:password])
56
+ session[:user] = user.id
57
+
58
+ if Rack.const_defined?('Flash')
59
+ flash[:notice] = "Login successful."
60
+ end
61
+
62
+ if session[:return_to]
63
+ redirect_url = session[:return_to]
64
+ session[:return_to] = false
65
+ redirect redirect_url
66
+ else
67
+ redirect '/'
68
+ end
69
+ else
70
+ if Rack.const_defined?('Flash')
71
+ flash[:error] = "The email or password you entered is incorrect."
72
+ end
73
+ redirect '/login'
74
+ end
75
+ end
76
+
77
+ app.get '/logout/?' do
78
+ session[:user] = nil
79
+ if Rack.const_defined?('Flash')
80
+ flash[:notice] = "Logout successful."
81
+ end
82
+ return_to = ( session[:return_to] ? session[:return_to] : '/' )
83
+ redirect return_to
84
+ end
85
+
86
+ app.get '/signup/?' do
87
+ if session[:user]
88
+ redirect '/'
89
+ else
90
+ send options.template_engine, get_view_as_string("signup.#{options.template_engine}"), :layout => use_layout?
91
+ end
92
+ end
93
+
94
+ app.post '/signup/?' do
95
+ @user = User.set(params[:user])
96
+ if @user.valid && @user.id
97
+ session[:user] = @user.id
98
+ if Rack.const_defined?('Flash')
99
+ flash[:notice] = "Account created."
100
+ end
101
+ redirect '/'
102
+ else
103
+ if Rack.const_defined?('Flash')
104
+ flash[:error] = "There were some problems creating your account: #{@user.errors}."
105
+ end
106
+ redirect '/signup?' + hash_to_query_string(params['user'])
107
+ end
108
+ end
109
+
110
+ app.get '/users/:id/edit/?' do
111
+ login_required
112
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
113
+ @user = User.get(:id => params[:id])
114
+ send options.template_engine, get_view_as_string("edit.#{options.template_engine}"), :layout => use_layout?
115
+ end
116
+
117
+ app.post '/users/:id/edit/?' do
118
+ login_required
119
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
120
+
121
+ user = User.get(:id => params[:id])
122
+ user_attributes = params[:user]
123
+ if params[:user][:password] == ""
124
+ user_attributes.delete("password")
125
+ user_attributes.delete("password_confirmation")
126
+ end
127
+
128
+ if user.update(user_attributes)
129
+ if Rack.const_defined?('Flash')
130
+ flash[:notice] = 'Account updated.'
131
+ end
132
+ redirect '/'
133
+ else
134
+ if Rack.const_defined?('Flash')
135
+ flash[:error] = "Whoops, looks like there were some problems with your updates: #{user.errors}."
136
+ end
137
+ redirect "/users/#{user.id}/edit?" + hash_to_query_string(user_attributes)
138
+ end
139
+ end
140
+
141
+ app.get '/users/:id/delete/?' do
142
+ login_required
143
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
144
+
145
+ if User.delete(params[:id])
146
+ if Rack.const_defined?('Flash')
147
+ flash[:notice] = "User deleted."
148
+ end
149
+ else
150
+ if Rack.const_defined?('Flash')
151
+ flash[:error] = "Deletion failed."
152
+ end
153
+ end
154
+ redirect '/'
155
+ end
156
+
157
+
158
+ if Sinatra.const_defined?('FacebookObject')
159
+ app.get '/connect/?' do
160
+ if fb[:user]
161
+ if current_user.class != GuestUser
162
+ user = current_user
163
+ else
164
+ user = User.get(:fb_uid => fb[:user])
165
+ end
166
+
167
+ if user
168
+ if !user.fb_uid || user.fb_uid != fb[:user]
169
+ user.update :fb_uid => fb[:user]
170
+ end
171
+ session[:user] = user.id
172
+ else
173
+ user = User.set!(:fb_uid => fb[:user])
174
+ session[:user] = user.id
175
+ end
176
+ end
177
+ redirect '/'
178
+ end
179
+
180
+ app.get '/receiver' do
181
+ %[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
182
+ <html xmlns="http://www.w3.org/1999/xhtml" >
183
+ <body>
184
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
185
+ </body>
186
+ </html>]
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ module Helpers
193
+ def hash_to_query_string(hash)
194
+ hash.collect {|k,v| "#{k}=#{v}"}.join('&')
195
+ end
196
+
197
+ def login_required
198
+ #not as efficient as checking the session. but this inits the fb_user if they are logged in
199
+ if current_user.class != GuestUser
200
+ return true
201
+ else
202
+ session[:return_to] = request.fullpath
203
+ redirect '/login'
204
+ return false
205
+ end
206
+ end
207
+
208
+ def current_user
209
+ if session[:user]
210
+ User.get(:id => session[:user])
211
+ else
212
+ GuestUser.new
213
+ end
214
+ end
215
+
216
+ def logged_in?
217
+ !!session[:user]
218
+ end
219
+
220
+ def use_layout?
221
+ !request.xhr?
222
+ end
223
+
224
+ #BECAUSE sinatra 9.1.1 can't load views from different paths properly
225
+ def get_view_as_string(filename)
226
+ view = File.join(settings.sinatra_authentication_view_path, filename)
227
+ data = ""
228
+ f = File.open(view, "r")
229
+ f.each_line do |line|
230
+ data += line
231
+ end
232
+ return data
233
+ end
234
+
235
+ def render_login_logout(html_attributes = {:class => ""})
236
+ css_classes = html_attributes.delete(:class)
237
+ parameters = ''
238
+ html_attributes.each_pair do |attribute, value|
239
+ parameters += "#{attribute}=\"#{value}\" "
240
+ end
241
+
242
+ result = "<div id='sinatra-authentication-login-logout' >"
243
+ if logged_in?
244
+ logout_parameters = html_attributes
245
+ # a tad janky?
246
+ logout_parameters.delete(:rel)
247
+ result += "<a href='/users/#{current_user.id}/edit' class='#{css_classes} sinatra-authentication-edit' #{parameters}>Edit account</a> "
248
+ if Sinatra.const_defined?('FacebookObject')
249
+ if fb[:user]
250
+ result += "<a href='javascript:FB.Connect.logoutAndRedirect(\"/logout\");' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
251
+ else
252
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
253
+ end
254
+ else
255
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
256
+ end
257
+ else
258
+ result += "<a href='/signup' class='#{css_classes} sinatra-authentication-signup' #{parameters}>Signup</a> "
259
+ result += "<a href='/login' class='#{css_classes} sinatra-authentication-login' #{parameters}>Login</a>"
260
+ end
261
+
262
+ result += "</div>"
263
+ end
264
+
265
+ if Sinatra.const_defined?('FacebookObject')
266
+ def render_facebook_connect_link(text = 'Login using facebook', options = {:size => 'small'})
267
+ if options[:size] == 'small'
268
+ size = 'Small'
269
+ elsif options[:size] == 'medium'
270
+ size = 'Medium'
271
+ elsif options[:size] == 'large'
272
+ size = 'Large'
273
+ elsif options[:size] == 'xlarge'
274
+ size = 'BigPun'
275
+ else
276
+ size = 'Small'
277
+ end
278
+
279
+ %[<a href="#" onclick="FB.Connect.requireSession(function(){document.location = '/connect';}); return false;" class="fbconnect_login_button FBConnectButton FBConnectButton_#{size}">
280
+ <span id="RES_ID_fb_login_text" class="FBConnectButton_Text">
281
+ #{text}
282
+ </span>
283
+ </a>]
284
+ end
285
+ end
286
+ end
287
+
288
+ register SinatraAuthentication
289
+ end
290
+
291
+ class GuestUser
292
+ def guest?
293
+ true
294
+ end
295
+
296
+ def permission_level
297
+ 0
298
+ end
299
+
300
+ # current_user.admin? returns false. current_user.has_a_baby? returns false.
301
+ # (which is a bit of an assumption I suppose)
302
+ def method_missing(m, *args)
303
+ return false
304
+ end
305
+ end