tight-engine 0.0.1 → 0.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.
- 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
|