sinatra-authentication-nedludd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/History.txt +4 -0
- data/Manifest +26 -0
- data/Rakefile +36 -0
- data/TODO +53 -0
- data/example/dm_extend_app.rb +26 -0
- data/example/dm_sinbook.rb +56 -0
- data/example/extend_views/edit.haml +42 -0
- data/example/extend_views/index.haml +31 -0
- data/example/extend_views/login.haml +21 -0
- data/example/extend_views/show.haml +9 -0
- data/example/extend_views/signup.haml +30 -0
- data/example/mm_app.rb +22 -0
- data/example/tc_app.rb +16 -0
- data/example/tc_sinbook.rb +62 -0
- data/lib/models/abstract_user.rb +44 -0
- data/lib/models/datamapper_user.rb +39 -0
- data/lib/models/dm_adapter.rb +50 -0
- data/lib/sinatra-authentication.rb +227 -0
- data/lib/views/edit.haml +38 -0
- data/lib/views/index.haml +27 -0
- data/lib/views/login.haml +18 -0
- data/lib/views/show.haml +7 -0
- data/lib/views/signup.haml +21 -0
- data/readme.markdown +161 -0
- data/sinatra-authentication-nedludd.gemspec +97 -0
- data/test/datamapper_test.rb +5 -0
- data/test/lib/dm_app.rb +20 -0
- data/test/lib/dm_extend_app.rb +27 -0
- data/test/lib/extend_views/edit.haml +42 -0
- data/test/lib/extend_views/index.haml +31 -0
- data/test/lib/extend_views/login.haml +21 -0
- data/test/lib/extend_views/show.haml +9 -0
- data/test/lib/extend_views/signup.haml +29 -0
- data/test/lib/helper.rb +9 -0
- data/test/route_tests.rb +29 -0
- metadata +190 -0
data/lib/views/show.haml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#sinatra_authentication
|
2
|
+
- if Rack.const_defined?('Flash')
|
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_password_confirmation"} Confirm Password
|
17
|
+
%input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
|
18
|
+
.buttons
|
19
|
+
%input{ :value => "Create account", :type => "submit" }
|
20
|
+
%a{:href => "/login", :class => 'sinatra_authentication_link'}
|
21
|
+
Login
|
data/readme.markdown
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
### A little sinatra gem that implements user authentication, with support for DataMapper.
|
2
|
+
|
3
|
+
(Forked from maxjustus' version. I don't need TC or Mongo, nor Facebook integration)
|
4
|
+
|
5
|
+
## INSTALLATION:
|
6
|
+
|
7
|
+
In your sinatra app simply require "dm-core", "digest/sha1", 'rack-flash' (if you want flash messages) and then "sinatra-authentication" and turn on session storage with a super secret key, like so:
|
8
|
+
|
9
|
+
require "dm-core"
|
10
|
+
#for using auto_migrate!
|
11
|
+
require "dm-migrations"
|
12
|
+
require "digest/sha1"
|
13
|
+
require 'rack-flash'
|
14
|
+
require "sinatra-authentication"
|
15
|
+
|
16
|
+
use Rack::Session::Cookie, :secret => 'A1 sauce 1s so good you should use 1t on a11 yr st34ksssss'
|
17
|
+
#if you want flash messages
|
18
|
+
use Rack::Flash
|
19
|
+
|
20
|
+
## DEFAULT ROUTES:
|
21
|
+
|
22
|
+
* get '/login'
|
23
|
+
* get '/logout'
|
24
|
+
* get '/signup'
|
25
|
+
* get/post '/users'
|
26
|
+
* get '/users/:id'
|
27
|
+
* get/post '/users/:id/edit'
|
28
|
+
* get '/users/:id/delete'
|
29
|
+
|
30
|
+
If you fetch any of the user pages using ajax, they will automatically render without a layout
|
31
|
+
|
32
|
+
## FLASH MESSAGES
|
33
|
+
|
34
|
+
Flash messages are implemented using rack-flash. To set them up add this to your code:
|
35
|
+
|
36
|
+
require 'rack-flash'
|
37
|
+
|
38
|
+
#be sure and do this after after 'use Rack:Session:Cookie...'
|
39
|
+
use Rack::Flash
|
40
|
+
|
41
|
+
And then sinatra-authentication related flash messages will be made available through flash[:notice]
|
42
|
+
|
43
|
+
-# somewhere in a haml view:
|
44
|
+
= flash[:notice]
|
45
|
+
|
46
|
+
## HELPER METHODS:
|
47
|
+
|
48
|
+
This plugin provides the following helper methods for your sinatra app:
|
49
|
+
|
50
|
+
* login_required
|
51
|
+
> which you place at the beginning of any routes you want to be protected
|
52
|
+
* current_user
|
53
|
+
* logged_in?
|
54
|
+
* render_login_logout(html_attributes)
|
55
|
+
> Which renders login/logout and singup/edit account links.
|
56
|
+
If you pass a hash of html parameters to render_login_logout all the links will get set to them.
|
57
|
+
Which is useful for if you're using some sort of lightbox
|
58
|
+
|
59
|
+
## SIMPLE PERMISSIONS:
|
60
|
+
|
61
|
+
By default the user class includes a method called admin? which simply checks
|
62
|
+
if user.permission_level == -1.
|
63
|
+
|
64
|
+
you can take advantage of this method in your views or controllers by calling
|
65
|
+
current_user.admin?
|
66
|
+
i.e.
|
67
|
+
|
68
|
+
- if current_user.admin?
|
69
|
+
%a{:href => "/adminey_link_route_thing"} do something adminey
|
70
|
+
|
71
|
+
(these view examples are in HAML, by the way)
|
72
|
+
|
73
|
+
You can also extend the user class with any convenience methods for determining permissions.
|
74
|
+
i.e.
|
75
|
+
|
76
|
+
#somewhere in the murky depths of your sinatra app
|
77
|
+
class User
|
78
|
+
def peasant?
|
79
|
+
self.permission_level == 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
then in your views you can do
|
84
|
+
|
85
|
+
- if current_user.peasant?
|
86
|
+
%h1 hello peasant!
|
87
|
+
%p Welcome to the caste system! It's very depressing.
|
88
|
+
|
89
|
+
if no one is logged in, current_user returns a GuestUser instance, which responds to current_user.guest?
|
90
|
+
with true, current_user.permission_level with 0 and any other method calls with false
|
91
|
+
|
92
|
+
This makes some view logic easier since you don't always have to check if the user is logged in,
|
93
|
+
although a logged_in? helper method is still provided
|
94
|
+
|
95
|
+
|
96
|
+
## OVERRIDING DEFAULT VIEWS
|
97
|
+
|
98
|
+
Right now if you're going to override sinatra-authentication's views, you have to override all of them.
|
99
|
+
This is something I hope to change in a future release.
|
100
|
+
|
101
|
+
To override the default view path do something like this:
|
102
|
+
|
103
|
+
set :sinatra_authentication_view_path, Pathname(__FILE__).dirname.expand_path + "my_views/"
|
104
|
+
|
105
|
+
And then the views you'll need to define are:
|
106
|
+
|
107
|
+
* show.haml
|
108
|
+
* index.haml
|
109
|
+
* signup.haml
|
110
|
+
* login.haml
|
111
|
+
* edit.haml
|
112
|
+
|
113
|
+
The signup and edit form fields are named so they pass a hash called 'user' to the server:
|
114
|
+
|
115
|
+
%input{:name => "user[email]", :size => 30, :type => "text", :value => @user.email}
|
116
|
+
%input{:name => "user[password]", :size => 30, :type => "password"}
|
117
|
+
%input{:name => "user[password_confirmation]", :size => 30, :type => "password"}
|
118
|
+
|
119
|
+
%select{:name => "user[permission_level]"}
|
120
|
+
%option{:value => -1, :selected => @user.admin?}
|
121
|
+
Admin
|
122
|
+
%option{:value => 1, :selected => @user.permission_level == 1}
|
123
|
+
Authenticated user
|
124
|
+
|
125
|
+
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.
|
126
|
+
|
127
|
+
The login form fields just pass a field called email and a field called password:
|
128
|
+
|
129
|
+
%input{:name => "email", :size => 30, :type => "text"}
|
130
|
+
%input{:name => "password", :size => 30, :type => "password"}
|
131
|
+
|
132
|
+
To add methods or properties to the User class, you have to access the underlying database user class, like so:
|
133
|
+
|
134
|
+
class DmUser
|
135
|
+
property :name, String
|
136
|
+
property :has_dog, Boolean, :default => false
|
137
|
+
end
|
138
|
+
|
139
|
+
And then to access/update your newly defined attributes you use the User class:
|
140
|
+
|
141
|
+
current_user.name
|
142
|
+
current_user.has_dog
|
143
|
+
|
144
|
+
current_user.update({:has_dog => true})
|
145
|
+
|
146
|
+
new_user = User.set({:email => 'max@max.com' :password => 'hi', :password_confirmation => 'hi', :name => 'Max', :has_dog => false})
|
147
|
+
|
148
|
+
User.all(:has_dog => true).each do |user|
|
149
|
+
user.update({has_dog => false})
|
150
|
+
end
|
151
|
+
|
152
|
+
User.all(:has_dog => false).each do |user|
|
153
|
+
user.delete
|
154
|
+
end
|
155
|
+
|
156
|
+
the User class passes additional method calls along to the interfacing database class, so calls to Datamapper functions should work as expected.
|
157
|
+
|
158
|
+
The database user class is named
|
159
|
+
|
160
|
+
DmUser
|
161
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sinatra-authentication-nedludd}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Max Justus Spransy" "Tim Hermans"]
|
12
|
+
s.date = %q{2010-06-29}
|
13
|
+
s.description = %q{Simple authentication plugin for sinatra.}
|
14
|
+
s.email = ["maxjustus@gmail.com" "thermans@gmail.com"]
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"TODO"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"History.txt",
|
21
|
+
"Manifest",
|
22
|
+
"Rakefile",
|
23
|
+
"TODO",
|
24
|
+
"example/dm_extend_app.rb",
|
25
|
+
"example/dm_sinbook.rb",
|
26
|
+
"example/extend_views/edit.haml",
|
27
|
+
"example/extend_views/index.haml",
|
28
|
+
"example/extend_views/login.haml",
|
29
|
+
"example/extend_views/show.haml",
|
30
|
+
"example/extend_views/signup.haml",
|
31
|
+
"example/mm_app.rb",
|
32
|
+
"example/tc_app.rb",
|
33
|
+
"example/tc_sinbook.rb",
|
34
|
+
"lib/models/abstract_user.rb",
|
35
|
+
"lib/models/datamapper_user.rb",
|
36
|
+
"lib/models/dm_adapter.rb",
|
37
|
+
"lib/sinatra-authentication.rb",
|
38
|
+
"lib/views/edit.haml",
|
39
|
+
"lib/views/index.haml",
|
40
|
+
"lib/views/login.haml",
|
41
|
+
"lib/views/show.haml",
|
42
|
+
"lib/views/signup.haml",
|
43
|
+
"readme.markdown",
|
44
|
+
"sinatra-authentication-nedludd.gemspec",
|
45
|
+
"test/datamapper_test.rb",
|
46
|
+
"test/lib/dm_app.rb",
|
47
|
+
"test/lib/dm_extend_app.rb",
|
48
|
+
"test/lib/extend_views/edit.haml",
|
49
|
+
"test/lib/extend_views/index.haml",
|
50
|
+
"test/lib/extend_views/login.haml",
|
51
|
+
"test/lib/extend_views/show.haml",
|
52
|
+
"test/lib/extend_views/signup.haml",
|
53
|
+
"test/lib/helper.rb",
|
54
|
+
"test/route_tests.rb"
|
55
|
+
]
|
56
|
+
s.homepage = %q{http://github.com/nedludd/sinatra-authentication}
|
57
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
58
|
+
s.require_paths = ["lib"]
|
59
|
+
s.rubygems_version = %q{1.3.7}
|
60
|
+
s.summary = %q{Simple authentication plugin for sinatra.}
|
61
|
+
s.test_files = [
|
62
|
+
"test/route_tests.rb",
|
63
|
+
"test/datamapper_test.rb",
|
64
|
+
"test/lib/dm_app.rb",
|
65
|
+
"test/lib/helper.rb",
|
66
|
+
"test/lib/dm_extend_app.rb"
|
67
|
+
]
|
68
|
+
|
69
|
+
if s.respond_to? :specification_version then
|
70
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
71
|
+
s.specification_version = 3
|
72
|
+
|
73
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
74
|
+
s.add_runtime_dependency(%q<sinatra>, [">= 0"])
|
75
|
+
s.add_runtime_dependency(%q<dm-core>, [">= 0"])
|
76
|
+
s.add_runtime_dependency(%q<dm-migrations>, [">= 0"])
|
77
|
+
s.add_runtime_dependency(%q<dm-validations>, [">= 0"])
|
78
|
+
s.add_runtime_dependency(%q<dm-timestamps>, [">= 0"])
|
79
|
+
s.add_runtime_dependency(%q<rack-flash>, [">= 0"])
|
80
|
+
else
|
81
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
82
|
+
s.add_dependency(%q<dm-core>, [">= 0"])
|
83
|
+
s.add_dependency(%q<dm-migrations>, [">= 0"])
|
84
|
+
s.add_dependency(%q<dm-validations>, [">= 0"])
|
85
|
+
s.add_dependency(%q<dm-timestamps>, [">= 0"])
|
86
|
+
s.add_dependency(%q<rack-flash>, [">= 0"])
|
87
|
+
end
|
88
|
+
else
|
89
|
+
s.add_dependency(%q<sinatra>, [">= 0"])
|
90
|
+
s.add_dependency(%q<dm-core>, [">= 0"])
|
91
|
+
s.add_dependency(%q<dm-migrations>, [">= 0"])
|
92
|
+
s.add_dependency(%q<dm-validations>, [">= 0"])
|
93
|
+
s.add_dependency(%q<dm-timestamps>, [">= 0"])
|
94
|
+
s.add_dependency(%q<rack-flash>, [">= 0"])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
data/test/lib/dm_app.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'haml'
|
4
|
+
require 'dm-core'
|
5
|
+
require 'rack-flash'
|
6
|
+
require File.join(File.dirname(__FILE__), '../../lib/sinatra-authentication')
|
7
|
+
|
8
|
+
DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/test.db")
|
9
|
+
DataMapper.auto_migrate!
|
10
|
+
|
11
|
+
use Rack::Session::Cookie, :secret => "heyhihello"
|
12
|
+
use Rack::Flash
|
13
|
+
|
14
|
+
set :environment, 'development'
|
15
|
+
set :public, 'public'
|
16
|
+
set :views, 'views'
|
17
|
+
|
18
|
+
get '/' do
|
19
|
+
haml "= render_login_logout", :layout => :layout
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'haml'
|
4
|
+
require 'dm-core'
|
5
|
+
require 'rack-flash'
|
6
|
+
require File.join(File.dirname(__FILE__), '../../lib/sinatra-authentication')
|
7
|
+
|
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
|
+
puts User.all(:name => 'max')
|
26
|
+
haml "= render_login_logout", :layout => :layout
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#sinatra_authentication
|
2
|
+
#sinatra_authentication_flash= session[:flash]
|
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= session[:flash]
|
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')
|