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,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