Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
icss-activesupport-4
Advanced tools
An ICSS file is a complete, expressive description of a collection of related data and all associated assets. It is based on the Avro Protocol specification, with some necessary extensions
Hooray:
class Thing
include Icss::ReceiverModel
field :name, String
field :description, String
end
class GeoCoordinates
include Icss::ReceiverModel
field :longitude, Float, :validates => { :numericality => { :>= => -180, :<= => 180 } }
field :latitude, Float, :validates => { :numericality => { :>= => -90, :<= => 90 } }
def coordinates
[ longitude, latitude ]
end
end
class Place < Thing
field :geo, GeoCoordinates
end
class MenuItem < Thing
field :price, Float, :required => true
end
class TacoTrailer < Place
field :menu, Array, :items => MenuItem
field :founding_date, Time
end
torchys = Restaurant.receive({
:name => "Torchy's Taco's",
:menu => [
{ :name => "Dirty Sanchez", :price => "6.95" },
{ :name => "Fried Avocado", :price => "7.35" }
],
:founding_date => '2006-08-01T00:00:00Z',
:geo => { :longitude => 30.295, :latitude => -97.745 },
})
# #<TacoTrailer:0x00000101d539f8 @name="Torchy's Taco's",
# @geo=#<GeoCoordinates:0x00000101d53318 @latitude=-97.745, @longitude=30.295>,
# @menu=[ #<MenuItem:0x00000101d51180 @name="Dirty Sanchez", @price=6.95>,
# #<MenuItem:0x00000101d4d468 @name="Fried Avocado", @price=7.35> ]
# @founding_date=2006-08-01 00:00:00 UTC >
torchys.geo.coordinates
# [ 30.295, -97.745 ]
torchys.to_hash
# { :name => "Torchy's Taco's",
# :geo => { :longitude => 30.295, :latitude => -97.745 },
# :menu => [
# { :name => "Dirty Sanchez", :price => 3.50 },
# { :name => "Fried Avocado", :price => 2.95 } ],
# :founding_date => '2006-08-01T00:00:00Z',
# }
Declaring a field constructs the following. Taking
field :foo, Array, :items => :int
#foo
and foo=
getter/setters. These are completely regular accessors: no type checking/conversion/magic happens when the object is in regular use.receive_foo
method that provides lightweight type coercionRecordField
object describing the field, available through the .fields
class method. You can send this schema over the wire (in JSON or whatever) and use it to recapitulate the type elsewhere.object[:foo]
, or set it with object[:foo] = 7
.Optionally, you can decorate with
receive!
d that wasn't predicted by the schema.Magic only happens in the neighborhood of receive
methods.
receive_foo
is invoked.You can make a new ojbect using Smurf.receive({...})
, which is exactly equivalent to calling each of obj = Smurf.new ; obj.receive!({...}) ; obj
in turn.
.keys
returns a list of the fields with set values, in the same order as the class .field_names
Add ActiveModel validations with the :validates
option to .field
, or directly using .validates
:
class Icss::Handy
include Icss::ReceiverModel
field :rangey, Integer, :validates => { :inclusion => { :in => 0..9 }}
field :patternish, String
field :mandatory, Integer, :required => true
validates :patternish, :format => { :with => /eat$/ }
end
good_smurf = Icss::Handy.receive(:rangey => 5, :patternish => 'smurfberry crunch is fun to eat', :mandatory => 1)
bad_smurf = Icss::Handy.receive(:rangey => 3, :patternish => 'smurfnuggets!')
good_smurf.valid? # true
bad_smurf.valid? # false
bad_smurf.errors # { :mandatory => ["can't be blank"], :patternish => ["is invalid"] }
As shown, you can also say :required => true
as a shorthand for :validates => { :presence => true }
. A summary of the other :validates
directives:
:presence => true
:uniqueness => true
:numericality => true # also :==, :>, :>=, :<, :<=, :odd?, :even?, :equal_to, :less_than, etc
:length => { :< => 7 } # also :==, :>=, :<=, :is, :minimum, :maximum
:format => { :with => /.*/ }
:inclusion => { :in => [1,2,3] }
:exclusion => { :in => [1,2,3] }
rcvr_remaining
creates a Hash field to catch all attributes send to receive!
that don't match any receiver fields. This is surprisingly useful.
Note that you can feed rcvr_remaining
a :values
option if you want type coercion on the extra params.
rcvr_alias
will redirect an attribute to a different receiver:
class Wheel
include Icss::ReceiverModel
field :name, String
field :center_height, Float
rcvr_alias :centre_height, :center_height
end
foo = Wheel.receive(:name => 'tyre', :centre_height => 18.2)
foo.center_height # 18.2
foo.respond_to?(:centre_height) # false
Notes:
receive_(fake)
that calls the receive_(target)
method.after_receive(:hook_name){ ... }
creates a named hook, executed at the end of receive!
(and similar actions). Some examples:
after_receive(:warnings) do |hsh|
warn "Validation failed for field #{self}: #{errors.inspect}" if respond_to?(:errors) && (not valid?)
end
after_receive(:generate_id) do |hsh|
if !attr_set?(:md5id) then self.md5id = Digest::MD5.hex_digest(name) ; end
end
Notes:
after_receive
blocks are idempotent -- that is, that re-running the block has no effect. Lots of things are allowed to trigger run_after_receivers
.You can use the :default
option to field
(or call .set_field_default
directly) to specify a default value when the field is empty after a receive!
.
class Icss::Smurf
field :tool, Symbol, :default => :smurfwrench
field :weapon, Symbol, :default => :smurfthrower
end
# default set for missing attributes
handy_smurf = Icss::Smurf.receive( :tool => :pipesmurf )
handy_smurf.weapon # :smurfthrower
# if an attribute is set-but-nil no default is applied
handy_smurf = Icss::Smurf.receive( :tool => :smurfwrench, :weapon => nil )
handy_smurf.weapon # nil
# you can also use a block; it is `instance_eval`ed for the value to set.
Icss::Smurf.field(:food, Symbol, :default =>
lambda{ (weapon.to_s =~ /^smurf/) ? :smurfed_cheese : :grilled_smurf }
brainy_smurf = Icss::Smurf.receive( :weapon => :smurfapult )
hefty_smurf = Icss::Smurf.receive( :weapon => :gatling_smurf )
brainy_smurf.food # :smurfed_cheese
hefty_smurf.food # :grilled_smurf
Note:
nil
, the default is not applied.instance_eval
ing the block.run_after_receivers
is triggered. (so, the receive
operation is complete).avro kind ruby json example schema example
--------- --------- ------------ ------- --------- --------------
null base NilClass null nil 'null'
boolean base Boolean boolean true 'boolean'
int base Integer integer 1 'int'
long base Long integer 1 'long'
float base Float number 1.1 'float'
double base Double number 1.1 'double'
bytes base Binary string "\u00FF" 'bytes'
string base String string "foo" 'string'
time base Time string "2011-01-02T03:04:05Z" 'time'
symbol base Symbol string :belongs_to 'symbol'
array structured (ArrayOfXXX) array [1,2] { 'type': 'array', 'items': 'int' }
map structured (HashOfXXX) object { "a": 1 } { 'type': 'map', 'values': 'int' }
enum named (EnumType) string "heads" { 'type': 'enum', 'name': 'result', 'symbols': ['heads','tails'] }
fixed named (FixedType) string "\xBD\xF3)Q" { 'type': 'fixed', 'name': 'crc32', 'length': 4 }
record named (RecordType) object {"a": 1} { 'type': 'record', 'name': 'bob', 'fields':[...] }
error named (ErrorType) object {"err":halp! fire!"} { 'type': 'record', 'name': 'db_on_fire, 'fields':[...] }
union union <UnionType> object [ 'long', { 'type': 'array', 'items': 'int' } ]
st.regexp simple St::Regexp string "^hel*o newman" 'regexp'
st.url simple St::Url string "http://..." 'url'
mu.epoch_time simple Mu::EpochTime string 1312507492 'epoch_time'
A :base
type in an Icss file
Class .receive
method is just new
(where appropriate) with the appropriate conversion. Receiving nil
returns nil
without error.
Note that some of the base types are not present in the Avro spec.
Assets may include
See icss_specification.textile for more.
Huge thanks to Doug Cutting and the rest of the Avro maintainers.
Copyright (c) 2011 Philip (flip) Kromer for Infochimps. See LICENSE.txt for further details.
FAQs
Unknown package
We found that icss-activesupport-4 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.