tight-engine 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/lib/tight-engine.rb +23 -0
- data/lib/tight-engine/defer.rb +30 -0
- data/lib/tight-engine/init.rb +120 -0
- data/lib/tight-engine/locale.rb +40 -0
- data/lib/tight-engine/render.rb +193 -0
- data/lib/tight-engine/template.rb +60 -0
- data/lib/tight-engine/url.rb +27 -0
- data/lib/tight-engine/utils.rb +62 -0
- data/lib/tight-engine/version.rb +5 -0
- data/tight-engine.gemspec +2 -2
- metadata +13 -19
- data/lib/tight-auth.rb +0 -10
- data/lib/tight-auth/access.rb +0 -148
- data/lib/tight-auth/login.rb +0 -138
- data/lib/tight-auth/login/controller.rb +0 -20
- data/lib/tight-auth/login/layout.slim +0 -10
- data/lib/tight-auth/login/new.slim +0 -37
- data/lib/tight-auth/permissions.rb +0 -180
- data/lib/tight/version.rb +0 -3
- data/test/auth_helper.rb +0 -83
- data/test/test_padrino_access.rb +0 -124
- data/test/test_padrino_auth.rb +0 -38
- data/test/test_padrino_login.rb +0 -76
@@ -1,20 +0,0 @@
|
|
1
|
-
module Tight
|
2
|
-
module Login
|
3
|
-
module Controller
|
4
|
-
def self.included(base)
|
5
|
-
base.get :index do
|
6
|
-
render :slim, :"new", :layout => :"layout", :views => File.dirname(__FILE__)
|
7
|
-
end
|
8
|
-
base.post :index do
|
9
|
-
if authenticate
|
10
|
-
restore_location
|
11
|
-
else
|
12
|
-
params.delete 'password'
|
13
|
-
flash.now[:error] = 'Wrong password'
|
14
|
-
render :slim, :"new", :layout => :"layout", :views => File.dirname(__FILE__)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
doctype html
|
2
|
-
html
|
3
|
-
head
|
4
|
-
meta charset="utf-8"
|
5
|
-
meta name="robots" content="noindex"
|
6
|
-
title Padrino::Login
|
7
|
-
link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css"
|
8
|
-
body
|
9
|
-
.container.login style='width: 287px'
|
10
|
-
= yield
|
@@ -1,37 +0,0 @@
|
|
1
|
-
h3
|
2
|
-
| Login
|
3
|
-
br
|
4
|
-
small
|
5
|
-
a href=url('/') = request.env['HTTP_HOST']
|
6
|
-
|
7
|
-
form.form-horizontal.well action=''
|
8
|
-
- [:error, :warning, :success, :notice].each do |type|
|
9
|
-
- next if flash[type].blank?
|
10
|
-
.alert.alert-message class=('alert-' + (type == :notice ? :info : type).to_s) data-alert=true
|
11
|
-
= flash[type]
|
12
|
-
|
13
|
-
legend Social
|
14
|
-
.control-group
|
15
|
-
a href=url('/oauth/google')
|
16
|
-
img src='/images/social/google.png'
|
17
|
-
|
18
|
-
legend Obsolete
|
19
|
-
.control-group
|
20
|
-
.input-prepend
|
21
|
-
span.add-on
|
22
|
-
i.icon-envelope
|
23
|
-
input type=:text name=:email value=params[:email] placeholder='email'
|
24
|
-
.control-group
|
25
|
-
.input-prepend
|
26
|
-
span.add-on
|
27
|
-
i.icon-lock
|
28
|
-
input type=:password name=:password value=params[:password] placeholder='password'
|
29
|
-
.control-group
|
30
|
-
input.btn.btn-primary.pull-right type=:submit Log in
|
31
|
-
- if settings.login_bypass
|
32
|
-
label.checkbox
|
33
|
-
| Bypass
|
34
|
-
input type=:checkbox name=:bypass value='Bypass'
|
35
|
-
|
36
|
-
small
|
37
|
-
a href=url('/login/reset_password') Forgot password?
|
@@ -1,180 +0,0 @@
|
|
1
|
-
module Tight
|
2
|
-
##
|
3
|
-
# Class to store and check permissions used in Padrino::Access.
|
4
|
-
#
|
5
|
-
class Permissions
|
6
|
-
##
|
7
|
-
# Initializes new permissions storage.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# permissions = Permissions.new
|
11
|
-
#
|
12
|
-
def initialize
|
13
|
-
clear!
|
14
|
-
end
|
15
|
-
|
16
|
-
##
|
17
|
-
# Clears permit records and action cache.
|
18
|
-
#
|
19
|
-
# @example
|
20
|
-
# permissions.clear!
|
21
|
-
#
|
22
|
-
def clear!
|
23
|
-
@permits = {}
|
24
|
-
@actions = {}
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# Adds a permission record to storage.
|
29
|
-
#
|
30
|
-
# @param [Symbol || Object] subject
|
31
|
-
# permit subject
|
32
|
-
# @param [Hash] options
|
33
|
-
# permit attributes
|
34
|
-
# @param [Symbol] options[:allow] || options[:action]
|
35
|
-
# what action to allow with objects
|
36
|
-
# @param [Symbol] options[:with] || options[:object]
|
37
|
-
# with what objects allow specified action
|
38
|
-
#
|
39
|
-
# @example
|
40
|
-
# permissions.add :robots, :allow => :protect, :object => :humans
|
41
|
-
# permissions.add @bender, :allow => :kill, :object => :humans
|
42
|
-
#
|
43
|
-
def add(*args)
|
44
|
-
@actions = {}
|
45
|
-
options = args.extract_options!
|
46
|
-
action, object = action_and_object(options)
|
47
|
-
object_type = detect_type(object)
|
48
|
-
args.each{ |subject| merge(subject, action, object_type) }
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
# Checks if permission record exists. Returns a boolean or yield a block.
|
53
|
-
#
|
54
|
-
# @param [Object] subject
|
55
|
-
# performer of an action
|
56
|
-
# @param [Hash] options
|
57
|
-
# attributes to check
|
58
|
-
# @param [Symbol] options[:have]
|
59
|
-
# check if the subject has a role
|
60
|
-
# @param [Symbol] options[:allow] || options[:action]
|
61
|
-
# check if the subject is allowed to perform the action
|
62
|
-
# @param [Symbol] options[:with] || options[:object]
|
63
|
-
# check if the subject is allowed to interact with the subject
|
64
|
-
# @param [Proc]
|
65
|
-
# optional block to yield if the action is allowed
|
66
|
-
#
|
67
|
-
# @example
|
68
|
-
# # check if @bender have role :robots
|
69
|
-
# permissions.check @bender, :have => :robots # => true
|
70
|
-
# # check if @bender is allowed to kill :humans
|
71
|
-
# permissions.check @bender, :allow => :kill, :object => :humans # => true
|
72
|
-
# # check if @bender is allowed to kill :humans and yield a block
|
73
|
-
# permissions.check @bender, :allow => :kill, :object => :humans do
|
74
|
-
# @bender.kill_all! :humans
|
75
|
-
# end
|
76
|
-
#
|
77
|
-
def check(subject, options)
|
78
|
-
case
|
79
|
-
when options[:have]
|
80
|
-
check_role(subject, options[:have])
|
81
|
-
else
|
82
|
-
check_action(subject, *action_and_object(options))
|
83
|
-
end && (block_given? ? yield : true)
|
84
|
-
end
|
85
|
-
|
86
|
-
##
|
87
|
-
# Populates and returns the list of objects available to the subject.
|
88
|
-
#
|
89
|
-
# @param [Object] subject
|
90
|
-
# the subject to be checked for actions
|
91
|
-
#
|
92
|
-
def find_objects(subject, target_action=nil)
|
93
|
-
find_actions(subject).inject([]) do |all,(action,objects)|
|
94
|
-
all |= objects if target_action.nil? || action == target_action || action == :*
|
95
|
-
all
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
private
|
100
|
-
|
101
|
-
# Merges a list of new permits into permissions storage.
|
102
|
-
def merge(subject, actions, object_type)
|
103
|
-
subject_id = detect_id(subject)
|
104
|
-
@permits[subject_id] ||= {}
|
105
|
-
Array(actions).each do |action|
|
106
|
-
@permits[subject_id][action] ||= []
|
107
|
-
@permits[subject_id][action] |= [object_type]
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Checks if the subject has the role.
|
112
|
-
def check_role(subject, roles)
|
113
|
-
if subject.respond_to?(:role)
|
114
|
-
Array(roles).include?(subject.role)
|
115
|
-
else
|
116
|
-
false
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Checks if the subject is allowed to perform the action with the object.
|
121
|
-
def check_action(subject, action, object)
|
122
|
-
actions = find_actions(subject)
|
123
|
-
objects = actions && (Array(actions[action]) | Array(actions[:*]))
|
124
|
-
objects && (objects & [:*, detect_type(object)]).any?
|
125
|
-
end
|
126
|
-
|
127
|
-
# Finds all permits for the subject. Caches the permits in @actions.
|
128
|
-
# find_actions(@bender) # => { :kill => { :humans }, :drink => { :booze }, :* => { :login } }
|
129
|
-
def find_actions(subject)
|
130
|
-
subject_id = detect_id(subject)
|
131
|
-
return @actions[subject_id] if @actions[subject_id]
|
132
|
-
actions = @permits[subject_id] || {}
|
133
|
-
if subject.respond_to?(:role) && (role_actions = @permits[subject.role.to_sym])
|
134
|
-
actions.merge!(role_actions){ |_,left,right| Array(left)|Array(right) }
|
135
|
-
end
|
136
|
-
if public_actions = @permits[:*]
|
137
|
-
actions.merge!(public_actions){ |_,left,right| Array(left)|Array(right) }
|
138
|
-
end
|
139
|
-
@actions[subject_id] = actions
|
140
|
-
end
|
141
|
-
|
142
|
-
# Returns object type.
|
143
|
-
# detect_type :humans # => :human
|
144
|
-
# detect_type 'foobar' # => 'foobar'
|
145
|
-
def detect_type(object)
|
146
|
-
case object
|
147
|
-
when Symbol
|
148
|
-
object.to_s.singularize.to_sym
|
149
|
-
else
|
150
|
-
object
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
# Returns parametrized subject.
|
155
|
-
# detect_id :robots # => :robots
|
156
|
-
# detect_id sluggable_ar_resource # => 'Sluggable-resource-slug'
|
157
|
-
# detect_id some_resource_with_id # => '4'
|
158
|
-
# detect_id generic_object # => "<Object:0x00001234>"
|
159
|
-
def detect_id(subject)
|
160
|
-
case
|
161
|
-
when Symbol === subject
|
162
|
-
subject
|
163
|
-
when subject.respond_to?(:to_param)
|
164
|
-
subject.to_param
|
165
|
-
when subject.respond_to?(:id)
|
166
|
-
subject.id.to_s
|
167
|
-
else
|
168
|
-
"#{subject}"
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Utility function to extract action and object from options. Defaults to [:*, :*]
|
173
|
-
# action_and_object(:allow => :kill, :object => :humans) # => [:kill, :humans]
|
174
|
-
# action_and_object(:action => :romance, :with => :mutants) # => [:romance, :mutants]
|
175
|
-
# action_and_object({}) # => [:*, :*]
|
176
|
-
def action_and_object(options)
|
177
|
-
[options[:allow] || options[:action] || :*, options[:with] || options[:object] || :*]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
data/lib/tight/version.rb
DELETED
data/test/auth_helper.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
ENV['RACK_ENV'] = 'test'
|
2
|
-
|
3
|
-
require 'padrino-core'
|
4
|
-
require 'tight-auth'
|
5
|
-
require 'minitest/autorun'
|
6
|
-
require 'rack/test'
|
7
|
-
|
8
|
-
module TightLogger
|
9
|
-
attr_accessor :io
|
10
|
-
def self.io
|
11
|
-
@io ||= StringIO.new
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Padrino::Logger::Config[:test] = { :log_level => :devel, :stream => TightLogger.io }
|
16
|
-
|
17
|
-
class Minitest::Spec
|
18
|
-
include Rack::Test::Methods
|
19
|
-
|
20
|
-
def mock_app(base=Padrino::Application, &block)
|
21
|
-
@app = Sinatra.new(base, &block)
|
22
|
-
end
|
23
|
-
|
24
|
-
def app
|
25
|
-
Rack::Lint.new(@app)
|
26
|
-
end
|
27
|
-
|
28
|
-
def set_access(*args)
|
29
|
-
@app.set_access(*args)
|
30
|
-
end
|
31
|
-
|
32
|
-
def allow(subject = nil, path = '/')
|
33
|
-
@app.fake_session[:visitor] = nil
|
34
|
-
get "/login/#{subject.id}" if subject
|
35
|
-
get path
|
36
|
-
assert_equal 200, status, caller.first.to_s
|
37
|
-
end
|
38
|
-
|
39
|
-
def deny(subject = nil, path = '/')
|
40
|
-
@app.fake_session[:visitor] = nil
|
41
|
-
get "/login/#{subject.id}" if subject
|
42
|
-
get path
|
43
|
-
assert_equal 403, status, caller.first.to_s
|
44
|
-
end
|
45
|
-
|
46
|
-
def status
|
47
|
-
response.status
|
48
|
-
end
|
49
|
-
|
50
|
-
def body
|
51
|
-
response.body
|
52
|
-
end
|
53
|
-
|
54
|
-
def response
|
55
|
-
last_response
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
module Character
|
60
|
-
extend self
|
61
|
-
|
62
|
-
def authenticate(credentials)
|
63
|
-
case
|
64
|
-
when credentials[:email] && credentials[:password]
|
65
|
-
target = all.find{ |resource| resource.id.to_s == credentials[:email] }
|
66
|
-
target.name.gsub(/[^A-Z]/,'') == credentials[:password] ? target : nil
|
67
|
-
when credentials.has_key?(:id)
|
68
|
-
all.find{ |resource| resource.id == credentials[:id] }
|
69
|
-
else
|
70
|
-
false
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def all
|
75
|
-
@all = [
|
76
|
-
OpenStruct.new(:id => :bender, :name => 'Bender Bending Rodriguez', :role => :robots ),
|
77
|
-
OpenStruct.new(:id => :leela, :name => 'Turanga Leela', :role => :mutants ),
|
78
|
-
OpenStruct.new(:id => :fry, :name => 'Philip J. Fry', :role => :humans ),
|
79
|
-
OpenStruct.new(:id => :ami, :name => 'Amy Wong', :role => :humans ),
|
80
|
-
OpenStruct.new(:id => :zoidberg, :name => 'Dr. John A. Zoidberg', :role => :lobsters),
|
81
|
-
]
|
82
|
-
end
|
83
|
-
end
|
data/test/test_padrino_access.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
require File.expand_path('../auth_helper', __FILE__)
|
2
|
-
|
3
|
-
describe "Tight::Access" do
|
4
|
-
before do
|
5
|
-
mock_app do
|
6
|
-
set :credentials_reader, :visitor
|
7
|
-
register Tight::Access
|
8
|
-
set_access :*, :allow => :login
|
9
|
-
set :users, Character.all
|
10
|
-
get(:login, :with => :id) do
|
11
|
-
user = settings.users.find{ |user| user.id.to_s == params[:id] }
|
12
|
-
self.send(:"#{settings.credentials_reader}=", user)
|
13
|
-
end
|
14
|
-
get(:index){ 'foo' }
|
15
|
-
get(:bend){ 'bend' }
|
16
|
-
get(:drink){ 'bend' }
|
17
|
-
get(:subject){ self.send(settings.credentials_reader).inspect }
|
18
|
-
get(:stop_partying){ 'stop partying' }
|
19
|
-
controller :surface do
|
20
|
-
get(:live) { 'live on the surface' }
|
21
|
-
end
|
22
|
-
controller :sewers do
|
23
|
-
get(:live) { 'live in the sewers' }
|
24
|
-
get(:visit) { 'visit the sewers' }
|
25
|
-
end
|
26
|
-
set :fake_session, {}
|
27
|
-
helpers do
|
28
|
-
def visitor
|
29
|
-
settings.fake_session[:visitor]
|
30
|
-
end
|
31
|
-
def visitor=(user)
|
32
|
-
settings.fake_session[:visitor] = user
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
Character.all.each do |user|
|
37
|
-
instance_variable_set :"@#{user.id}", user
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'should register with authorization module' do
|
42
|
-
assert @app.respond_to? :set_access
|
43
|
-
assert_kind_of Tight::Permissions, @app.permissions
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should properly detect access subject' do
|
47
|
-
set_access :*
|
48
|
-
get '/login/ami'
|
49
|
-
get '/subject'
|
50
|
-
assert_equal @ami.inspect, body
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should reset access properly' do
|
54
|
-
set_access :*
|
55
|
-
allow
|
56
|
-
@app.reset_access!
|
57
|
-
deny
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'should set group access' do
|
61
|
-
# only humans should be allowed on TV
|
62
|
-
set_access :humans
|
63
|
-
allow @fry
|
64
|
-
deny @bender
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should set individual access' do
|
68
|
-
# only Fry should be allowed to romance Leela
|
69
|
-
set_access @fry
|
70
|
-
allow @fry
|
71
|
-
deny @ami
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'should set mixed individual and group access' do
|
75
|
-
# only humans and Leela should be allowed on the surface
|
76
|
-
set_access :humans
|
77
|
-
set_access @leela
|
78
|
-
allow @fry
|
79
|
-
allow @leela
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'should set action-specific access' do
|
83
|
-
# bender should be allowed to bend, and he's denied to stop partying
|
84
|
-
set_access @bender, :allow => :bend
|
85
|
-
set_access @fry, :allow => :stop_partying
|
86
|
-
allow @bender, '/bend'
|
87
|
-
deny @bender, '/stop_partying'
|
88
|
-
allow @fry, '/stop_partying'
|
89
|
-
deny @fry, '/bend'
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'should set multiple action' do
|
93
|
-
# bender should be allowed to bend and drink
|
94
|
-
set_access @bender, :allow => [:drink, :bend]
|
95
|
-
allow @bender, '/drink'
|
96
|
-
allow @bender, '/bend'
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should set object-specific access' do
|
100
|
-
# only humans and Leela should be allowed to live on the surface
|
101
|
-
# only mutants should be allowed to live in the sewers though humans can visit
|
102
|
-
set_access :humans, :allow => :live, :with => :surface
|
103
|
-
set_access :mutants, :allow => :live, :with => :sewers
|
104
|
-
set_access @leela, :allow => :live, :with => :surface
|
105
|
-
set_access :humans, :allow => :visit, :with => :sewers
|
106
|
-
allow @fry, '/surface/live'
|
107
|
-
deny @fry, '/sewers/live'
|
108
|
-
allow @fry, '/sewers/visit'
|
109
|
-
allow @leela, '/surface/live'
|
110
|
-
allow @leela, '/sewers/live'
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'should detect object when setting access from controller' do
|
114
|
-
# only humans and lobsters should have binocular vision
|
115
|
-
@app.controller :binocular do
|
116
|
-
set_access :humans, :lobsters
|
117
|
-
get(:vision) { 'binocular vision' }
|
118
|
-
end
|
119
|
-
deny @fry, '/'
|
120
|
-
allow @fry, '/binocular/vision'
|
121
|
-
allow @zoidberg, '/binocular/vision'
|
122
|
-
deny @leela, '/binocular/vision'
|
123
|
-
end
|
124
|
-
end
|