sinatra-authentication-dmeiz 0.3.2

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 (47) hide show
  1. data/.gitignore +4 -0
  2. data/History.txt +4 -0
  3. data/Manifest +26 -0
  4. data/Rakefile +38 -0
  5. data/TODO +53 -0
  6. data/example/dm_extend_app.rb +26 -0
  7. data/example/dm_sinbook.rb +56 -0
  8. data/example/extend_views/edit.haml +42 -0
  9. data/example/extend_views/index.haml +31 -0
  10. data/example/extend_views/login.haml +21 -0
  11. data/example/extend_views/show.haml +9 -0
  12. data/example/extend_views/signup.haml +30 -0
  13. data/example/mm_app.rb +22 -0
  14. data/example/tc_app.rb +16 -0
  15. data/example/tc_sinbook.rb +62 -0
  16. data/lib/models/abstract_user.rb +54 -0
  17. data/lib/models/datamapper_user.rb +42 -0
  18. data/lib/models/dm_adapter.rb +50 -0
  19. data/lib/models/mm_adapter.rb +53 -0
  20. data/lib/models/mongomapper_user.rb +42 -0
  21. data/lib/models/rufus_tokyo_user.rb +177 -0
  22. data/lib/models/tc_adapter.rb +83 -0
  23. data/lib/sinatra-authentication.rb +290 -0
  24. data/lib/views/edit.haml +43 -0
  25. data/lib/views/index.haml +29 -0
  26. data/lib/views/login.haml +22 -0
  27. data/lib/views/show.haml +9 -0
  28. data/lib/views/signup.haml +26 -0
  29. data/readme.markdown +238 -0
  30. data/sinatra-authentication.gemspec +119 -0
  31. data/test/datamapper_test.rb +5 -0
  32. data/test/lib/dm_app.rb +20 -0
  33. data/test/lib/dm_extend_app.rb +27 -0
  34. data/test/lib/dm_sinbook.rb +55 -0
  35. data/test/lib/extend_views/edit.haml +42 -0
  36. data/test/lib/extend_views/index.haml +31 -0
  37. data/test/lib/extend_views/login.haml +21 -0
  38. data/test/lib/extend_views/show.haml +9 -0
  39. data/test/lib/extend_views/signup.haml +29 -0
  40. data/test/lib/helper.rb +9 -0
  41. data/test/lib/mm_app.rb +24 -0
  42. data/test/lib/tc_app.rb +16 -0
  43. data/test/lib/tc_sinbook.rb +62 -0
  44. data/test/mongomapper_test.rb +39 -0
  45. data/test/route_tests.rb +29 -0
  46. data/test/rufus_tokyo_test.rb +5 -0
  47. metadata +212 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/
