can_camel 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19f8ade41da75b5b9b3beb17bc729b62fae529e3
4
- data.tar.gz: 44fd15e4109320bc9143dd4acb992bed642955b3
3
+ metadata.gz: 6cd2a7e24ff8c42df996b7255ecfc0710ae5b011
4
+ data.tar.gz: 97d7813911fdbbcc34c765243df8f047fceef026
5
5
  SHA512:
6
- metadata.gz: f02195d10717ac041a2e64df9b893d8f2d14a91051bdaa87a3b5e4cc668dda8f4e8dc932744330d982905e8a2b216fbebc7ec7d033b02549dd3287b88e6638c2
7
- data.tar.gz: 590a5bd7ec97794d11638630d45561b496f3279428ab8dadb83078b12b65437d6ca859de64694fe0a3ce30c7b2c6a869116f6f5c0de87bdd1e607e4b76878504
6
+ metadata.gz: 89e48cc509dfe2269a5f308e3234fbcbe2400642b22c916b44937b72f32fcbfb57eaa28de6d4162b23e4d69f37cd4a6a222ca79270994faf6a29d0ff01ba5338
7
+ data.tar.gz: c765a6da93ea8aa404105b405a22a8598348a5c4a42b54c36655f6c471c61d46228eeb3c077962f88c933457aa4a641ec09e641dc4d3fd3d4faf16e1b86e18e2
@@ -0,0 +1,65 @@
1
+ CanCamel
2
+ ========
3
+ This project uses WTFPL license, requires postgresql db adapter and rocks <br>
4
+ Upstream have not been tested in production, take a lot of care
5
+ What is CanCamel?
6
+ =================
7
+ CanCamel is a ruby gem for access control. For example, we can want to know
8
+ `can camel write a poem?` We can write it as `can?(camel, :write, :poem)`
9
+ This code calls function with 3 arguments: user (actor), action and subject and returns hash or nil
10
+ For example, we can grant camel full poem access (but only for actions that exists).
11
+ We can let camel write poems only in fridays midnight, why not? Any optional params
12
+ can be passed to a filter. Any custom filters could be made and any additional data
13
+ (e.g. maximal poem length allowed) can be passed back
14
+
15
+ Step 1. Installation
16
+ ====================
17
+ run rails g can_camel:install <br>
18
+ Then visit generated initializer at config/initializers/can_camel.rb
19
+ <pre>
20
+ # CanCamel::Filters.include AbilityFilters
21
+ CanCamel::TABLE_NAME = "can_camel_nodes"
22
+ CanCamel::GROUP_METHOD = :group
23
+ </pre>
24
+ First line describes how to use you own filters. You may prefer `prepend` over `include`
25
+ here. You can also specify table name, if you want. Third line describes a symbol, which references for
26
+ user model method, returning user group. Group should be a symbol. Visit spec/dummy/app/models/user.rb
27
+ for example. When you sure with this file, run generated migration.
28
+ Remember, that migration installs 'hstore' plugin, on which relies,
29
+ but does not remove it. If you want to revert it, you may want to remove plugin too
30
+
31
+ Step 2. Database structure
32
+ ==========================
33
+ Database consists of nodes. Primary nodes (WHERE parent_id IS NULL) are called subjects,
34
+ Their children are called actions, and actions' children are called groups. Groups' children
35
+ are called garbage and never used. Any node can have conditions and results. Conditions' syntax is
36
+ <pre>
37
+ [
38
+ { method: :day_of_week, allow: %w(saturday sunday) }
39
+ ]
40
+ </pre>
41
+ It means, that :day_of_week will be called with `allow: {"saturday", "sunday}"` argument
42
+
43
+ Step 3. Linting
44
+ ===============
45
+ If you are working primary with database (e.g. in migration), you can call
46
+ `CanCamel.lint` to check is database correct. Best way is to call `CanCamel.lint!` in transaction
47
+ with all changes done and enjoy your exception if need
48
+
49
+ Step 4. Constrains (Incomplete)
50
+ ===============================
51
+ Filters have great powers, and with big power big responsibility comes. For example, you are managing
52
+ statistics access on Users, and your filter scoping them. What if your filter would be called for Blog?
53
+ I think, nothing good. To prevent it, you can write a constraint
54
+ <pre>
55
+ validate :filter_name, subject: :user
56
+ def filter_name
57
+ #TODO: do something
58
+ end
59
+ </pre>
60
+
61
+ Step 5. Human interface (NIY)
62
+ ============================
63
+ Nodes supports some usefull methods to work with them
64
+ * `Node#aviable_filters` returns all filters available
65
+ * `Node#handling_params` returns list of all results available
@@ -1,7 +1,7 @@
1
1
  module CanCamel
