sinatra-authentication-oran 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.
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