2
+ *.swp
3
+ *.db
4
+ *.tct
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-04-06
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest ADDED
@@ -0,0 +1,26 @@
1
+ History.txt
2
+ Manifest
3
+ Rakefile
4
+ TODO
5
+ lib/models/abstract_user.rb
6
+ lib/models/datamapper_user.rb
7
+ lib/models/dm_adapter.rb
8
+ lib/models/mongomapper_user.rb
9
+ lib/models/mm_adapter.rb
10
+ lib/models/rufus_tokyo_user.rb
11
+ lib/models/tc_adapter.rb
12
+ lib/sinatra-authentication.rb
13
+ lib/views/edit.haml
14
+ lib/views/index.haml
15
+ lib/views/login.haml
16
+ lib/views/show.haml
17
+ lib/views/signup.haml
18
+ readme.markdown
19
+ test/datamapper_test.rb
20
+ test/lib/dm_app.rb
21
+ test/lib/helper.rb
22
+ test/lib/tc_app.rb
23
+ test/lib/test.db
24
+ test/lib/users.tct
25
+ test/route_tests.rb
26
+ test/rufus_tokyo_test.rb
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+
7
+ Jeweler::Tasks.new do |gemspec|
8
+ gemspec.name = 'sinatra-authentication-dmeiz'
9
+ gemspec.version = '0.3.2'
10
+ gemspec.description = "Simple authentication plugin for sinatra."
11
+ gemspec.summary = "Simple authentication plugin for sinatra."
12
+ gemspec.homepage = "http://github.com/dmeiz/sinatra-authentication"
13
+ gemspec.author = "Dan Hensgen"
14
+ gemspec.email = "dan@methodhead.com"
15
+ gemspec.add_dependency "sinatra"
16
+ gemspec.add_dependency "dm-core"
17
+ gemspec.add_dependency "dm-migrations"
18
+ gemspec.add_dependency "dm-validations"
19
+ gemspec.add_dependency "dm-timestamps"
20
+ gemspec.add_dependency "rufus-tokyo"
21
+ gemspec.add_dependency "sinbook"
22
+ gemspec.add_dependency "rack-flash"
23
+ end
24
+ Jeweler::GemcutterTasks.new
25
+ rescue LoadError
26
+ puts "Jeweler (or a dependency) not available. Install it first!"
27
+ end
28
+
29
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
30
+
31
+ require 'rake/testtask'
32
+
33
+ Rake::TestTask.new do |t|
34
+ t.libs << "test"
35
+ t.test_files = FileList['test/mongomapper_test.rb']
36
+ t.verbose = true
37
+ end
38
+
data/TODO ADDED
@@ -0,0 +1,53 @@
1
+ TODO:
2
+ ensure all calls to new in adaptors are equivelant to "find or create by"
3
+ - this is done in the Tc adaptor, and essentially works in Dm adaptor
4
+ because I validate the uniqueness of email
5
+ implement some way to allow for the creation of users with different
6
+ permission levels in an untamperable manner. Perhaps with some secret key
7
+ that must be sent in the form
8
+ - look at other permissions systems for some feature ideas
9
+ - add a config method that you pass a hash for configuring it's behavior
10
+ - secret signup urls
11
+ - account activation through email
12
+
13
+ - ?implement a session store which isn't cookie based
14
+ - turn on sessions unless they're already on
15
+ - randomize the session key on every installation?
16
+ - clean up adapters
17
+ - write simple attribute declaration method for TcUser
18
+ - condense the adapters down to the simplest solution that could possibly work
19
+ - right now it's like I have two seperate goals, both which are important
20
+ one is to write a simple ORM for rufus tokyo, the other is to create a simple adapter
21
+ for different database backends. I think it would be better if I made the datamapper adapter more abstract
22
+ and the api simpler, and then changed the way the controllers and views work to interface with the more abstract and simpler adapter.
23
+ maybe make the adapter class called UserAdapter, and then TkUser and DmUser become User. All my controller method calls go to UserAdapter
24
+ but then for people wanting to talk to the model, they just use User, since they aren't dealing with multiple backends and thus don't need
25
+ a creepy adapter.
26
+
27
+ - make site admin work the same for dm and tc, because I like how permission == -2 is site admin, then you could set a user as site admin instead of it being limited to the first user created
28
+ and they wouldn't be deletable.
29
+ or maybe I just make a heirarchy for that so users with lower permissions can't delete users with higher.
30
+ just remember, this is supposed to be a simple authentication solution
31
+
32
+
33
+ - for the User adapter
34
+ - add pagination to all
35
+ - serious cleanup of rufus_tokyo_user.rb
36
+ - add virtual attribute declaration
37
+ - add validations
38
+ - remove the object syntax method_missing? and stick to hash accessors?
39
+ - or rather then use method missing, dynamically create class methods based in the contents of the hash?
40
+ - or create a validator tool for hashes. hash.valid?
41
+ - change User to AbstractUser and DmUser and TcUser to User
42
+
43
+ - add error messages for failed logins and stuff
44
+
45
+ - PROBLEM the way I have method missing working right now, it doesn't behave the same way I've documented, since I use it for attributes
46
+ - throw configuration errors on startup
47
+ - investigate why sinatra_auth doesn't seem to work unless it's the last thing required..
48
+
49
+ - add facebook connect
50
+ - using facebooker and frankie
51
+ - using the same method as datamapper vs tokyo in that the functionality is only included if the libraries are required
52
+ before sinatra_auth is.
53
+ - when a user signs in using facebook and doesn't have an email specified, an email field is included in the edit form.
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'haml'
4
+ require 'dm-core'
5
+ require 'dm-migrations'
6
+ require 'rack-flash'
7
+ require 'sinatra-authentication'
8
+
9
+ class DmUser
10
+ property :name, String
11
+ end
12
+
13
+ DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/test.db")
14
+ DataMapper.auto_migrate!
15
+
16
+ set :sinatra_authentication_view_path, Pathname(__FILE__).dirname.expand_path + "extend_views/"
17
+ use Rack::Session::Cookie, :secret => "heyhihello"
18
+ use Rack::Flash
19
+
20
+ set :environment, 'development'
21
+ set :public, 'public'
22
+ set :views, 'views'
23
+
24
+ get '/' do
25
+ haml "= render_login_logout", :layout => :layout
26
+ end
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'haml'
4
+ require 'sinbook'
5
+ require 'dm-core'
6
+ require 'dm-migrations'
7
+ require 'sinatra-authentication'
8
+
9
+ facebook do
10
+ api_key 'aa2db1b96cb7b57f0c5b1d4d3d8f0a22'
11
+ secret '21d94ee63969ae3b3f833689838ca00f'
12
+ app_id 48652736613
13
+ url 'peoplewithjetpacks.com:4568/'
14
+ callback 'peoplewithjetpacks.com:4568/'
15
+ end
16
+
17
+ set :port, 4568
18
+
19
+ DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/test.db")
20
+ DataMapper.auto_migrate!
21
+
22
+ use Rack::Session::Cookie, :secret => "heyhihello"
23
+
24
+ set :environment, 'development'
25
+ set :public, 'public'
26
+ set :views, 'views'
27
+
28
+ get '/' do
29
+ haml :main
30
+ end
31
+
32
+ get '/test' do
33
+ login_required
34
+ 'hihihi'
35
+ end
36
+
37
+ __END__
38
+
39
+ @@ layout
40
+ %html{:xmlns=>"http://www.w3.org/1999/xhtml", :'xmlns:fb'=>"http://www.facebook.com/2008/fbml"}
41
+ %head
42
+ %title Welcome to my Facebook Connect website!
43
+ %script{:type => 'text/javascript', :src => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US'}
44
+ %body
45
+ = render_login_logout
46
+ = yield
47
+ :javascript
48
+ FB.init("#{fb.api_key}", "/receiver")
49
+
50
+ @@ main
51
+ - if fb[:user]
52
+ Hi,
53
+ %fb:profile-pic{:uid => fb[:user]}
54
+ %fb:name{:uid => fb[:user], :useyou => 'false', :firstnameonly => 'true'}
55
+ !
56
+
@@ -0,0 +1,42 @@
1
+ #sinatra_authentication
2
+ #sinatra_authentication_flash= flash[:notice]
3
+ %h1
4
+ Edit
5
+ - if @user.id == current_user.id
6
+ account
7
+ - else
8
+ - if @user.email
9
+ = @user.email
10
+ - elsif @user.fb_uid
11
+ <fb:name uid=#{@user.fb_uid} linked='false' />
12
+ - else
13
+ account
14
+ %form{:action => "/users/#{@user.id}/edit", :method => "post"}
15
+ .field
16
+ .label
17
+ %label{:for => "user_email"} Email
18
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text", :value => @user.email }
19
+ .field
20
+ .label
21
+ %label{:for => "user_password"} New password
22
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
23
+ .field
24
+ .label
25
+ %label{:for => "user_password_confirmation"} Confirm
26
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
27
+ -# don't render permission field if admin and editing yourself so you don't shoot yourself in the foot
28
+ - if current_user.admin? && current_user.id != @user.id
29
+ .field
30
+ .label
31
+ %label{:for => 'permission_level'} Permission level
32
+ %select{ :id => "permission_level", :name => "user[permission_level]" }
33
+ %option{:value => -1, :selected => @user.admin?}
34
+ Admin
35
+ %option{:value => 1, :selected => @user.permission_level == 1}
36
+ Authenticated user
37
+ .buttons
38
+ %input{ :value => "Update", :type => "submit" }
39
+ - if Sinatra.const_defined?('FacebookObject')
40
+ - unless @user.fb_uid
41
+ |
42
+ = render_facebook_connect_link('Link account with Facebook')
@@ -0,0 +1,31 @@
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
+ = user.name
21
+ %td
22
+ %a{:href => "/users/#{user.id}"} show
23
+ - if current_user.admin?
24
+ %td
25
+ %a{:href => "/users/#{user.id}/edit"} edit
26
+ %td
27
+ -# this doesn't work for tk
28
+ - if !user.site_admin?
29
+ %a{:href => "/users/#{user.id}/delete", :onclick => "return confirm('you sure?')"} delete
30
+ - else
31
+ site admin
@@ -0,0 +1,21 @@
1
+ #sinatra_authentication
2
+ #sinatra_authentication_flash= flash[:notice]
3
+ %h1.page_title Login
4
+ %form{:action => "/login", :method => "post"}
5
+ .field
6
+ .label
7
+ %label{:for => "user_email'"} Email
8
+ %input{:id => "user_email", :name => "email", :size => 30, :type => "text"}
9
+ .field
10
+ .label
11
+ %label{:for => "user_password"} Password
12
+ %input{:id => "user_password", :name => "password", :size => 30, :type => "password"}
13
+ .buttons
14
+ %input{:value => "login", :type => "submit"}
15
+ %a{:href => "/signup", :class => 'sinatra_authentication_link'}
16
+ Signup
17
+ - if Sinatra.const_defined?('FacebookObject')
18
+ .third_party_signup
19
+ %h3.section_title One click login:
20
+ .login_link.facebook_login
21
+ = 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,30 @@
1
+ %h1 This view is overridden
2
+ #sinatra_authentication
3
+ #sinatra_authentication_flash= flash[:notice]
4
+ %h1.page_title Signup
5
+ %form{:action => "/signup", :method => "post"}
6
+ .field
7
+ .label
8
+ %label{:for => "user_email"} Email
9
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text" }
10
+ .field
11
+ .label
12
+ %label{:for => "user_password"} Password
13
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
14
+ .field
15
+ .label
16
+ %label{:for => "user_name"} Name
17
+ %input{ :id => "user_name", :name => "user[name]", :size => 30, :type => "text" }
18
+ .field
19
+ .label
20
+ %label{:for => "user_password_confirmation"} Confirm Password
21
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
22
+ .buttons
23
+ %input{ :value => "Create account", :type => "submit" }
24
+ %a{:href => "/login", :class => 'sinatra_authentication_link'}
25
+ Login
26
+ - if Sinatra.const_defined?('FacebookObject')
27
+ .third_party_signup
28
+ %h3.section_title One click signup:
29
+ .login_link.facebook_login
30
+ = render_facebook_connect_link('Signup using facebook', :size => 'large')
data/example/mm_app.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'sinatra/base'
3
+ require 'haml'
4
+ require 'mongo_mapper'
5
+ require 'sinatra-authentication'
6
+
7
+ logger = Logger.new($stdout)
8
+ MongoMapper.connection = Mongo::Connection.new('db.mongohq.com', 27017, :logger => logger)
9
+ MongoMapper.database = "fdbk"
10
+ MongoMapper.database.authenticate(ENV['mongohq_user'], ENV['mongohq_pass'])
11
+
12
+ class TestApp < Sinatra::Base
13
+ use Rack::Session::Cookie, :secret => "heyhihello"
14
+
15
+ set :environment, 'development'
16
+ set :public, 'public'
17
+ set :views, 'views'
18
+
19
+ get '/' do
20
+ haml "= render_login_logout", :layout => :layout
21
+ end
22
+ end
data/example/tc_app.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'haml'
4
+ require 'rufus/tokyo'
5
+ require 'sinatra-authentication'
6
+
7
+ use Rack::Session::Cookie, :secret => "heyhihello"
8
+ TcUserTable.cabinet_path = File.dirname(__FILE__)
9
+
10
+ set :environment, 'development'
11
+ set :public, 'public'
12
+ set :views, 'views'
13
+
14
+ get '/' do
15
+ haml "= render_login_logout", :layout => :layout
16
+ end
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'haml'
3
+ require 'sinbook'
4
+ require 'rufus/tokyo'
5
+ require 'sinatra'
6
+ require 'sinatra-authentication'
7
+
8
+ use Rack::Session::Cookie, :secret => "heyhihello"
9
+ TcUserTable.cabinet_path = File.dirname(__FILE__)
10
+
11
+ facebook do
12
+ api_key 'aa2db1b96cb7b57f0c5b1d4d3d8f0a22'
13
+ secret '21d94ee63969ae3b3f833689838ca00f'
14
+ app_id 48652736613
15
+ url 'peoplewithjetpacks.com:4568/'
16
+ callback 'peoplewithjetpacks.com:4568/'
17
+ end
18
+
19
+ set :port, 4568
20
+
21
+ get '/' do
22
+ haml :main
23
+ end
24
+
25
+ get '/test' do
26
+ login_required
27
+ 'hihihi'
28
+ end
29
+
30
+ __END__
31
+
32
+ @@ layout
33
+ %html{:xmlns=>"http://www.w3.org/1999/xhtml", :'xmlns:fb'=>"http://www.facebook.com/2008/fbml"}
34
+ %head
35
+ %title Welcome to my Facebook Connect website!
36
+ %script{:type => 'text/javascript', :src => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US'}
37
+ %script{:type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'}
38
+ :javascript
39
+ $(document).ready(function(){
40
+ /* test facebook crap works with ajax */
41
+ $('.sinatra-authentication-login').click(function(){
42
+ $.get($(this).attr('href'), {}, function(data){
43
+ $('#test_box').html(data);
44
+ });
45
+ return false;
46
+ });
47
+ });
48
+ %body
49
+ = render_login_logout
50
+ = yield
51
+ :javascript
52
+ FB.init("#{fb.api_key}", "/receiver")
53
+ #test_box
54
+
55
+ @@ main
56
+ - if fb[:user]
57
+ Hi,
58
+ %fb:profile-pic{:uid => fb[:user]}
59
+ %fb:name{:uid => fb[:user], :useyou => 'false', :firstnameonly => 'true'}
60
+ !
61
+ %br/
62
+