2
2
  extend ActiveSupport::Autoload
3
3
  %i(Base Node SubjectNode ActionNode GroupNode ConcernNode Linter Filters
4
- Validators Cache FilterHelper)
4
+ Validators Cache)
5
5
  .each { |x| autoload(x) }
6
6
 
7
7
  extend CanCamel::Base
@@ -3,8 +3,8 @@ module CanCamel
3
3
  # don't delegate all, because lint_node designed to be run on same instances of linter
4
4
  delegate :lint, :lint!, to: :new_linter
5
5
 
6
- def can?(group, action, subject, **args)
7
- Cache[[group, action, subject]].try(:can?, args)
6
+ def can?(user, action, subject, **args)
7
+ Cache[[user.send(GROUP_METHOD), action, subject]].try(:can?, args)
8
8
  end
9
9
 
10
10
  private
@@ -1,21 +1,19 @@
1
1
  require 'can_camel/validators'
2
2
  module CanCamel::Filters
3
3
  include CanCamel::Validators
4
- extend CanCamel::FilterHelper
5
4
  ArgSyntaxError = Class.new(StandardError)
6
5
 
7
6
  module_function
8
7
 
9
8
  validates :at_time, :hours, presence: {}
10
9
  def at_time(hours:, **_)
11
- hours = from_int_array hours
12
10
  hours.include?(Time.now.hour) && {}
13
11
  end
14
12
 
15
13
  validates :at_day, presence_of: { fields: [:days, :wdays], any: true }
16
14
  def at_day(days: nil, wdays: nil, **_)
17
- return if days && !from_int_array(days).include?(Time.now.day)
18
- return if wdays && !from_int_array(wdays).include?(Time.now.wday)
15
+ return if days && !days.include?(Time.now.day)
16
+ return if wdays && !wdays.include?(Time.now.wday)
19
17
  {}
20
18
  end
21
19
  end
@@ -5,10 +5,9 @@ module CanCamel
5
5
  validates_presence_of :parent_id
6
6
 
7
7
  def can?(**additional_params)
8
- condition.each_with_object(result.dup) do |hash, result|
9
- hash.symbolize_keys!
10
- raise Linter::LintingError unless hash[:method]
11
- filtered = Filters.send(hash[:method], **hash.merge(additional_params))
8
+ condition.each_with_object(result.dup) do |(method, args), result|
9
+ args = args.symbolize_keys
10
+ filtered = Filters.send(method, **args.merge(additional_params))
12
11
  return unless filtered
13
12
  result.merge! filtered
14
13
  end || result
@@ -19,10 +19,8 @@ module CanCamel
19
19
  private
20
20
 
21
21
  def validate_node(node)
22
- node.condition.each do |hash|
23
- hash.symbolize_keys!
24
- raise LintingError unless hash[:method]
25
- Validators.validate!(filter: hash[:method], args: hash)
22
+ node.condition.each do |method, args|
23
+ Validators.validate!(filter: method, args: args.symbolize_keys)
26
24
  end
27
25
  true
28
26
  rescue Validators::ValidationError, LintingError
@@ -19,12 +19,14 @@ module CanCamel
19
19
 
20
20
  validates! :inherited, absence: { message: "You should not save inherited nodes!" }
21
21
 
22
- # accessors
23
-
24
22
  def name
25
23
  super.to_sym
26
24
  end
27
25
 
26
+ def condition
27
+ super.symbolize_keys
28
+ end
29
+
28
30
  private
29
31
 
30
32
  attr_reader :inherited
@@ -36,13 +38,7 @@ module CanCamel
36
38
 
37
39
  inherit_field(source, :description) { |x| self.description ||= x }
38
40
  inherit_field(source, :result) { |x| result.merge!(x) { |_k, l, _r| l } }
