ixtlan-guard 0.6.0 → 0.6.1
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/features/generators.feature +18 -0
- data/features/step_definitions/ruby_maven.rb +170 -0
- data/features/step_definitions/simple_steps.rb +82 -0
- data/lib/generators/guard/controller/controller_generator.rb~ +22 -0
- data/lib/generators/guard/templates/guard.yml~ +20 -0
- data/lib/ixtlan/guard/abstract_session.rb +61 -0
- data/lib/ixtlan/guard/abstract_session.rb~ +59 -0
- data/lib/ixtlan/guard/guard_config.rb~ +47 -0
- data/lib/ixtlan/guard/guard_ng.rb~ +81 -0
- data/lib/ixtlan/guard/guard_rails.rb~ +68 -0
- data/lib/ixtlan/guard/permission_builder.rb~ +7 -0
- data/spec/guard_cache_spec.rb~ +73 -0
- data/spec/guard_export_spec.rb~ +89 -0
- data/spec/guards/accounts1_guard.yml~ +3 -0
- data/spec/guards/accounts2_guard.yml~ +2 -0
- data/spec/guards/defaults_guard.yml~ +5 -0
- data/spec/guards/no_defaults_guard.yml~ +6 -0
- data/spec/guards/tools_guard.yml~ +3 -0
- data/spec/guards/users1_guard.yml~ +2 -0
- data/spec/guards/users2_guard.yml~ +3 -0
- data/spec/guards/users_guard.yml~ +13 -0
- metadata +27 -6
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Generators for ixtlan-guard
|
2
|
+
|
3
|
+
Scenario: The guard generator creates a guard file for each controller
|
4
|
+
Given I create new rails application with template "simple.template" and "simple" tests
|
5
|
+
And I execute "rails generate controller users promote go"
|
6
|
+
And I execute "rails generate scaffold account name:string --skip"
|
7
|
+
And I execute "rake db:migrate test"
|
8
|
+
Then the output should contain "7 tests, 10 assertions, 0 failures, 0 errors"
|
9
|
+
|
10
|
+
Scenario: The user-management-model generator creates user/group models, etc
|
11
|
+
Given I create new rails application with template "user_management.template" and "user-management" specs
|
12
|
+
And I execute "rails generate rspec:install"
|
13
|
+
And I execute "rails generate ixtlan:user_management_models user group name:string domain name:string locale code:string"
|
14
|
+
# this tes env is needed since we execute the specs directly
|
15
|
+
And I execute "rails rake db:migrate -- -Drails.env=test"
|
16
|
+
# needed due to bug in rspec-maven-plugin with emtpy gem-path
|
17
|
+
And I execute "gem exec ../rubygems/bin/rspec spec/user_management_models_spec.rb"
|
18
|
+
Then the output should contain "14 examples, 0 failures"
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Maven
|
4
|
+
class RubyMaven
|
5
|
+
|
6
|
+
# make the command line for the goals of the jruby-maven-plugins nicer
|
7
|
+
PLUGINS = {
|
8
|
+
:rake => [:rake],
|
9
|
+
:ruby => [:jruby, :compile],
|
10
|
+
:gem => [:package, :install, :push, :exec, :pom, :initialize, :irb],
|
11
|
+
:gemify => [:gemify, :versions],
|
12
|
+
:rails2 => [:new, :generate, :rake, :server, :console],
|
13
|
+
:rails3 => [:new, :generate, :rake, :server, :console, :dbconsole, :pom, :initialize],
|
14
|
+
:cucumber => [:test],
|
15
|
+
:rspec => [:test],
|
16
|
+
:runit => [:test],
|
17
|
+
:bundler => [:install]
|
18
|
+
}
|
19
|
+
ALIASES = {
|
20
|
+
:jruby => :ruby,
|
21
|
+
:spec => :rspec,
|
22
|
+
:rails => :rails3,
|
23
|
+
:bundle => :bundler
|
24
|
+
}
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@command = "#{ENV['GEM_HOME']}/bin/rmvn"
|
28
|
+
@jruby = File.read(@command).split("\n")[0].sub(/^#!/, '')
|
29
|
+
@maven_home = File.expand_path(Dir.glob("#{ENV['GEM_HOME']}/gems/ruby-maven-*-java")[0])
|
30
|
+
end
|
31
|
+
|
32
|
+
def launch_jruby(args)
|
33
|
+
classpath_array.each do |path|
|
34
|
+
require path
|
35
|
+
end
|
36
|
+
|
37
|
+
java.lang.System.setProperty("classworlds.conf",
|
38
|
+
File.join(@maven_home, 'bin', "m2.conf"))
|
39
|
+
|
40
|
+
java.lang.System.setProperty("maven.home", @maven_home)
|
41
|
+
|
42
|
+
org.codehaus.plexus.classworlds.launcher.Launcher.main(args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def classpath_array
|
46
|
+
(Dir.glob(File.join(@maven_home, "boot", "*jar")) +
|
47
|
+
Dir.glob(File.join(@maven_home, "ext", "ruby-tools*jar"))).each do |path|
|
48
|
+
path
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def launch_java(*args)
|
53
|
+
"java -cp #{classpath_array.join(':')} -Dmaven.home=#{File.expand_path(@maven_home)} -Dclassworlds.conf=#{File.expand_path(File.join(@maven_home, 'bin', 'm2.conf'))} org.codehaus.plexus.classworlds.launcher.Launcher #{args.join ' '}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def prepare(args)
|
57
|
+
if args.size > 0
|
58
|
+
name = args[0].to_sym
|
59
|
+
name = ALIASES[name] || name
|
60
|
+
if PLUGINS.member?(name)
|
61
|
+
start = 1
|
62
|
+
if args.size > 1
|
63
|
+
if PLUGINS[name].member? args[1].to_sym
|
64
|
+
goal = args[1].to_sym
|
65
|
+
start = 2
|
66
|
+
else
|
67
|
+
goal = PLUGINS[name][0]
|
68
|
+
end
|
69
|
+
else
|
70
|
+
goal = PLUGINS[name][0]
|
71
|
+
end
|
72
|
+
aa = if index = args.index("--")
|
73
|
+
args[(index + 1)..-1]
|
74
|
+
else
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
ruby_args = (args[start, (index || 1000) - start] || []).join(' ')
|
78
|
+
|
79
|
+
# determine the version and delete from args if given
|
80
|
+
version = args.detect do |a|
|
81
|
+
a =~ /^-Dplugin.version=/
|
82
|
+
end
|
83
|
+
if version
|
84
|
+
aa.delete(version)
|
85
|
+
version.sub!(/^-Dplugin.version=/, ':')
|
86
|
+
end
|
87
|
+
aa << "de.saumya.mojo:#{name}-maven-plugin#{version}:#{goal}"
|
88
|
+
aa << "-Dargs=#{ruby_args}" if ruby_args.size > 0
|
89
|
+
args.replace(aa)
|
90
|
+
else
|
91
|
+
args.delete("--")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
args
|
95
|
+
end
|
96
|
+
|
97
|
+
def log(args)
|
98
|
+
log = File.join('log', 'rmvn.log')
|
99
|
+
if File.exists? File.dirname(log)
|
100
|
+
File.open(log, 'a') do |f|
|
101
|
+
f.puts args.join ' '
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def maybe_print_help(args)
|
107
|
+
if args.size == 0 || args[0] == "--help"
|
108
|
+
puts "usage: rmvn [<plugin name>|<plugin alias> [<args>] [-- <maven options>] | [<maven goal>|<maven phase> <maven options>] | --help"
|
109
|
+
PLUGINS.each do |name, goals|
|
110
|
+
puts
|
111
|
+
print "plugin #{name}"
|
112
|
+
print " - alias: #{ALIASES[name]}" if ALIASES[name]
|
113
|
+
puts
|
114
|
+
if goals.size > 1
|
115
|
+
print "\tgoals : #{goals.join(',')}"
|
116
|
+
puts
|
117
|
+
end
|
118
|
+
print "\tdefault goal: #{goals[0]}"
|
119
|
+
puts
|
120
|
+
end
|
121
|
+
puts
|
122
|
+
["--help"]
|
123
|
+
else
|
124
|
+
args
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def options
|
129
|
+
@options ||= {}
|
130
|
+
end
|
131
|
+
|
132
|
+
def options_string
|
133
|
+
options_array.join ' '
|
134
|
+
end
|
135
|
+
|
136
|
+
def options_array
|
137
|
+
options.collect do |k,v|
|
138
|
+
if k =~ /^-D/
|
139
|
+
v = "=#{v}" if v
|
140
|
+
else
|
141
|
+
v = " #{v}" if v
|
142
|
+
end
|
143
|
+
"#{k}#{v}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def command_line(args)
|
148
|
+
args = prepare(args)
|
149
|
+
args = maybe_print_help(args)
|
150
|
+
args
|
151
|
+
end
|
152
|
+
|
153
|
+
def exec(*args)
|
154
|
+
a = command_line(args.dup.flatten)
|
155
|
+
a << options_array
|
156
|
+
a.flatten!
|
157
|
+
#puts a.join ' '
|
158
|
+
#launch_jruby(a)
|
159
|
+
args_line = args.join ' '
|
160
|
+
full = "#{@jruby} #{@command} #{args_line} #{args_line =~ / -- / ? '' : '--'} #{options_string}"
|
161
|
+
system full
|
162
|
+
end
|
163
|
+
|
164
|
+
def exec_in(launchdirectory, *args)
|
165
|
+
FileUtils.cd(launchdirectory) do
|
166
|
+
exec(args)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require File.join(File.dirname(__FILE__), 'ruby_maven')
|
3
|
+
|
4
|
+
def rmvn
|
5
|
+
@rmvn ||= Maven::RubyMaven.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def copy_tests(tests)
|
9
|
+
FileUtils.mkdir_p(@app_directory)
|
10
|
+
FileUtils.cp_r(File.join('templates', "tests-#{tests}", "."),
|
11
|
+
File.join(@app_directory, 'test'))
|
12
|
+
end
|
13
|
+
|
14
|
+
def copy_specs(specs)
|
15
|
+
FileUtils.mkdir_p(@app_directory)
|
16
|
+
FileUtils.cp_r(File.join('templates', "specs-#{specs}", "."),
|
17
|
+
File.join(@app_directory, 'spec'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_rails_application(template)
|
21
|
+
name = template.sub(/.template$/, '')
|
22
|
+
@app_directory = File.join('target', name)
|
23
|
+
|
24
|
+
# rails version from gemspec
|
25
|
+
gemspec = File.read(Dir.glob("*.gemspec")[0])
|
26
|
+
rails_version = gemspec.split("\n").detect { |l| l =~ /development_dep.*rails/ }.sub(/'$/, '').sub(/.*'/, '')
|
27
|
+
|
28
|
+
rmvn.options['-Dplugin.version'] = '0.28.4-SNAPSHOT'
|
29
|
+
rmvn.options['-Drails.version'] = rails_version
|
30
|
+
rmvn.options['-Dgem.home'] = ENV['GEM_HOME']
|
31
|
+
rmvn.options['-Dgem.path'] = ENV['GEM_PATH']
|
32
|
+
rmvn.options['-o'] = nil
|
33
|
+
|
34
|
+
FileUtils.rm_rf(@app_directory)
|
35
|
+
|
36
|
+
rmvn.exec("rails", "new", @app_directory, "-f")
|
37
|
+
|
38
|
+
# TODO that should be done via the rails new task !!!
|
39
|
+
rmvn.exec_in(@app_directory, "rails", "rake", "rails:template LOCATION=" + File.expand_path("templates/#{template}"))
|
40
|
+
end
|
41
|
+
|
42
|
+
Given /^I create new rails application with template "(.*)"$/ do |template|
|
43
|
+
create_rails_application(template)
|
44
|
+
end
|
45
|
+
|
46
|
+
Given /^I create new rails application with template "(.*)" and "(.*)" tests$/ do |template, tests|
|
47
|
+
create_rails_application(template)
|
48
|
+
copy_tests(tests)
|
49
|
+
end
|
50
|
+
|
51
|
+
Given /^I create new rails application with template "(.*)" and "(.*)" specs$/ do |template, specs|
|
52
|
+
create_rails_application(template)
|
53
|
+
copy_specs(specs)
|
54
|
+
end
|
55
|
+
|
56
|
+
Given /^me an existing rails application "(.*)"$/ do |name|
|
57
|
+
@app_directory = File.join('target', name)
|
58
|
+
end
|
59
|
+
|
60
|
+
Given /^me an existing rails application "(.*)" and "(.*)" tests$/ do |name, tests|
|
61
|
+
@app_directory = File.join('target', name)
|
62
|
+
copy_tests(tests)
|
63
|
+
end
|
64
|
+
|
65
|
+
Given /^me an existing rails application "(.*)" and "(.*)" specs$/ do |name, specs|
|
66
|
+
@app_directory = File.join('target', name)
|
67
|
+
copy_specs(specs)
|
68
|
+
end
|
69
|
+
|
70
|
+
And /^I execute \"(.*)\"$/ do |args|
|
71
|
+
rmvn.options['-l'] = "output.log"
|
72
|
+
rmvn.exec_in(@app_directory, args)
|
73
|
+
end
|
74
|
+
|
75
|
+
Then /^the output should contain \"(.*)\"$/ do |expected|
|
76
|
+
result = File.read(File.join(@app_directory, "output.log"))
|
77
|
+
expected.split(/\"?\s+and\s+\"?/).each do |exp|
|
78
|
+
puts exp
|
79
|
+
(result =~ /.*#{exp}.*/).should_not be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
class ControllerGenerator < Rails::Generators::NamedBase
|
3
|
+
|
4
|
+
source_root File.expand_path('../../templates', __FILE__)
|
5
|
+
|
6
|
+
argument :actions, :type => :array, :default => [], :banner => "action action"
|
7
|
+
|
8
|
+
check_class_collision :suffix => "Guard"
|
9
|
+
|
10
|
+
def create_guard_file
|
11
|
+
template 'guard.rb', File.join('app', 'guards', class_path, "#{file_name}_guard.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
def guard_class_name
|
15
|
+
class_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def aliases
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class <%= guard_class_name %>Guard
|
2
|
+
def initialize(guard)
|
3
|
+
#guard.name = "<%= plural_file_name %>"
|
4
|
+
<% if aliases -%>
|
5
|
+
guard.aliases = <%= aliases.inspect %>
|
6
|
+
<% end -%>
|
7
|
+
guard.action_map= {
|
8
|
+
<% case actions
|
9
|
+
when Array
|
10
|
+
for action in actions -%>
|
11
|
+
:<%= action %> => [],
|
12
|
+
<% end
|
13
|
+
when Hash
|
14
|
+
actions.each do |action, groups| -%>
|
15
|
+
:<%= action %> => <%= groups.inspect %>,
|
16
|
+
<% end
|
17
|
+
end -%>
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module Guard
|
3
|
+
class AbstractSession
|
4
|
+
|
5
|
+
attr_accessor :permissions, :user, :idle_session_timeout
|
6
|
+
|
7
|
+
def self.create(login, password)
|
8
|
+
self.do_create(authenticate(login, password))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create_remote(login, password)
|
12
|
+
self.do_create(authenticate_remote(login, password))
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.do_create(user)
|
18
|
+
result = new
|
19
|
+
|
20
|
+
if user.valid?
|
21
|
+
result.user = user
|
22
|
+
else
|
23
|
+
result.log = user.to_log # error message
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
public
|
29
|
+
|
30
|
+
def log=(msg)
|
31
|
+
@log = msg
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_log
|
35
|
+
if @log
|
36
|
+
@log
|
37
|
+
else
|
38
|
+
"Session(user-id: #{user.id}, idle-session-timeout: #{idle_session_timeout})"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def valid?
|
43
|
+
@log.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def attributes
|
47
|
+
{'idle_session_timeout' => idle_session_timeout, 'permissions' => permissions, 'user' => user}
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def self.authenticate(login, password)
|
53
|
+
raise "not implemented"
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.authenticate_remote(login, password)
|
57
|
+
raise "not implemented"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Resty
|
2
|
+
class AbstractSession
|
3
|
+
|
4
|
+
attr_accessor :permissions, :user, :idle_session_timeout
|
5
|
+
|
6
|
+
def self.create(login, password)
|
7
|
+
self.do_create(authenticate(login, password))
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.create_remote(login, password)
|
11
|
+
self.do_create(authenticate_remote(login, password))
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def self.do_create(user)
|
16
|
+
result = new
|
17
|
+
|
18
|
+
if user.valid?
|
19
|
+
result.user = user
|
20
|
+
else
|
21
|
+
result.log = user.to_log # error message
|
22
|
+
end
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
public
|
27
|
+
|
28
|
+
def log=(msg)
|
29
|
+
@log = msg
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_log
|
33
|
+
if @log
|
34
|
+
@log
|
35
|
+
else
|
36
|
+
"Session(user-id: #{user.id}, idle-session-timeout: #{idle_session_timeout})"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid?
|
41
|
+
@log.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def attributes
|
45
|
+
{'idle_session_timeout' => idle_session_timeout, 'permissions' => permissions, 'user' => user}
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def self.authenticate(login, password)
|
51
|
+
raise "not implemented"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.authenticate_remote(login, password)
|
55
|
+
raise "not implemented"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Ixtlan
|
3
|
+
module Guard
|
4
|
+
class Config
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@guards_dir = options[:guards_dir]
|
8
|
+
@load_method = options[:cache] ? :cached_load_from_yaml_file : :load_from_yaml_file
|
9
|
+
raise GuardException.new("guards directory does not exists: #{@guards_dir}") unless File.directory?(@guards_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
def allowed_groups(resource, action)
|
13
|
+
if resource && action
|
14
|
+
resource = resource.to_s
|
15
|
+
groups = send(@load_method, resource)
|
16
|
+
groups[action.to_s] || groups["defaults"] || []
|
17
|
+
else
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_guard?(resource)
|
23
|
+
File.exists? yaml_file(resource)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def cached_load_from_yaml_file(resource)
|
29
|
+
@cache ||= {}
|
30
|
+
@cache[resource] ||= load_from_yaml_file(resource)
|
31
|
+
end
|
32
|
+
|
33
|
+
def yaml_file(resource)
|
34
|
+
File.join(@guards_dir, "#{resource}_guard.yml")
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_from_yaml_file(resource)
|
38
|
+
file = yaml_file(resource)
|
39
|
+
if File.exists? file
|
40
|
+
YAML.load_file(file)[resource] || {}
|
41
|
+
else
|
42
|
+
{}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'ixtlan/guard/guard_config'
|
2
|
+
|
3
|
+
module Ixtlan
|
4
|
+
module Guard
|
5
|
+
class GuardNG
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
options[:guards_dir] ||= File.expand_path(".")
|
9
|
+
@superuser = [(options[:superuser] || "root").to_s]
|
10
|
+
@config = Config.new(options)
|
11
|
+
@logger = options[:logger]
|
12
|
+
end
|
13
|
+
|
14
|
+
def block_groups(groups)
|
15
|
+
@blocked_groups = (groups || []).collect { |g| g.to_s}
|
16
|
+
@blocked_groups.delete(@superuser)
|
17
|
+
@blocked_groups
|
18
|
+
end
|
19
|
+
|
20
|
+
def blocked_groups
|
21
|
+
@blocked_groups ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def logger
|
25
|
+
@logger ||=
|
26
|
+
if defined?(Slf4r::LoggerFactory)
|
27
|
+
Slf4r::LoggerFactory.new(Ixtlan::Guard)
|
28
|
+
else
|
29
|
+
require 'logger'
|
30
|
+
Logger.new(STDOUT)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def allowed(resource, action, current_groups)
|
35
|
+
current_groups = current_groups.collect { |g| g.to_s }
|
36
|
+
allowed = @config.allowed_groups(resource, action) - blocked_groups + @superuser
|
37
|
+
if allowed.member?('*')
|
38
|
+
current_groups
|
39
|
+
else
|
40
|
+
intersect(allowed, current_groups)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def allowed?(resource, action, current_groups, flavor = nil, &block)
|
45
|
+
allowed_groups = allowed(resource, action, current_groups)
|
46
|
+
logger.debug { "guard #{resource}##{action}: #{allowed_groups.size > 0}" }
|
47
|
+
if allowed_groups.size > 0
|
48
|
+
if block
|
49
|
+
g = allowed_groups.detect do |group|
|
50
|
+
block.call(group).member?(flavor)
|
51
|
+
end
|
52
|
+
logger.debug do
|
53
|
+
if g
|
54
|
+
"found group #{g} for #{flavor}"
|
55
|
+
else
|
56
|
+
"no group found for #{flavor}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
g != nil
|
60
|
+
else
|
61
|
+
true
|
62
|
+
end
|
63
|
+
else
|
64
|
+
unless @config.has_guard?(resource)
|
65
|
+
raise ::Ixtlan::Guard::GuardException.new("no guard config for '#{resource}'")
|
66
|
+
else
|
67
|
+
false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def intersect(set1, set2)
|
75
|
+
set1 - (set1 - set2)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
class GuardException < Exception; end
|
79
|
+
class PermissionDenied < GuardException; end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Ixtlan
|
2
|
+
module ActionController #:nodoc:
|
3
|
+
module Guard #:nodoc:
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
unless base.respond_to?(:groups_for_current_user)
|
7
|
+
base.send(:include, GroupsMethod)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module GroupsMethod
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def groups_for_current_user
|
16
|
+
if current_user
|
17
|
+
current_user.groups.collect do |group|
|
18
|
+
group.name
|
19
|
+
end
|
20
|
+
else
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module InstanceMethods #:nodoc:
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def guard
|
31
|
+
Rails.application.config.guard
|
32
|
+
end
|
33
|
+
|
34
|
+
def check(flavor = nil, &block)
|
35
|
+
unless guard.allowed?(params[:controller],
|
36
|
+
params[:action],
|
37
|
+
groups_for_current_user,
|
38
|
+
flavor,
|
39
|
+
block)
|
40
|
+
if flavor
|
41
|
+
raise ::Ixtlan::Guard::PermissionDenied.new("permission denied for '#{resource}##{action}##{flavor}'")
|
42
|
+
else
|
43
|
+
raise ::Ixtlan::Guard::PermissionDenied.new("permission denied for '#{resource}##{action}'")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorization
|
50
|
+
check
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Allowed #:nodoc:
|
57
|
+
# Inclusion hook to make #allowed available as method
|
58
|
+
def self.included(base)
|
59
|
+
base.send(:include, InstanceMethods)
|
60
|
+
end
|
61
|
+
|
62
|
+
module InstanceMethods #:nodoc:
|
63
|
+
def allowed?(resource, action)
|
64
|
+
controller.send(:guard).allowed?(controller, resource, action)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ixtlan/guard/guard_ng'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
describe Ixtlan::Guard::GuardNG do
|
6
|
+
|
7
|
+
subject do
|
8
|
+
logger = Logger.new(STDOUT)
|
9
|
+
def logger.debug(&block)
|
10
|
+
info("\n\t[debug] " + block.call)
|
11
|
+
end
|
12
|
+
Ixtlan::Guard::GuardNG.new(:guards_dir => File.join(File.dirname(__FILE__), "guards"), :logger => logger )
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should fail with missing guard dir' do
|
16
|
+
lambda {Ixtlan::Guard::GuardNG.new(:guards_dir => "does_not_exists") }.should raise_error(Ixtlan::Guard::GuardException)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should initialize' do
|
20
|
+
subject.should_not be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should fail without groups' do
|
24
|
+
subject.allowed?(:users, :something, []).should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should pass with user being root' do
|
28
|
+
subject.allowed?(:users, :show, [:root]).should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should pass "allow all groups" with user with any groups' do
|
32
|
+
subject.allowed?(:users, :index, [:any]).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should pass' do
|
36
|
+
subject.allowed?(:users, :update, [:users]).should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not pass with user when in blocked group' do
|
40
|
+
subject.block_groups([:users])
|
41
|
+
begin
|
42
|
+
subject.allowed?(:users, :update, [:users]).should be_false
|
43
|
+
ensure
|
44
|
+
subject.block_groups([])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should pass with user when not in blocked group' do
|
49
|
+
subject.block_groups([:accounts])
|
50
|
+
begin
|
51
|
+
subject.allowed?(:users, :update, [:users]).should be_true
|
52
|
+
ensure
|
53
|
+
subject.block_groups([])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should not block root group' do
|
58
|
+
subject.block_groups([:root])
|
59
|
+
begin
|
60
|
+
subject.allowed?(:users, :update, [:root]).should be_true
|
61
|
+
ensure
|
62
|
+
subject.block_groups([])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should not pass' do
|
67
|
+
subject.allowed?(:users, :update, [:accounts]).should be_false
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should should use defaults on unknown action' do
|
71
|
+
subject.allowed?(:users, :unknow, [:users]).should be_true
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ixtlan/guard/guard_ng'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
describe Ixtlan::Guard::GuardNG do
|
6
|
+
|
7
|
+
subject do
|
8
|
+
logger = Logger.new(STDOUT)
|
9
|
+
def logger.debug(&block)
|
10
|
+
info("\n\t[debug] " + block.call)
|
11
|
+
end
|
12
|
+
Ixtlan::Guard::GuardNG.new(:guards_dir => File.join(File.dirname(__FILE__), "guards"), :logger => logger )
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should fail with missing guard dir' do
|
16
|
+
lambda {Ixtlan::Guard::GuardNG.new(:guards_dir => "does_not_exists") }.should raise_error(Ixtlan::Guard::GuardException)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should initialize' do
|
20
|
+
subject.should_not be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should fail without groups' do
|
24
|
+
subject.allowed?(:users, :something, []).should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should pass with user being root' do
|
28
|
+
subject.allowed?(:users, :show, [:root]).should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should pass "allow all groups" with user with any groups' do
|
32
|
+
subject.allowed?(:users, :index, [:any]).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should pass' do
|
36
|
+
subject.allowed?(:users, :update, [:users]).should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not pass with user when in blocked group' do
|
40
|
+
subject.block_groups([:users])
|
41
|
+
begin
|
42
|
+
subject.allowed?(:users, :update, [:users]).should be_false
|
43
|
+
ensure
|
44
|
+
subject.block_groups([])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should pass with user when not in blocked group' do
|
49
|
+
subject.block_groups([:accounts])
|
50
|
+
begin
|
51
|
+
subject.allowed?(:users, :update, [:users]).should be_true
|
52
|
+
ensure
|
53
|
+
subject.block_groups([])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should not block root group' do
|
58
|
+
subject.block_groups([:root])
|
59
|
+
begin
|
60
|
+
subject.allowed?(:users, :update, [:root]).should be_true
|
61
|
+
ensure
|
62
|
+
subject.block_groups([])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should not pass' do
|
67
|
+
subject.allowed?(:users, :update, [:accounts]).should be_false
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should should use defaults on unknown action' do
|
71
|
+
subject.allowed?(:users, :unknow, [:users]).should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should pass with right group and allowed flavor' do
|
75
|
+
subject.allowed?(:users, :update, [:users], :example){ |g| [:example]}.should be_true
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should not pass with wrong group but allowed flavor' do
|
79
|
+
subject.allowed?(:users, :update, [:accounts], :example){ |g| [:example]}.should be_false
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should not pass with wrong group but disallowed flavor' do
|
83
|
+
subject.allowed?(:users, :update, [:accounts], :example){ |g| []}.should be_false
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should not pass with right group and disallowed flavor' do
|
87
|
+
subject.allowed?(:users, :update, [:users], :example){ |g| []}.should be_false
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ixtlan-guard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.6.
|
5
|
+
version: 0.6.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- mkristian
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-10-16 00:00:00 +05:30
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -19,12 +19,9 @@ dependencies:
|
|
19
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
|
-
- -
|
22
|
+
- - ~>
|
23
23
|
- !ruby/object:Gem::Version
|
24
24
|
version: 0.6.0
|
25
|
-
- - <
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: 0.6.99999
|
28
25
|
type: :runtime
|
29
26
|
version_requirements: *id001
|
30
27
|
- !ruby/object:Gem::Dependency
|
@@ -97,9 +94,11 @@ files:
|
|
97
94
|
- lib/generators/erb/user_management_controller_generator.rb
|
98
95
|
- lib/generators/guard/controller/USAGE
|
99
96
|
- lib/generators/guard/controller/controller_generator.rb
|
97
|
+
- lib/generators/guard/controller/controller_generator.rb~
|
100
98
|
- lib/generators/guard/scaffold/USAGE
|
101
99
|
- lib/generators/guard/scaffold/scaffold_generator.rb
|
102
100
|
- lib/generators/guard/templates/guard.yml
|
101
|
+
- lib/generators/guard/templates/guard.yml~
|
103
102
|
- lib/generators/ixtlan/user_management_scaffold/user_management_scaffold_generator.rb
|
104
103
|
- lib/generators/ixtlan/user_management_controller/USAGE
|
105
104
|
- lib/generators/ixtlan/user_management_controller/user_management_controller_generator.rb
|
@@ -116,27 +115,46 @@ files:
|
|
116
115
|
- lib/generators/active_record/templates/group_user_migration.rb
|
117
116
|
- lib/generators/active_record/templates/flavor_model.rb
|
118
117
|
- lib/ixtlan/guard.rb
|
118
|
+
- lib/ixtlan/guard/abstract_session.rb
|
119
|
+
- lib/ixtlan/guard/abstract_session.rb~
|
120
|
+
- lib/ixtlan/guard/guard_rails.rb~
|
119
121
|
- lib/ixtlan/guard/guard_ng.rb
|
122
|
+
- lib/ixtlan/guard/permission_builder.rb~
|
123
|
+
- lib/ixtlan/guard/guard_ng.rb~
|
120
124
|
- lib/ixtlan/guard/guard_config.rb
|
121
125
|
- lib/ixtlan/guard/guard_rails.rb
|
126
|
+
- lib/ixtlan/guard/guard_config.rb~
|
122
127
|
- lib/ixtlan/guard/railtie.rb
|
123
128
|
- lib/ixtlan/guard/controllers/maintenance_controller.rb
|
124
129
|
- lib/ixtlan/guard/controllers/permissions_controller.rb
|
125
130
|
- lib/ixtlan/guard/spec/user_management_models_spec.rb
|
126
131
|
- lib/ixtlan/guard/models/maintenance.rb
|
127
132
|
- lib/ixtlan/guard/models/user_update_manager.rb
|
133
|
+
- spec/guard_export_spec.rb~
|
128
134
|
- spec/guard_export_spec.rb
|
129
135
|
- spec/spec_helper.rb
|
130
136
|
- spec/guard_cache_spec.rb
|
137
|
+
- spec/guard_cache_spec.rb~
|
131
138
|
- spec/guard_spec.rb
|
132
139
|
- spec/railtie_spec.rb
|
140
|
+
- spec/guards/accounts1_guard.yml~
|
133
141
|
- spec/guards/users_guard.yml
|
134
142
|
- spec/guards/users2_guard.yml
|
143
|
+
- spec/guards/accounts2_guard.yml~
|
144
|
+
- spec/guards/users2_guard.yml~
|
145
|
+
- spec/guards/users_guard.yml~
|
146
|
+
- spec/guards/users1_guard.yml~
|
147
|
+
- spec/guards/tools_guard.yml~
|
135
148
|
- spec/guards/no_defaults_guard.yml
|
136
149
|
- spec/guards/defaults_guard.yml
|
137
150
|
- spec/guards/users1_guard.yml
|
138
151
|
- spec/guards/person_guard.yml
|
139
152
|
- spec/guards/accounts_guard.yml
|
153
|
+
- spec/guards/no_defaults_guard.yml~
|
154
|
+
- spec/guards/defaults_guard.yml~
|
155
|
+
- features/step_definitions/ruby_maven.rb
|
156
|
+
- features/step_definitions/simple_steps.rb
|
157
|
+
- features/generators.feature
|
140
158
|
has_rdoc: true
|
141
159
|
homepage: http://github.com/mkristian/ixtlan-guard
|
142
160
|
licenses:
|
@@ -170,3 +188,6 @@ test_files:
|
|
170
188
|
- spec/guard_cache_spec.rb
|
171
189
|
- spec/guard_spec.rb
|
172
190
|
- spec/railtie_spec.rb
|
191
|
+
- features/generators.feature
|
192
|
+
- features/step_definitions/ruby_maven.rb
|
193
|
+
- features/step_definitions/simple_steps.rb
|