chowder 0.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.
- data/lib/chowder.rb +176 -0
- data/lib/sinatra/chowder.rb +28 -0
- metadata +76 -0
data/lib/chowder.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'openid'
|
4
|
+
require 'openid/store/filesystem'
|
5
|
+
|
6
|
+
module Chowder
|
7
|
+
class Base < Sinatra::Base
|
8
|
+
disable :raise_errors
|
9
|
+
|
10
|
+
LOGIN_VIEW = <<-HTML
|
11
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
12
|
+
<html lang='en-us' xmlns='http://www.w3.org/1999/xhtml'>
|
13
|
+
<head><title>Log In</title></head>
|
14
|
+
<body>
|
15
|
+
<form action="/login" method="post">
|
16
|
+
<div id="basic_login_field">
|
17
|
+
<label for="login">Login: </label>
|
18
|
+
<input id="login" type="text" name="login" /><br />
|
19
|
+
</div>
|
20
|
+
<div id="basic_password_field">
|
21
|
+
<label for="password">Password: </label>
|
22
|
+
<input id="password" type="password" name="password" /><br />
|
23
|
+
</div>
|
24
|
+
<div id="basic_login_button">
|
25
|
+
<input type="submit" value="Login" />
|
26
|
+
</div>
|
27
|
+
</form>
|
28
|
+
<p>OpenID:</p>
|
29
|
+
<form action="/openid/initiate" method="post">
|
30
|
+
<div id="openid_login_field">
|
31
|
+
<label for="openid_identifier">URL: </label>
|
32
|
+
<input id="openid_identifier" type="text" name="openid_identifier" /><br />
|
33
|
+
</div>
|
34
|
+
<div id="openid_login_button">
|
35
|
+
<input type="submit" value="Login" />
|
36
|
+
</div>
|
37
|
+
</form>
|
38
|
+
</body></html>
|
39
|
+
HTML
|
40
|
+
|
41
|
+
SIGNUP_VIEW = <<-HTML
|
42
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
43
|
+
<html lang='en-us' xmlns='http://www.w3.org/1999/xhtml'>
|
44
|
+
<head><title>Sign Up</title></head>
|
45
|
+
<body>
|
46
|
+
__ERRORS__
|
47
|
+
<form action="/signup" method="post">
|
48
|
+
<div id="basic_login_field">
|
49
|
+
<label for="login">Login: </label>
|
50
|
+
<input id="login" type="text" name="login" /><br />
|
51
|
+
</div>
|
52
|
+
<div id="basic_password_field">
|
53
|
+
<label for="password">Password: </label>
|
54
|
+
<input id="password" type="password" name="password" /><br />
|
55
|
+
</div>
|
56
|
+
<div id="basic_signup_button">
|
57
|
+
<input type="submit" value="Sign Up" />
|
58
|
+
</div>
|
59
|
+
</form>
|
60
|
+
</body></html>
|
61
|
+
HTML
|
62
|
+
|
63
|
+
def self.new(app=nil, args={}, &block)
|
64
|
+
builder = Rack::Builder.new
|
65
|
+
builder.use Rack::Session::Cookie, :secret => args[:secret]
|
66
|
+
builder.run super
|
67
|
+
builder.to_app
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize(app=nil, args={}, &block)
|
71
|
+
@signup_callback = args[:signup]
|
72
|
+
@login_callback = args[:login] || block
|
73
|
+
super(app)
|
74
|
+
end
|
75
|
+
|
76
|
+
def authorize(user)
|
77
|
+
session[:current_user] = user
|
78
|
+
end
|
79
|
+
|
80
|
+
def return_or_redirect_to(path)
|
81
|
+
redirect(session[:return_to] || path)
|
82
|
+
end
|
83
|
+
|
84
|
+
def render_custom_template(type)
|
85
|
+
views_dir = self.options.views || "./views"
|
86
|
+
template = Dir[File.join(views_dir, "#{type}.*")].first
|
87
|
+
if template
|
88
|
+
engine = File.extname(template)[1..-1]
|
89
|
+
send(engine, type)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
get '/login' do
|
94
|
+
render_custom_template(:login) || LOGIN_VIEW
|
95
|
+
end
|
96
|
+
|
97
|
+
get '/logout' do
|
98
|
+
session[:current_user] = nil
|
99
|
+
redirect '/'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Basic < Base
|
104
|
+
post '/login' do
|
105
|
+
login, password = params['login'], params['password']
|
106
|
+
if authorize @login_callback.call(login, password)
|
107
|
+
return_or_redirect_to '/'
|
108
|
+
else
|
109
|
+
redirect '/login'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
get '/signup' do
|
114
|
+
if @signup_callback
|
115
|
+
render_custom_template(:signup) || signup_view_with_errors([])
|
116
|
+
else
|
117
|
+
throw :pass
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
post '/signup' do
|
122
|
+
throw :pass unless @signup_callback
|
123
|
+
|
124
|
+
# results is either [true, <userid>] or [false, <errors>]
|
125
|
+
successful_signup, *extras = @signup_callback.call(params)
|
126
|
+
if successful_signup
|
127
|
+
authorize extras[0]
|
128
|
+
return_or_redirect_to '/'
|
129
|
+
else
|
130
|
+
@errors = extras
|
131
|
+
render_custom_template(:signup) || signup_view_with_errors(extras)
|
132
|
+
SIGNUP_VIEW.gsub(
|
133
|
+
/__ERRORS__/,
|
134
|
+
@errors.map { |e| "<p class=\"error\">#{e}</p>" }.join("\n")
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def signup_view_with_errors(errors)
|
141
|
+
SIGNUP_VIEW.gsub(
|
142
|
+
/__ERRORS__/,
|
143
|
+
errors.map { |e| "<p class=\"error\">#{e}</p>" }.join("\n")
|
144
|
+
)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class OpenID < Base
|
149
|
+
def host
|
150
|
+
host = env['HTTP_HOST'] || "#{env['SERVER_NAME']}:#{env['SERVER_PORT']}"
|
151
|
+
"http://#{host}"
|
152
|
+
end
|
153
|
+
|
154
|
+
def setup_consumer
|
155
|
+
store = ::OpenID::Store::Filesystem.new('.openid')
|
156
|
+
osession = session[:openid] ||= {}
|
157
|
+
@consumer = ::OpenID::Consumer.new(osession, store)
|
158
|
+
end
|
159
|
+
|
160
|
+
post '/openid/initiate' do
|
161
|
+
setup_consumer
|
162
|
+
url = @consumer.begin(params['openid_identifier']).redirect_url(host, host + '/openid/authenticate')
|
163
|
+
redirect url
|
164
|
+
end
|
165
|
+
|
166
|
+
get '/openid/authenticate' do
|
167
|
+
setup_consumer
|
168
|
+
res = @consumer.complete(request.params, host + '/openid/authenticate')
|
169
|
+
user = @login_callback.call(res.identity_url)
|
170
|
+
if res.is_a?(::OpenID::Consumer::SuccessResponse) && authorize(user)
|
171
|
+
return_or_redirect_to '/'
|
172
|
+
end
|
173
|
+
redirect '/login'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module Chowder
|
5
|
+
def current_user
|
6
|
+
session[:current_user]
|
7
|
+
end
|
8
|
+
|
9
|
+
def authorized?
|
10
|
+
session[:current_user]
|
11
|
+
end
|
12
|
+
|
13
|
+
def login
|
14
|
+
session[:redirect_to] = request.path_info
|
15
|
+
redirect '/login'
|
16
|
+
end
|
17
|
+
|
18
|
+
def logout
|
19
|
+
session[:current_user] = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def require_user
|
23
|
+
login unless authorized?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
helpers Chowder
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chowder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.2"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Harry Vangberg
|
8
|
+
- Sam Merritt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-03-11 00:00:00 +01:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: sinatra
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.9.1
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: ruby-openid
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
version:
|
36
|
+
description:
|
37
|
+
email: harry@vangberg.name
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- lib/chowder.rb
|
46
|
+
- lib/sinatra/chowder.rb
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://github.com/ichverstehe/chowder
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.3.5
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: rack middleware providing session based authentication
|
75
|
+
test_files: []
|
76
|
+
|