39
-
40
- inherit_field(source, :condition) do |new|
41
- methods = condition.map { |c| c['method'] }
42
- new.each do |x|
43
- condition.push(x) unless methods.include? x['method']
44
- end
45
- end
41
+ inherit_field(source, :condition) { |x| self.condition = x.merge(condition) }
46
42
  end
47
43
 
48
44
  def inherit_field(source, field)
@@ -1,3 +1,3 @@
1
1
  module CanCamel
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -2,3 +2,4 @@
2
2
  # require 'can_camel/filters'
3
3
  # CanCamel::Filters.include AbilityFilters
4
4
  CanCamel::TABLE_NAME = "can_camel_nodes"
5
+ CanCamel::GROUP_METHOD = :group
@@ -0,0 +1,14 @@
1
+ class HstoreToJson < ActiveRecord::Migration
2
+ def change
3
+ unless ENV['RAILS_ENV'] == 'test' || ENV['FORCE_CAN_CAMEL_WIPE'] == 'true'
4
+ puts "Attention! This migration will wipe can_camel data. Continue? (Y/n)"
5
+ puts "Set FORCE_CAN_CAMEL_WIPE=true to automaticaly accept"
6
+ res = STDIN.gets
7
+ raise unless res =~ /\A[Yy]/
8
+ end
9
+ CanCamel::Node.delete_all
10
+ remove_column CanCamel::TABLE_NAME, :condition, :hstore, array: true, default: []
11
+ add_column CanCamel::TABLE_NAME, :condition, :json, default: {}
12
+ CanCamel::Node.delete_all
13
+ end
14
+ end
@@ -4,5 +4,6 @@ class CanCamel::InstallGenerator < Rails::Generators::Base
4
4
  def install
5
5
  copy_file 'config/initializers/can_camel.rb'
6
6
  copy_file 'db/migrate/00000000000001_create_can_camel_nodes.rb'
7
+ copy_file 'db/migrate/00000000000002_hstore_to_json.rb'
7
8
  end
8
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: can_camel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Smirnov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-08 00:00:00.000000000 Z
11
+ date: 2015-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,26 +16,26 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.0
19
+ version: '4.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 4.2.0
26
+ version: '4.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pg
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description: |2
@@ -47,13 +47,13 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - LICENSE
50
+ - README.md
50
51
  - Rakefile
51
52
  - lib/can_camel.rb
52
53
  - lib/can_camel/action_node.rb
53
54
  - lib/can_camel/base.rb
54
55
  - lib/can_camel/cache.rb
55
56
  - lib/can_camel/concern_node.rb
56
- - lib/can_camel/filter_helper.rb
57
57
  - lib/can_camel/filters.rb
58
58
  - lib/can_camel/group_node.rb
59
59
  - lib/can_camel/linter.rb
@@ -63,6 +63,7 @@ files:
63
63
  - lib/can_camel/version.rb
64
64
  - lib/generators/can_camel/config/initializers/can_camel.rb
65
65
  - lib/generators/can_camel/db/migrate/00000000000001_create_can_camel_nodes.rb
66
+ - lib/generators/can_camel/db/migrate/00000000000002_hstore_to_json.rb
66
67
  - lib/generators/can_camel/install_generator.rb
67
68
  - lib/tasks/can_camel_tasks.rake
68
69
  homepage: https://github.com/JelF/can_camel
@@ -75,9 +76,9 @@ require_paths:
75
76
  - lib
76
77
  required_ruby_version: !ruby/object:Gem::Requirement
77
78
  requirements:
78
- - - ">="
79
+ - - ">"
79
80
  - !ruby/object:Gem::Version
80
- version: '0'
81
+ version: '2.1'
81
82
  required_rubygems_version: !ruby/object:Gem::Requirement
82
83
  requirements:
83
84
  - - ">="
@@ -1,15 +0,0 @@
1
- # Holds functions to parse params from strings
2
- module CanCamel
3
- module FilterHelper
4
- def from_int_array(str)
5
- from_array(str).map(&:to_i)
6
- rescue
7
- raise Filters::ArgSyntaxError
8
- end
9
-
10
- def from_array(str)
11
- raise Filters::ArgSyntaxError unless /\A\[(?<els>.+)\]\z/ =~ str
12
- els.split ','
13
- end
14
- end
15
- end