strong_attributes 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/lib/strong_attributes.rb +0 -1
- data/lib/strong_attributes/displayable.rb +12 -22
- data/lib/strong_attributes/permissible.rb +5 -5
- data/lib/strong_attributes/permissions.rb +39 -11
- data/lib/strong_attributes/version.rb +1 -1
- data/spec/strong_attributes/permissions_spec.rb +1 -6
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c16f8c67c4ade076c784776b24f742121a9849d4
         | 
| 4 | 
            +
              data.tar.gz: 08273a443123e27eec2ff657ab62f23379e10511
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a8e313f21c846d34479baae0b5cf2b7635c5d8a4da653a6d73909c24b470377b75eea58a33cf5cf9341a5ba930b40a971492f19ab5575a6a765c0594a6c6ab02
         | 
| 7 | 
            +
              data.tar.gz: 5e1f356c3ef40603cb0f53c1898ad61e385f97ab3052d07529e8b510cc7e606a5881ea25de674fa39f11859f11c8e7c8631ebd7d9a1d6b3094a7ec85ac6a47c0
         | 
    
        data/lib/strong_attributes.rb
    CHANGED
    
    
| @@ -8,49 +8,39 @@ module StrongAttributes | |
| 8 8 | 
             
                # Calls and returns the result of each method call in the argument list. If a block is given, then each result
         | 
| 9 9 | 
             
                # is passed to the block.
         | 
| 10 10 | 
             
                #
         | 
| 11 | 
            -
                #   user. | 
| 11 | 
            +
                #   user.presents :username, :email # returns [user.username, user.email]
         | 
| 12 12 | 
             
                #
         | 
| 13 13 | 
             
                # Or with two arguments, the name of the field is passed first:
         | 
| 14 14 | 
             
                #
         | 
| 15 15 | 
             
                #   <ul>
         | 
| 16 | 
            -
                #     <% user. | 
| 16 | 
            +
                #     <% user.presents :username, :email, :address do |field, value| %>
         | 
| 17 17 | 
             
                #       <li><%= field.capitalize %>: <% value %></li>     
         | 
| 18 18 | 
             
                #     <% end %>
         | 
| 19 19 | 
             
                #   </ul>
         | 
| 20 20 | 
             
                #
         | 
| 21 21 | 
             
                # If only the presented value is desired, use `each`:
         | 
| 22 22 | 
             
                #
         | 
| 23 | 
            -
                #   <% user. | 
| 23 | 
            +
                #   <% user.presents(:username, :email).each do |value| %>
         | 
| 24 24 | 
             
                #     <td><%= value %></td>
         | 
| 25 25 | 
             
                #   <% end %>
         | 
| 26 26 | 
             
                #
         | 
| 27 27 | 
             
                # Arguments can be included in an array:
         | 
| 28 28 | 
             
                #
         | 
| 29 | 
            -
                #   user. | 
| 30 | 
            -
                #
         | 
| 31 | 
            -
                def  | 
| 32 | 
            -
                  select_permitted(*attributes).map do | | 
| 33 | 
            -
                     | 
| 34 | 
            -
                    value  | 
| 35 | 
            -
                    until args.empty? do
         | 
| 36 | 
            -
                      arity = value.method(args[0]).arity
         | 
| 37 | 
            -
                      if arity >= 0
         | 
| 38 | 
            -
                        value = value.public_send *args.slice!(0, arity+1)
         | 
| 39 | 
            -
                      else
         | 
| 40 | 
            -
                        value = value.public_send *args
         | 
| 41 | 
            -
                        break
         | 
| 42 | 
            -
                      end
         | 
| 43 | 
            -
                    end
         | 
| 44 | 
            -
                    yield attribute, value if block_given?
         | 
| 29 | 
            +
                #   user.presents :username, [:notifications, :unread] # returns [user.username, user.notifications(:unread)]
         | 
| 30 | 
            +
                #
         | 
| 31 | 
            +
                def presents *attributes
         | 
| 32 | 
            +
                  select_permitted(*attributes).map do |attribute_path|
         | 
| 33 | 
            +
                    value = Array(attribute_path).inject(self) { |obj, args| obj.public_send *args }
         | 
| 34 | 
            +
                    yield attribute_path, value if block_given?
         | 
| 45 35 | 
             
                    value
         | 
| 46 36 | 
             
                  end
         | 
| 47 37 | 
             
                end
         | 
| 48 38 |  | 
| 49 | 
            -
                # Same as  | 
| 39 | 
            +
                # Same as presents, but for a single attribute. The differences are:
         | 
| 50 40 | 
             
                #   - the return value is not in an Array
         | 
| 51 41 | 
             
                #   - passes the value only (without attribute key as the 1st argument) to a block
         | 
| 52 | 
            -
                def  | 
| 53 | 
            -
                   | 
| 42 | 
            +
                def present field
         | 
| 43 | 
            +
                  presents field do |key, value|
         | 
