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,5 @@
1
+ # Allows you to use the models from cron scripts etc
2
+ if !Object.const_defined?("Sinatra")
3
+ class Sinatra;end # To please the testing for Sinatra.const_defined?('FacebookObject')
4
+ require File.expand_path(File.join(__FILE__,'../../models/') + 'abstract_user.rb')
5
+ end
@@ -0,0 +1,45 @@
1
+ #sinatra_authentication
2
+ - if Rack.const_defined?('Flash') && flash[:notice]
3
+ #sinatra_authentication_flash= flash[:notice]
4
+ - if Rack.const_defined?('Flash') && flash[:error]
5
+ #sinatra_authentication_flash= flash[:error]
6
+ %h1
7
+ Edit
8
+ - if @user.id == current_user.id
9
+ account
10
+ - else
11
+ - if @user.email
12
+ = @user.email
13
+ - elsif @user.fb_uid
14
+ <fb:name uid=#{@user.fb_uid} linked='false' />
15
+ - else
16
+ account
17
+ %form{:action => "/users/#{@user.id}/edit", :method => "post"}
18
+ .field
19
+ .label
20
+ %label{:for => "user_email"} Email
21
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text", :value => @user.email }
22
+ .field
23
+ .label
24
+ %label{:for => "user_password"} New password
25
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
26
+ .field
27
+ .label
28
+ %label{:for => "user_password_confirmation"} Confirm
29
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
30
+ -# don't render permission field if admin and editing yourself so you don't shoot yourself in the foot
31
+ - if current_user.admin? && current_user.id != @user.id
32
+ .field
33
+ .label
34
+ %label{:for => 'permission_level'} Permission level
35
+ %select{ :id => "permission_level", :name => "user[permission_level]" }
36
+ %option{:value => -1, :selected => @user.admin?}
37
+ Admin
38
+ %option{:value => 1, :selected => @user.permission_level == 1}
39
+ Authenticated user
40
+ .buttons
41
+ %input{ :value => "Update", :type => "submit" }
42
+ - if Sinatra.const_defined?('FacebookObject')
43
+ - unless @user.fb_uid
44
+ |
45
+ = render_facebook_connect_link('Link account with Facebook')
@@ -0,0 +1,46 @@
1
+ - # -*- coding:utf-8 -*-
2
+ #sinatra_authentication
3
+ - if Rack.const_defined?('Flash') && flash[:notice]
4
+ #sinatra_authentication_flash= flash[:notice]
5
+ - if Rack.const_defined?('Flash') && flash[:error]
6
+ #sinatra_authentication_flash= flash[:error]
7
+ h1
8
+ | Edit
9
+ - if @user.id == current_user.id
10
+ | account
11
+ - else
12
+ - if @user.email
13
+ = @user.email
14
+ - elsif @user.fb_uid
15
+ | <fb:name uid=#{@user.fb_uid} linked='false' />
16
+ - else
17
+ | account
18
+ form{:action => "/users/# @user.id}/edit" method="post"
19
+ .field
20
+ .label
21
+ label for="user_email"
22
+ input id="user_email" name="user[email]" size=(30)type="text" value=(@user.email )
23
+ .field
24
+ .label
25
+ label for="user_password"
26
+ input id="user_password" name="user[password]" size=(30)type="password"
27
+ .field
28
+ .label
29
+ label for="user_password_confirmation"
30
+ input id="user_password_confirmation" name="user[password_confirmation]" size=(30)type="password"
31
+ / don't render permission field if admin and editing yourself so you don't shoot yourself in the foot
32
+ - if current_user.admin? && current_user.id != @user.id
33
+ .field
34
+ .label
35
+ label for='permission_level'
36
+ select id="permission_level" name="user[permission_level]"
37
+ option value=(-1 selected=@user.admin?)
38
+ | Admin
39
+ option value=(1 selected=@user.permission_level == 1)
40
+ | Authenticated user
41
+ .buttons
42
+ input value="Update" type="submit"
43
+ - if Sinatra.const_defined?('FacebookObject')
44
+ - unless @user.fb_uid
45
+ | \
46
+ = render_facebook_connect_link('Link account with Facebook')
@@ -0,0 +1,29 @@
1
+ #sinatra_authentication
2
+ %h1.page_title Users
3
+ %table
4
+ %tr
5
+ %th
6
+ - if current_user.admin?
7
+ %th permission level
8
+ - @users.each do |user|
9
+ %tr
10
+ %td
11
+ - if user.email
12
+ = user.email
13
+ - elsif user.fb_uid
14
+ <fb:name uid=#{user.fb_uid} />
15
+ - else
16
+ "user #{user.id}"
17
+ - if current_user.admin?
18
+ %td= user.permission_level
19
+ %td
20
+ %a{:href => "/users/#{user.id}"} show
21
+ - if current_user.admin?
22
+ %td
23
+ %a{:href => "/users/#{user.id}/edit"} edit
24
+ %td
25
+ -# this doesn't work for tk
26
+ - if !user.site_admin?
27
+ %a{:href => "/users/#{user.id}/delete", :onclick => "return confirm('you sure?')"} delete
28
+ - else
29
+ site admin
@@ -0,0 +1,30 @@
1
+ - # -*- coding:utf-8 -*-
2
+ #sinatra_authentication
3
+ h1.page_title Users
4
+ table
5
+ tr
6
+ th
7
+ - if current_user.admin?
8
+ th permission level
9
+ - @users.each do |user|
10
+ tr
11
+ td
12
+ - if user.email
13
+ = user.email
14
+ - elsif user.fb_uid
15
+ | <fb:name uid=#{user.fb_uid} />
16
+ - else
17
+ | "user #{user.id}"
18
+ - if current_user.admin?
19
+ td= user.permission_level
20
+ td
21
+ a{:href => "/users/# user.id}"
22
+ - if current_user.admin?
23
+ td
24
+ a{:href => "/users/# user.id}/edit"
25
+ td
26
+ / this doesn't work for tk
27
+ - if !user.site_admin?
28
+ a{:href => "/users/# user.id}/delete" onclick="return confirm('you sure?')"
29
+ - else
30
+ | site admin
@@ -0,0 +1,24 @@
1
+ #sinatra_authentication
2
+ - if Rack.const_defined?('Flash') && flash[:notice]
3
+ #sinatra_authentication_flash= flash[:notice]
4
+ - if Rack.const_defined?('Flash') && flash[:error]
5
+ #sinatra_authentication_flash= flash[:error]
6
+ %h1.page_title Login
7
+ %form{:action => "/login", :method => "post"}
8
+ .field
9
+ .label
10
+ %label{:for => "user_email'"} Email
11
+ %input{:id => "user_email", :name => "email", :size => 30, :type => "text"}
12
+ .field
13
+ .label
14
+ %label{:for => "user_password"} Password
15
+ %input{:id => "user_password", :name => "password", :size => 30, :type => "password"}
16
+ .buttons
17
+ %input{:value => "Login", :type => "submit"}
18
+ %a{:href => "/signup", :class => 'sinatra_authentication_link'}
19
+ Sign up
20
+ - if Sinatra.const_defined?('FacebookObject')
21
+ .third_party_signup
22
+ %h3.section_title One click login:
23
+ .login_link.facebook_login
24
+ = render_facebook_connect_link('Login using facebook', :size => 'large')
@@ -0,0 +1,25 @@
1
+ - # -*- coding:utf-8 -*-
2
+ #sinatra_authentication
3
+ - if Rack.const_defined?('Flash') && flash[:notice]
4
+ #sinatra_authentication_flash= flash[:notice]
5
+ - if Rack.const_defined?('Flash') && flash[:error]
6
+ #sinatra_authentication_flash= flash[:error]
7
+ h1.page_title Login
8
+ form action="/login" method="post"
9
+ .field
10
+ .label name
11
+ label for="user_name"
12
+ input id="user_name" name="email" size="30" type="text"
13
+ .field
14
+ .label
15
+ label for="user_password"pass
16
+ input id="user_password" name="password" size="30"type="password"
17
+ .buttons
18
+ input value="Login" type="submit"
19
+ a href="/signup" class='sinatra_authentication_link'
20
+ | Sign up
21
+ - if Sinatra.const_defined?('FacebookObject')
22
+ .third_party_signup
23
+ h3.section_title One click login:
24
+ .login_link.facebook_login
25
+ = render_facebook_connect_link('Login using facebook', :size => 'large')
@@ -0,0 +1,9 @@
1
+ #sinatra_authentication
2
+ %h1.page_title
3
+ - if @user.email
4
+ = @user.email
5
+ - elsif @user.fb_uid
6
+ <fb:name uid=#{@user.fb_uid} linked='false' />
7
+ - if current_user.admin?
8
+ %h2 permission level
9
+ = @user.permission_level
@@ -0,0 +1,10 @@
1
+ - # -*- coding:utf-8 -*-
2
+ #sinatra_authentication
3
+ h1.page_title
4
+ - if @user.email
5
+ = @user.email
6
+ - elsif @user.fb_uid
7
+ | <fb:name uid=#{@user.fb_uid} linked='false' />
8
+ - if current_user.admin?
9
+ h2 permission level
10
+ = @user.permission_level
@@ -0,0 +1,28 @@
1
+ #sinatra_authentication
2
+ - if Rack.const_defined?('Flash') && flash[:notice]
3
+ #sinatra_authentication_flash= flash[:notice]
4
+ - if Rack.const_defined?('Flash') && flash[:error]
5
+ #sinatra_authentication_flash= flash[:error]
6
+ %h1.page_title Sign Up
7
+ %form{:action => "/signup", :method => "post"}
8
+ .field
9
+ .label
10
+ %label{:for => "user_email"} Email
11
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text" , :value => params[:email]}
12
+ .field
13
+ .label
14
+ %label{:for => "user_password"} Password
15
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
16
+ .field
17
+ .label
18
+ %label{:for => "user_password_confirmation"} Confirm Password
19
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
20
+ .buttons
21
+ %input{ :value => "Sign up", :type => "submit" }
22
+ %a{:href => "/login", :class => 'sinatra_authentication_link'}
23
+ Login
24
+ - if Sinatra.const_defined?('FacebookObject')
25
+ .third_party_signup
26
+ %h3.section_title One click signup:
27
+ .login_link.facebook_login
28
+ = render_facebook_connect_link('Signup using facebook', :size => 'large')
@@ -0,0 +1,33 @@
1
+ - # -*- coding:utf-8 -*-
2
+ #sinatra_authentication
3
+ - if Rack.const_defined?('Flash') && flash[:notice]
4
+ #sinatra_authentication_flash= flash[:notice]
5
+ - if Rack.const_defined?('Flash') && flash[:error]
6
+ #sinatra_authentication_flash= flash[:error]
7
+ h1.page_title Sign Up
8
+ form action="/signup" method="post"
9
+ .field
10
+ .label name
11
+ label for="user_name"
12
+ input id="user_name" name="user[name]" size="30"type="text" value=(params[:name])
13
+ .field
14
+ .label mail
15
+ label for="user_email"
16
+ input id="user_email" name="user[email]" size="30"type="text" value=(params[:email])
17
+ .field
18
+ .label password
19
+ label for="user_password"
20
+ input id="user_password" name="user[password]" size="30" type="password"
21
+ .field
22
+ .label password again
23
+ label for="user_password_confirmation"
24
+ input id="user_password_confirmation" name="user[password_confirmation]" size="30" type="password"
25
+ .buttons
26
+ input value="Sign up" type="submit"
27
+ a href="/login" class='sinatra_authentication_link'
28
+ | Login
29
+ - if Sinatra.const_defined?('FacebookObject')
30
+ .third_party_signup
31
+ h3.section_title One click signup:
32
+ .login_link.facebook_login
33
+ = render_facebook_connect_link('Signup using facebook', :size => 'large')
data/readme.markdown ADDED
@@ -0,0 +1,295 @@
1
+ ### A little sinatra gem that implements user authentication, with support for Datamapper, Mongomapper, Mongoid, Sequel and Rufus-Tokyo
2
+
3
+ ## INSTALLATION:
4
+
5
+ in your sinatra app simply require either "dm-core", 'sequel', 'rufus-tokyo', 'mongoid' or "mongo_mapper", "digest/sha1", 'rack-flash' (if you want flash messages) and then "sinatra-authentication" and turn on session storage
6
+ with a super secret key, like so:
7
+
8
+ require "dm-core"
9
+ #for using auto_migrate!
10
+ require "dm-migrations"
11
+ require "digest/sha1"
12
+ require 'rack-flash'
13
+ require "sinatra-authentication"
14
+
15
+ use Rack::Session::Cookie, :secret => 'A1 sauce 1s so good you should use 1t on a11 yr st34ksssss'
16
+ #if you want flash messages
17
+ use Rack::Flash
18
+
19
+ If you're using rufus-tokyo, you also need to set the database path for Users. like so:
20
+
21
+ require "rufus_tokyo"
22
+ require "digest/sha1"
23
+ require 'rack-flash'
24
+ require "sinatra-authentication"
25
+
26
+ #Setting the database path for Users
27
+ TcUserTable.cabinet_path = File.dirname(__FILE__) + 'folder/where/you/wanna/store/your/database'
28
+
29
+ use Rack::Session::Cookie, :secret => 'A1 sauce 1s so good you should use 1t on a11 yr st34ksssss'
30
+ #if you want flash messages
31
+ use Rack::Flash
32
+
33
+ ## DEFAULT ROUTES:
34
+
35
+ * get '/login'
36
+ * get '/logout'
37
+ * get '/signup'
38
+ * get/post '/users'
39
+ * get '/users/:id'
40
+ * get/post '/users/:id/edit'
41
+ * get '/users/:id/delete'
42
+
43
+ If you fetch any of the user pages using ajax, they will automatically render without a layout
44
+
45
+ ## ADDITIONAL ROUTES WHEN USING SINBOOK FOR FACEBOOK INTEGRATION:
46
+
47
+ * get '/reciever'
48
+ * get '/connect'
49
+
50
+ ## FLASH MESSAGES
51
+
52
+ Flash messages are implemented using rack-flash. To set them up add this to your code:
53
+
54
+ require 'rack-flash'
55
+
56
+ #be sure and do this after after 'use Rack:Session:Cookie...'
57
+ use Rack::Flash
58
+
59
+ And then sinatra-authentication related flash messages will be made available through flash[:notice] (successes) and flash[:error] (failures)
60
+
61
+ -# somewhere in a haml view:
62
+ = flash[:notice]
63
+ = flash[:error]
64
+
65
+ ## HELPER METHODS:
66
+
67
+ This plugin provides the following helper methods for your sinatra app:
68
+
69
+ * login_required
70
+ > which you place at the beginning of any routes you want to be protected
71
+ * current_user
72
+ * logged_in?
73
+ * render_login_logout(html_attributes)
74
+ > Which renders login/logout and singup/edit account links.
75
+ If you pass a hash of html parameters to render_login_logout all the links will get set to them.
76
+ Which is useful for if you're using some sort of lightbox
77
+
78
+ ## SIMPLE PERMISSIONS:
79
+
80
+ By default the user class includes a method called admin? which simply checks
81
+ if user.permission_level == -1.
82
+
83
+ you can take advantage of this method in your views or controllers by calling
84
+ current_user.admin?
85
+ i.e.
86
+
87
+ - if current_user.admin?
88
+ %a{:href => "/adminey_link_route_thing"} do something adminey
89
+
90
+ (these view examples are in HAML, by the way)
91
+
92
+ You can also extend the user class with any convenience methods for determining permissions.
93
+ i.e.
94
+
95
+ #somewhere in the murky depths of your sinatra app
96
+ class User
97
+ def peasant?
98
+ self.permission_level == 0
99
+ end
100
+ end
101
+
102
+ then in your views you can do
103
+
104
+ - if current_user.peasant?
105
+ %h1 hello peasant!
106
+ %p Welcome to the caste system! It's very depressing.
107
+
108
+ if no one is logged in, current_user returns a GuestUser instance, which responds to current_user.guest?
109
+ with true, current_user.permission_level with 0 and any other method calls with false
110
+
111
+ This makes some view logic easier since you don't always have to check if the user is logged in,
112
+ although a logged_in? helper method is still provided
113
+
114
+ ## RUFUS TOKYO
115
+
116
+ when using rufus-tokyo, current_user returns a hash, so to get the primary key of the current_user you would do current_user[:pk].
117
+ if you wanna set an attribute, you can do something like current_user["has_a_dog"] = true
118
+ and if you want to open a connection with the cabinet directly, you can do something like
119
+
120
+ user_connection = TcUser.new
121
+ users_with_gmail = user_connection.query do |q|
122
+ q.add 'email', :strinc, 'gmail'
123
+ end
124
+ user_connection.close
125
+
126
+ ## FACEBOOK
127
+
128
+ # at present, sinatra authentication supports sinbook for interacting with the facebook api.
129
+
130
+ If you want to allow users to login using facebook, just require 'sinbook' before requiring 'sinatra-authentication'.
131
+ The routes '/reciever' and '/connect' will be added. as well as connect links on the login and edit account pages.
132
+ You'll still have to include and initialize the facebook connect javascript in your layout yourself, like so:
133
+
134
+ (This example layout assumes you're using sinbook)
135
+
136
+ !!!
137
+ %head
138
+ %title Welcome to my Facebook Connect website!
139
+ %script{:type => 'text/javascript', :src => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US'}
140
+ %body
141
+ = yield
142
+ :javascript
143
+ FB.init("#{fb.api_key}", "/receiver")
144
+
145
+ Just remember to specify '/reciever' as the path to the xd-receiver file in your call to 'FB.init'.
146
+
147
+ The render_login_logout helper 'logout' link will log the user out of facebook and your app.
148
+
149
+ I've also included a little helper method 'render_facebook_connect_link' for rendering the facebook connect link with the correct 'onconnect' javascript callback.
150
+ The callback redirects to '/connect'.
151
+ This is important because the way I've implemented facebook connect support is by pinging '/connect' after the user
152
+ successfully connects with facebook.
153
+
154
+ If you choose to render the connect button yourself, be sure to have the 'onconnect' callback include "window.location = '/connect'".
155
+
156
+ '/connect' redirects to '/' on completion.
157
+
158
+ The 'render_facebook_connect_link' helper uses html instead of fbml, so ajax requests to '/login' or "/users/#{user.id}/edit"
159
+ will render the connect link without you needing to parse any fbml.
160
+
161
+ If the user is already logged into the app and connects with facebook via the user edit page,
162
+ it adds their fb_uid to their profile in the database,
163
+ which will allow them to log in using their email and password, OR their facebook account.
164
+
165
+ If they aren't already logged in to the app through the normal login form,
166
+ it creates a new user in the database without an email address or password.
167
+ They can later add this data by going to "/users/#{current_user.id}/edit",
168
+ which will allow them to log in using their email address and password, OR their facebook account.
169
+
170
+ ## OVERRIDING DEFAULT VIEWS
171
+
172
+ Right now if you're going to override sinatra-authentication's views, you have to override all of them.
173
+ This is something I hope to change in a future release.
174
+
175
+ To override the default view path do something like this:
176
+
177
+ set :sinatra_authentication_view_path, Pathname(__FILE__).dirname.expand_path + "my_views/"
178
+
179
+ And then the views you'll need to define are:
180
+
181
+ * show.haml
182
+ * index.haml
183
+ * signup.haml
184
+ * login.haml
185
+ * edit.haml
186
+
187
+ To override haml, set template_engine in your Sinatra App:
188
+
189
+ configure do
190
+ set :template_engine, :erb # for example
191
+ end
192
+
193
+ The signup and edit form fields are named so they pass a hash called 'user' to the server:
194
+
195
+ %input{:name => "user[email]", :size => 30, :type => "text", :value => @user.email}
196
+ %input{:name => "user[password]", :size => 30, :type => "password"}
197
+ %input{:name => "user[password_confirmation]", :size => 30, :type => "password"}
198
+
199
+ %select{:name => "user[permission_level]"}
200
+ %option{:value => -1, :selected => @user.admin?}
201
+ Admin
202
+ %option{:value => 1, :selected => @user.permission_level == 1}
203
+ Authenticated user
204
+
205
+ if you add attributes to the User class and pass them in the user hash your new attributes will be set along with the others.
206
+
207
+ The login form fields just pass a field called email and a field called password:
208
+
209
+ %input{:name => "email", :size => 30, :type => "text"}
210
+ %input{:name => "password", :size => 30, :type => "password"}
211
+
212
+ To add methods or properties to the User class, you have to access the underlying database user class, like so:
213
+
214
+ class DmUser
215
+ property :name, String
216
+ property :has_dog, Boolean, :default => false
217
+ end
218
+
219
+ And then to access/update your newly defined attributes you use the User class:
220
+
221
+ current_user.name
222
+ current_user.has_dog
223
+
224
+ current_user.update({:has_dog => true})
225
+
226
+ new_user = User.set({:email => 'max@max.com' :password => 'hi', :password_confirmation => 'hi', :name => 'Max', :has_dog => false})
227
+
228
+ User.all(:has_dog => true).each do |user|
229
+ user.update({has_dog => false})
230
+ end
231
+
232
+ User.all(:has_dog => false).each do |user|
233
+ user.delete
234
+ end
235
+
236
+ the User class passes additional method calls along to the interfacing database class, so most calls to Datamapper/Sequel/Mongomapper/RufusTokyo functions should work as expected.
237
+
238
+ If you need to get associations on current_user from the underlying ORM use current_user.db_instance, take this case for example:
239
+ class Brain
240
+ include DataMapper::Resource
241
+ property :type, String
242
+ property :iq, Integer
243
+ end
244
+
245
+ class DmUser
246
+ has n, :brains
247
+ end
248
+
249
+ get '/' do
250
+ @user_brains = current_user.db_instance.brains
251
+ end
252
+
253
+ The database user classes are named as follows:
254
+
255
+ * for Datamapper:
256
+ > DmUser
257
+ * for Sequel:
258
+ > SequelUser
259
+ * for Rufus Tokyo:
260
+ > TcUser
261
+ * for Mongoid:
262
+ > MongoidUser
263
+ * for Mongomapper:
264
+ > MmUser
265
+
266
+ ## Deprecations
267
+ * All database adapters now store created_at as a Time object.
268
+
269
+ ## Known issues
270
+ * First user in database is not properly recognized as site admin
271
+ > Proposed fix: add site_admin_email option when initialization functionality is added
272
+
273
+ ## Roadmap
274
+
275
+ * Move database adapter initialization, along with auto configuration of sinbook and rack flash functionality into a Sinatra::SinatraAuthentication.init(args) method
276
+ * Refactor/redesign database adapter interface, make User class AbstractUser and all ORM user classes User, with corresponding specs
277
+ * Remove Facebook connect support and add support for Omniauth
278
+ * Provide a method for overriding specific views, and/or specifying your own form partial, (passed an instance of User)
279
+ * Add Remember me (forever) checkbox to login form
280
+ * Add next url parameter support for login/signup
281
+ * Add verb selection on configuration (Sign in / Log in)
282
+ * Provide optional support through init method for inclusion of username
283
+ > Where login form accepts either email or username (through the same field)
284
+ * Add email functionality
285
+ > Confirmation emails
286
+ > Forgotten password emails
287
+ * Look into what might be neccesary to allow for logging in using Ajax
288
+
289
+ ## Maybe
290
+
291
+ * Allow passing custom database attributes into init method, also dynamically altering corresponding signup and user edit views. (potentially leaky abstraction)
292
+ > As an alternative, create a generic interface for accessing database row names through the various ORMs.
293
+ > So when users alter their User schemas, I can make my views 'Just Work'.
294
+ * Add HTTP basic auth support
295
+ * Add pluggable OAuth consumer/provider support