sinatra-auth 0.0.9
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/.gitignore +2 -0
- data/README.md +19 -0
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/examples/examples.rb +102 -0
- data/lib/sinatra/auth.rb +105 -0
- metadata +99 -0
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Simple authentication for Sinatra
|
2
|
+
|
3
|
+
Simplest case:
|
4
|
+
|
5
|
+
auth :password => 'p4ssw3rd'
|
6
|
+
|
7
|
+
Which is shorter than calling the rack middleware:
|
8
|
+
|
9
|
+
use Rack::Auth::Basic do |_, password|
|
10
|
+
password == 'p4ssw3rd'
|
11
|
+
end
|
12
|
+
|
13
|
+
Also supports scoping:
|
14
|
+
|
15
|
+
auth '/admin',
|
16
|
+
:username => 'myles',
|
17
|
+
:password => 'p4ssw3rd'
|
18
|
+
|
19
|
+
... and some other options. See examples.rb
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
task :default => :examples
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |s|
|
6
|
+
s.name = "sinatra-auth"
|
7
|
+
s.homepage = "http://github.com/quackingduck/sinatra-auth"
|
8
|
+
s.summary = "Simple authentication for sinatra"
|
9
|
+
s.email = "myles@myles.id.au"
|
10
|
+
s.authors = ["Myles Byrne"]
|
11
|
+
|
12
|
+
s.add_dependency 'sinatra', '>= 0.9.4'
|
13
|
+
s.add_development_dependency 'exemplor', '>= 2010.0.0'
|
14
|
+
s.add_development_dependency 'rack-test', '0.4.0'
|
15
|
+
s.add_development_dependency 'pow', '0.2.2'
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Install jeweler to build gem"
|
20
|
+
end
|
21
|
+
|
22
|
+
task(:examples) { ruby "examples.rb" }
|
23
|
+
task :test => :examples
|
24
|
+
|
25
|
+
task :tag_version do
|
26
|
+
version = File.read('VERSION')
|
27
|
+
system "git tag -a v#{version} -m v#{version}"
|
28
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.9
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'exemplor'
|
2
|
+
require 'pow'
|
3
|
+
|
4
|
+
require 'rack/test'
|
5
|
+
require 'sinatra/base'
|
6
|
+
require Pow!('../lib/sinatra/auth')
|
7
|
+
|
8
|
+
eg "Username and password" do
|
9
|
+
app do
|
10
|
+
auth :username => 'myles',
|
11
|
+
:password => 'p4ssw3rd'
|
12
|
+
|
13
|
+
get('/') { 'sekrets' }
|
14
|
+
end
|
15
|
+
|
16
|
+
check_auth
|
17
|
+
end
|
18
|
+
|
19
|
+
eg "Username, password and realm name" do
|
20
|
+
app do
|
21
|
+
auth :username => 'myles',
|
22
|
+
:password => 'p4ssw3rd',
|
23
|
+
:realm => 'Admin'
|
24
|
+
|
25
|
+
get('/') { 'sekrets' }
|
26
|
+
end
|
27
|
+
|
28
|
+
check_auth :realm => 'Admin'
|
29
|
+
end
|
30
|
+
|
31
|
+
eg "Non-root scope" do
|
32
|
+
app do
|
33
|
+
auth '/admin',
|
34
|
+
:password => 'p4ssw3rd'
|
35
|
+
|
36
|
+
get('/') { 'not secret' }
|
37
|
+
get('/admin') { 'sekrets' }
|
38
|
+
get('/admin/foo') { 'sekrets' }
|
39
|
+
end
|
40
|
+
|
41
|
+
Check(get('/').body).is('not secret')
|
42
|
+
check_auth '/admin'
|
43
|
+
check_auth '/admin/foo'
|
44
|
+
end
|
45
|
+
|
46
|
+
eg "Just password (any user name valid)" do
|
47
|
+
app do
|
48
|
+
auth :password => 'p4ssw3rd'
|
49
|
+
|
50
|
+
get('/') { 'sekrets' }
|
51
|
+
end
|
52
|
+
|
53
|
+
check_auth
|
54
|
+
end
|
55
|
+
|
56
|
+
eg "Block for authentication" do
|
57
|
+
app do
|
58
|
+
auth do |username,password|
|
59
|
+
username == 'myles' && password == 'p4ssw3rd'
|
60
|
+
end
|
61
|
+
|
62
|
+
get('/') { 'sekrets' }
|
63
|
+
end
|
64
|
+
|
65
|
+
check_auth
|
66
|
+
end
|
67
|
+
|
68
|
+
# --
|
69
|
+
|
70
|
+
eg.helpers do
|
71
|
+
|
72
|
+
include Rack::Test::Methods
|
73
|
+
|
74
|
+
def check_auth(path_or_options = '/', options = {})
|
75
|
+
options = case path_or_options
|
76
|
+
when Hash: {:path => '/'}.merge(path_or_options)
|
77
|
+
when String: options.merge(:path => path_or_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
allowed = get options[:path], {}, basic_auth
|
81
|
+
Check(allowed.status).is(200)
|
82
|
+
denied = get options[:path]
|
83
|
+
Check(denied.status).is(401)
|
84
|
+
Check(denied['WWW-Authenticate']).is(%{Basic realm="#{options[:realm] || 'Protected Area'}"})
|
85
|
+
end
|
86
|
+
|
87
|
+
def basic_auth(user="myles", password="p4ssw3rd")
|
88
|
+
credentials = ["#{user}:#{password}"].pack("m*")
|
89
|
+
|
90
|
+
{ "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
|
91
|
+
end
|
92
|
+
|
93
|
+
def app(&blk)
|
94
|
+
if blk
|
95
|
+
@app = Class.new Sinatra::Application # Sinatra::Base doesn't work
|
96
|
+
@app.set :environment, :test
|
97
|
+
@app.class_eval &blk
|
98
|
+
end
|
99
|
+
@app
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
data/lib/sinatra/auth.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
module Sinatra
|
2
|
+
|
3
|
+
module AuthDSL
|
4
|
+
|
5
|
+
# Only call this. Everything else is implementation. See examples.rb for usuage examples
|
6
|
+
def auth(*args, &blk)
|
7
|
+
auths << Auth.new(*args,&blk)
|
8
|
+
setup_authorization_filter if auths.size == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup_authorization_filter
|
12
|
+
before do
|
13
|
+
authenticator = self.class.auths.reverse.find { |auth| auth.protecting?(request.path_info) }
|
14
|
+
authenticate_with authenticator if authenticator
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def auths
|
19
|
+
@auths ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.registered(app)
|
23
|
+
app.helpers AuthHelpers
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
module AuthHelpers
|
29
|
+
|
30
|
+
def authenticate_with(authenticator)
|
31
|
+
auth = Rack::Auth::Basic::Request.new(request.env)
|
32
|
+
unauthorized!(authenticator.realm) unless auth.provided?
|
33
|
+
bad_request! unless auth.basic?
|
34
|
+
unauthorized!(authenticator.realm) unless authenticator.authorized?(*auth.credentials)
|
35
|
+
end
|
36
|
+
|
37
|
+
def unauthorized!(realm)
|
38
|
+
response["WWW-Authenticate"] = %(Basic realm="#{realm}")
|
39
|
+
throw :halt, [ 401, 'Authorization Required' ]
|
40
|
+
end
|
41
|
+
|
42
|
+
def bad_request!
|
43
|
+
throw :halt, [ 400, 'Bad Request' ]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class Auth
|
49
|
+
|
50
|
+
def self.new(*args, &blk)
|
51
|
+
super(parse_args(args, &blk))
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.parse_args(args,&blk)
|
55
|
+
conf = {}
|
56
|
+
conf[:auth_proc] = blk
|
57
|
+
case args.size
|
58
|
+
when 1
|
59
|
+
conf.merge!(args.first)
|
60
|
+
when 2
|
61
|
+
conf[:scope] = args.first
|
62
|
+
conf.merge!(args.last)
|
63
|
+
end
|
64
|
+
conf
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :conf
|
68
|
+
|
69
|
+
def initialize(conf)
|
70
|
+
@conf = conf
|
71
|
+
end
|
72
|
+
|
73
|
+
def authorized?(usename,password)
|
74
|
+
conf[:auth_proc] ||= proc { |u,p| self.valid_user?(u) && self.password == p }
|
75
|
+
return conf[:auth_proc].call(usename,password)
|
76
|
+
end
|
77
|
+
|
78
|
+
def protecting?(path)
|
79
|
+
scope_pattern =~ path
|
80
|
+
end
|
81
|
+
|
82
|
+
def valid_user?(username)
|
83
|
+
return true if conf[:username].nil?
|
84
|
+
conf[:username] == username
|
85
|
+
end
|
86
|
+
|
87
|
+
def password
|
88
|
+
conf[:password]
|
89
|
+
end
|
90
|
+
|
91
|
+
def realm
|
92
|
+
conf[:realm] ||= "Protected Area"
|
93
|
+
end
|
94
|
+
|
95
|
+
def scope_pattern
|
96
|
+
@scope_pattern ||= case conf[:scope]
|
97
|
+
when nil: //
|
98
|
+
when String: /^#{conf[:scope]}/
|
99
|
+
else; conf[:scope]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
register AuthDSL
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-auth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Myles Byrne
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-14 00:00:00 +11:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sinatra
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: exemplor
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2010.0.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rack-test
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.4.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: pow
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.2.2
|
54
|
+
version:
|
55
|
+
description:
|
56
|
+
email: myles@myles.id.au
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README.md
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- VERSION
|
68
|
+
- examples/examples.rb
|
69
|
+
- lib/sinatra/auth.rb
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: http://github.com/quackingduck/sinatra-auth
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options:
|
76
|
+
- --charset=UTF-8
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
version:
|
91
|
+
requirements: []
|
92
|
+
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 1.3.5
|
95
|
+
signing_key:
|
96
|
+
specification_version: 3
|
97
|
+
summary: Simple authentication for sinatra
|
98
|
+
test_files:
|
99
|
+
- examples/examples.rb
|