| 54 44 | 
             
                    yield value if block_given?
         | 
| 55 45 | 
             
                  end.first
         | 
| 56 46 | 
             
                end
         | 
| @@ -37,12 +37,12 @@ module StrongAttributes | |
| 37 37 | 
             
                  @permitted_attributes ||= StrongAttributes::Permissions.new
         | 
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 | 
            -
                # Links  | 
| 41 | 
            -
                # @param [ | 
| 40 | 
            +
                # Links permissions to that of the parent.
         | 
| 41 | 
            +
                # @param [Permissible] parent
         | 
| 42 42 | 
             
                # @param [Array<Symbol>] relative_path
         | 
| 43 | 
            -
                #   The prefix prepended before every permission check relative to parent | 
| 44 | 
            -
                def link_permissions  | 
| 45 | 
            -
                  @permitted_attributes = StrongAttributes::Permissions.new( | 
| 43 | 
            +
                #   The prefix prepended before every permission check relative to parent.
         | 
| 44 | 
            +
                def link_permissions parent, relative_path = []
         | 
| 45 | 
            +
                  @permitted_attributes = StrongAttributes::Permissions.new(parent.permitted_attributes, relative_path)
         | 
| 46 46 | 
             
                end
         | 
| 47 47 |  | 
| 48 48 | 
             
              end
         | 
| @@ -19,6 +19,7 @@ module StrongAttributes | |
| 19 19 | 
             
                def initialize(permissions = nil, prefix_path = [])
         | 
| 20 20 | 
             
                  unless permissions.nil?
         | 
| 21 21 | 
             
                    @permitted_paths = permissions.permitted_paths
         | 
| 22 | 
            +
                    @permittable_paths = permissions.permittable_paths
         | 
| 22 23 | 
             
                    @prefix_path = permissions.prefix_path + canonicalize(prefix_path) # copy on write
         | 
| 23 24 | 
             
                  end
         | 
| 24 25 | 
             
                end
         | 
| @@ -49,6 +50,11 @@ module StrongAttributes | |
| 49 50 | 
             
                  !path_tainted?(attribute_path) and permitted_by_wildcard?(prefix_path + attribute_path)  # wildcard match only if not tainted
         | 
| 50 51 | 
             
                end
         | 
| 51 52 |  | 
| 53 | 
            +
                def permittable? attribute_path
         | 
| 54 | 
            +
                  attribute_path = canonicalize(attribute_path)
         | 
| 55 | 
            +
                  permittable_paths.include?(prefix_path + attribute_path)
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 52 58 | 
             
                # Selects the attribute paths which are permitted.
         | 
| 53 59 | 
             
                # @param [Array] prefix_path
         | 
| 54 60 | 
             
                #   namespace in which each of the given attribute paths are in
         | 
| @@ -81,17 +87,37 @@ module StrongAttributes | |
| 81 87 | 
             
                  attribute_paths = attribute_paths.map{|path|canonicalize(path).taint} # exact match
         | 
| 82 88 | 
             
                  reject_permitted(*attribute_paths).each do |attribute_path| # don't permit if already permitted
         | 
| 83 89 | 
             
                    permitted_paths << attribute_path # prefix_path = [] because of copy on write
         | 
| 90 | 
            +
                    raw_permittable(attribute_path.slice(0...-1))
         | 
| 84 91 | 
             
                  end
         | 
| 85 92 | 
             
                  self
         | 
| 86 93 | 
             
                end
         | 
| 87 94 |  | 
| 95 | 
            +
                def permittable *attribute_paths
         | 
| 96 | 
            +
                  copy_on_write!
         | 
| 97 | 
            +
                  attribute_paths.each { |attribute_path| raw_permittable(canonicalize(attribute_path)) }
         | 
| 98 | 
            +
                  self
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 88 101 | 
             
                protected
         | 
| 89 102 |  | 
| 90 103 | 
             
                def permitted_paths
         | 
| 91 104 | 
             
                  @permitted_paths ||= Set.new
         | 
| 92 105 | 
             
                end
         | 
| 93 106 |  | 
| 107 | 
            +
                # some subpaths may be permitted
         | 
| 108 | 
            +
                def permittable_paths
         | 
| 109 | 
            +
                  @permittable_paths ||= Set.new
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 94 112 | 
             
                private
         | 
| 113 | 
            +
                # will mutate attribute_path
         | 
| 114 | 
            +
                def raw_permittable attribute_path
         | 
| 115 | 
            +
                  until attribute_path.empty? || permittable_paths.include?(attribute_path) do
         | 
| 116 | 
            +
                    permittable_paths << attribute_path.dup
         | 
| 117 | 
            +
                    attribute_path.pop
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 95 121 | 
             
                # Is this still referencing another objects permissions?
         | 
| 96 122 | 
             
                def reference?
         | 
| 97 123 | 
             
                  !@prefix_path.nil?
         | 
| @@ -101,15 +127,22 @@ module StrongAttributes | |
| 101 127 | 
             
                def copy_on_write!
         | 
| 102 128 | 
             
                  if prefix_path == []
         | 
| 103 129 | 
             
                    @permitted_paths = permitted_paths.dup
         | 
| 130 | 
            +
                    @permittable_paths = permittable_paths.dup
         | 
| 104 131 | 
             
                  elsif reference?
         | 
| 105 | 
            -
                    @permitted_paths | 
| 106 | 
            -
                     | 
| 107 | 
            -
                      @permitted_paths << path[prefix_path.size...path.size] if path[0...prefix_path.size] == prefix_path
         | 
| 108 | 
            -
                    end
         | 
| 132 | 
            +
                    @permitted_paths = dup_paths permitted_paths, prefix_path
         | 
| 133 | 
            +
                    @permittable_paths = dup_paths permittable_paths, prefix_path
         | 
| 109 134 | 
             
                  end
         | 
| 110 135 | 
             
                  @prefix_path = nil
         | 
| 111 136 | 
             
                end
         | 
| 112 137 |  | 
| 138 | 
            +
                def dup_paths old_set, prefix_path
         | 
| 139 | 
            +
                  new_set = Set.new
         | 
| 140 | 
            +
                  old_set.each do |path|
         | 
| 141 | 
            +
                    new_set << path[prefix_path.size...path.size] if path[0...prefix_path.size] == prefix_path
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
                  new_set
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 113 146 | 
             
                def path_tainted? attribute_path
         | 
| 114 147 | 
             
                  attribute_path.tainted? or attribute_path.any? { |element| element.tainted? }
         | 
| 115 148 | 
             
                end
         | 
| @@ -120,19 +153,14 @@ module StrongAttributes | |
| 120 153 | 
             
                    path[-1] = :*
         | 
| 121 154 | 
             
                    return true if permitted_paths.include? path
         | 
| 122 155 | 
             
                  end
         | 
| 123 | 
            -
                  until path.empty?
         | 
| 124 | 
            -
                    path[-1] = :**
         | 
| 125 | 
            -
                    return true if permitted_paths.include? path
         | 
| 126 | 
            -
                    path.pop
         | 
| 127 | 
            -
                  end
         | 
| 128 156 | 
             
                  false
         | 
| 129 157 | 
             
                end
         | 
| 130 158 |  | 
| 131 159 | 
             
                # Converts symbols to strings (except for wildcard symbol)
         | 
| 132 160 | 
             
                def canonicalize array
         | 
| 133 161 | 
             
                  array = Array(array)
         | 
| 134 | 
            -
                  canonical_array = array.map{|e|e.is_a?(Symbol) ? e.to_s : e}
         | 
| 135 | 
            -
                  canonical_array[-1] = array.last if  | 
| 162 | 
            +
                  canonical_array = array.map{|e| (e.is_a?(Array) ? e.first : e).instance_eval{ self.is_a?(Symbol) ? e.to_s : e } }
         | 
| 163 | 
            +
                  canonical_array[-1] = array.last if array.last == :*
         | 
| 136 164 | 
             
                  canonical_array.taint if array.tainted?
         | 
| 137 165 | 
             
                  canonical_array
         | 
| 138 166 | 
             
                end
         | 
| @@ -47,18 +47,13 @@ module StrongAttributes | |
| 47 47 | 
             
                describe "#permitted?" do
         | 
| 48 48 | 
             
                  context 'with some attributes permitted' do
         | 
| 49 49 | 
             
                    before(:all) do
         | 
| 50 | 
            -
                      @permissions = Permissions.new.permit([:another, :array], [:attr, :array], :attr2, :attr3, [:a, :wildcard, :*] | 
| 50 | 
            +
                      @permissions = Permissions.new.permit([:another, :array], [:attr, :array], :attr2, :attr3, [:a, :wildcard, :*])
         | 
| 51 51 | 
             
                    end
         | 
| 52 52 |  | 
| 53 53 | 
             
                    it 'permits single wildcard' do
         | 
| 54 54 | 
             
                      expect(@permissions.permitted?([:a, :wildcard, :irrelevant])).to be true
         | 
| 55 55 | 
             
                    end
         | 
| 56 56 |  | 
| 57 | 
            -
                    it 'permits full wildcard' do
         | 
| 58 | 
            -
                      expect(@permissions.permitted?([:wild, :wildcard, :irrelevant])).to be true
         | 
| 59 | 
            -
                      expect(@permissions.permitted?([:wild, :irrelevant])).to be true
         | 
| 60 | 
            -
                    end
         | 
| 61 | 
            -
             | 
| 62 57 | 
             
                    it 'does not permit un-prefixed path' do
         | 
| 63 58 | 
             
                      permissions = Permissions.new(@permissions, :attr)
         | 
| 64 59 | 
             
                      expect(permissions.permitted?(:attr2)).to be false
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: strong_attributes
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Ronald Chan
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2013- | 
| 11 | 
            +
            date: 2013-11-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         |