Module: Omega::Server::DSL

Included in:
Cosmos::RJR, Manufactured::RJR, Missions::RJR, Motel::RJR, Stats::RJR, Users::RJR
Defined in:
lib/omega/server/dsl.rb,
lib/omega/server/dsl/node.rb,
lib/omega/server/dsl/args.rb,
lib/omega/server/dsl/events.rb,
lib/omega/server/dsl/session.rb,
lib/omega/server/dsl/entities.rb,
lib/omega/server/dsl/subsystem.rb,
lib/omega/server/dsl/attributes.rb

Overview

Omega Server DSL defining many helper methods for server subsystems.

DSL gets included in scope of all Omega RJR handlers, see dsl subsections for specific helpers

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#nodeObject

Get/set node used in operations


10
11
12
# File 'lib/omega/server/dsl/node.rb', line 10

def node
  @node
end

Instance Method Details

#check_attribute(args = {}) ⇒ Object

Check if the user has the specified attribute


10
11
12
13
14
# File 'lib/omega/server/dsl/attributes.rb', line 10

def check_attribute(args = {})
  query = 'users::has_attribute?', args[:user_id], args[:attribute_id]
  query << args[:level] if args.has_key?(:level)
  args[:node].invoke(*query)
end

#check_privilege(args = {}) ⇒ Object

Check privileges using the specified registry


30
31
32
33
34
# File 'lib/omega/server/dsl/session.rb', line 30

def check_privilege(args = {})
  registry = args[:registry] || args[:user_registry]
  rargs = args.merge(:session => @rjr_headers['session_id'])
  registry.check_privilege rargs
end

#cosmos_entity?(entity) ⇒ Boolean

Return bool indicating if entity is defined under Cosmos::Entities

Returns:

  • (Boolean)

35
36
37
# File 'lib/omega/server/dsl/subsystem.rb', line 35

def cosmos_entity?(entity)
  subsystem_entity?(entity, Cosmos::Entities)
end

#current_session(args = {}) ⇒ Object

Return the current logging session using the specified registry


43
44
45
46
# File 'lib/omega/server/dsl/session.rb', line 43

def current_session(args = {})
  registry = args[:registry] || args[:user_registry]
  registry.current_session :id => @rjr_headers['session_id']
end

#current_user(args = {}) ⇒ Object

Return current logged in user using the specified registry


37
38
39
40
# File 'lib/omega/server/dsl/session.rb', line 37

def current_user(args = {})
  registry = args[:registry] || args[:user_registry]
  registry.current_user :session => @rjr_headers['session_id']
end

#delete_event_handler_for(args = {}) ⇒ Object

Helper to delete event handler in registry for event/endpoint


10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/omega/server/dsl/events.rb', line 10

def delete_event_handler_for(args={})
  event_id    = args[:event_id]
  event_type  = args[:event_type]
  endpoint_id = args[:endpoint_id]
  registry    = args[:registry]

  registry.delete { |entity|
    entity.is_a?(Omega::Server::EventHandler) &&
    (event_id.nil?   || entity.event_id   == event_id) &&
    (event_type.nil? || entity.event_type == event_type) &&
    entity.endpoint_id == endpoint_id
  }
end

#filter_properties(data, filter = {}) ⇒ Object

Filter properties able / not able to be set by the end user


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/omega/server/dsl/args.rb', line 10

def filter_properties(data, filter = {})
  is_hash = data.is_a?(Hash)
  ndata   = is_hash ? {} : data.class.new
  if filter[:allow]
    filter[:allow] = [filter[:allow]] unless filter[:allow].is_a?(Array)
    # copy allowed attributes over
    filter[:allow].each { |a|
      if is_hash
        # TODO ensure data key strings include a before interning
        ndata[a.intern] = data[a.intern] || data[a.to_s]
      else
        # TODO ensure a.responds to a before interning
        ndata.send("#{a}=".intern, data.send(a.intern))
      end
    }

  else
    # TODO copy all attributes over

  end

  # if filter[:reject] TODO

  return ndata
end

#filters_from_args(args, allowed_filters) ⇒ Object

Return a list of filters constructed from the specified args

Examples:

generating filters from args

def get_data(*args)
  filters =
    filters_from_args args,
      :with_id   => proc { |e, id| e.id == id },
      :between   => proc { |e, lval, gval|
        e.value < gval && e.value > lval
      }

   return my_entities.all? { |e| filters.all? { |f| f.call(e) } }
 end

 get_data(:with_id, 'foo')
 get_data(:with_id, 'bar',
          :between, 0, 5)
 get_data(:with_property, "foobar")
 #=> raises error since "with_property" not defined

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/omega/server/dsl/args.rb', line 55

def filters_from_args(args, allowed_filters)
  filters = []

  # create copy of args list so as to modify
  nargs   = Array.new(args)

  # shift first argument of from list (the filter id)
  while arg = nargs.shift

    # find the filter with the same key as the filter id
    filter = allowed_filters.find { |k,v| k.to_s == arg.to_s }

    # raise error if it could not be found
    raise ValidationError, "invalid filter #{arg}" if filter.nil?
    filter = filter.last

    # shift number of arguments off list corresponding to the
    # arity of the filter method (minus one, assume first param
    # is for the entity to match with the filter)
    params  = []
    nparams = filter.arity - 1 #
    0.upto(nparams - 1) {
      params << nargs.shift
    } if nparams > 0

    # addd a procedure calling the filter with the
    # specified entity and parameter list to the filter list
    # XXX need to define/call an inline function to bind filter/params variables
    filters << proc { |f,p| proc { |e| f.call e, *p } }.call(filter, params)
  end

  filters
end

#from_valid_source?Boolean

Return bool indiciating if source node is valid / can be used by Omega

Returns:

  • (Boolean)

34
35
36
37
# File 'lib/omega/server/dsl/node.rb', line 34

def from_valid_source?
   @rjr_headers['source_node'].is_a?(String) &&
  !@rjr_headers['source_node'].empty?
end

#handle_node_closed(node, &cb) ⇒ Object

Helper to handle node closed event


93
94
95
96
97
98
99
# File 'lib/omega/server/dsl/events.rb', line 93

def handle_node_closed(node, &cb)
  # delete callback on connection events
# FIXME skip if closed event is already registered for this node
  node.on(:closed){ |node|
    cb.call(node)
  }
end

#in_subsystemObject

Generate a selector which matches entities not descending from the Omega::Server namespace


37
38
39
40
41
42
43
# File 'lib/omega/server/dsl/entities.rb', line 37

def in_subsystem
  proc { |e|
    !e.class.ancestors.any? { |cl|
      cl.to_s =~ /Omega::Server::.*/
    }
  }
end

#is_cmd?(entity) ⇒ Boolean

Return boolean indicating if specified entity is a command

Returns:

  • (Boolean)

46
47
48
# File 'lib/omega/server/dsl/entities.rb', line 46

def is_cmd?(entity)
  entity.kind_of?(Omega::Server::Command)
end

#is_node?(type) ⇒ Boolean

Return bool indicating if node is of given type

Returns:

  • (Boolean)

13
14
15
# File 'lib/omega/server/dsl/node.rb', line 13

def is_node?(type)
  !@rjr_node.nil? && @rjr_node.node_type == type::RJR_NODE_TYPE
end

#login(node, username, password) ⇒ Object

Log a user into the specified node using the given username / password

Parameters:

  • node (RJR::Node)

    instance of rjr node or subclass to use to login the user

  • username (String)

    string id of the user to login

  • password (String)

    password of the user to login


15
16
17
18
19
20
# File 'lib/omega/server/dsl/session.rb', line 15

def (node, username, password)
  user    = Users::User.new(:id => username, :password => password)
  session = node.invoke('users::login', user)
  node.message_headers['session_id'] = session.id
  session
end

#matching(&bl) ⇒ Object

Generate a selector from block which is called to determine selection


21
22
23
# File 'lib/omega/server/dsl/entities.rb', line 21

def matching(&bl)
  proc { |e| bl.call(e) }
end

#persistent_transport?Boolean

Return bool indicating if request has come in over a persistent transport

Returns:

  • (Boolean)

23
24
25
# File 'lib/omega/server/dsl/node.rb', line 23

def persistent_transport?
  @rjr_node.persistent?
end

#remove_callbacks_for(registry_entities, criteria = {}) ⇒ Object

Remove callbacks matching the specified criteria. All criteria are optional and may include

- class : class of entities to look for
- id : id of entity to remove callbacks for
- type : event type to match
- endpoint : rjr endpoint to match

XXX Supports both cases where callbacks is a hash or array for different subsystems, these probably should be consolidated at some point


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/omega/server/dsl/events.rb', line 34

def remove_callbacks_for(registry_entities, criteria={})
  # allow user to specify registry or entities list
  if registry_entities.kind_of?(Omega::Server::Registry)
    registry_entities.safe_exec { |entities|
      remove_callbacks_for(entities, criteria)
    }

    return
  else
    entities = registry_entities
    entities = [entities] unless entities.is_a?(Array)

  end

  # retrieve entities
  matched = entities.select { |e|
    !criteria.has_key?(:class) || e.is_a?(criteria[:class])
  }

  # if specified only operate on single entity
  matched.reject! { |m|
    m.id != criteria[:id]
  } if criteria.has_key?(:id)


  matched.each { |m|
    to_remove = []
    (m.callbacks.is_a?(Hash) ? m.callbacks.values.flatten :
                               m.callbacks).each     { |cb|

      # skip if cb event type is specified and does not match
        # skip if cb endpoint id is specified and does not match
      if (!criteria.has_key?(:endpoint)           ||
           criteria[:endpoint] == cb.endpoint_id) &&
         (!criteria.has_key?(:type)               ||
           criteria[:type] == cb.event_type)
        to_remove << cb
      end
    }

    # remove flagged callbacks, compress array
    to_remove.each { |cb|
      m.callbacks.is_a?(Hash) ? m.callbacks[cb.event_type].delete(cb) :
                                m.callbacks.delete(cb)
    }

    # compress callback list
    if m.callbacks.is_a?(Hash)
      m.callbacks.keys.each { |type|
        m.callbacks[type].compact!
        m.callbacks.delete(type) if m.callbacks[type].empty?
      }
    else
      m.callbacks.compact!
    end
  }
end

#require_attribute(args = {}) ⇒ Object

Require the user to have the specified attribute, else raise PermissionErr


17
18
19
20
# File 'lib/omega/server/dsl/attributes.rb', line 17

def require_attribute(args = {})
  raise Omega::PermissionError,
    "require_attribute(#{args})" unless check_attribute(args)
end

#require_persistent_transport!(err = nil) ⇒ Object

Raise error is transport is not persistent

Raises:


28
29
30
31
# File 'lib/omega/server/dsl/node.rb', line 28

def require_persistent_transport!(err=nil)
  err = "request must come in on persistent transport" if err.nil?
  raise OperationError, err unless persistent_transport?
end

#require_privilege(args = {}) ⇒ Object

Require privileges using the specified registry


23
24
25
26
27
# File 'lib/omega/server/dsl/session.rb', line 23

def require_privilege(args = {})
  registry = args[:registry] || args[:user_registry]
  rargs = args.merge(:session => @rjr_headers['session_id'])
  registry.require_privilege rargs
end

#require_state(entity, msg = nil, &validation) ⇒ Object

Require entity to be in the state specified by the given callback. Raise ValidationError otherwise


13
14
15
16
17
18
# File 'lib/omega/server/dsl/entities.rb', line 13

def require_state(entity, msg=nil, &validation)
  unless validation.call entity
    msg ||= "#{entity} did not pass validation"
    raise ValidationError, msg
  end
end

#require_valid_source!(err = nil) ⇒ Object

Raise error if source node is not valid

Raises:


40
41
42
43
# File 'lib/omega/server/dsl/node.rb', line 40

def require_valid_source!(err=nil)
  err = "source node is required" if err.nil?
  raise PermissionError, err unless from_valid_source?
end

#subsystemObject

Return subsystem which request is running in.

Extracts from rjr environment, assumes all Omega RJR requests are served in the <subsystem>::RJR environment.


14
15
16
# File 'lib/omega/server/dsl/subsystem.rb', line 14

def subsystem
  rjr_env.parent
end

#subsystem_entity?(entity, subsys = nil) ⇒ Boolean

Return bool indicating if entity is defined is the specified subsystem

Returns:

  • (Boolean)

26
27
28
29
30
31
32
# File 'lib/omega/server/dsl/subsystem.rb', line 26

def subsystem_entity?(entity, subsys=nil)
  subsys = subsystem if subsys.nil?
  entity_class = entity.class
  entity_class = entity_class.parent until entity_class.parent == subsys ||
                                           entity_class.parent == Object
  (entity_class.parent == subsys)
end

#subsystem_event?(event_type) ⇒ Boolean

Return bool indicating if event type corresponds to a subsystem event

Returns:

  • (Boolean)

19
20
21
22
23
# File 'lib/omega/server/dsl/subsystem.rb', line 19

def subsystem_event?(event_type)
  subsystem::Events.module_classes.any? { |event_class|
    event_class::TYPE.to_s == event_type.to_s
  }
end

#validate_session_source!(args = {}) ⇒ Object

Raise an error if the endpoint which the session was established on is not the same as the specified source node

Raises:


50
51
52
53
54
55
56
# File 'lib/omega/server/dsl/session.rb', line 50

def validate_session_source!(args = {})
  # TODO if this is false we should invalidate session,
  # log the err, and send an email to the admin / etc
  matched = current_session(args).endpoint_id == @rjr_headers['source_node']
  err = args[:msg] || "source/session mismatch!"
  raise PermissionError, err unless matched
end

#with(attr, val) ⇒ Object

Generate a selector which compares entity w/ specified attribute


26
27
28
# File 'lib/omega/server/dsl/entities.rb', line 26

def with(attr, val)
  proc { |e| e.respond_to?(attr.intern) && e.send(attr.intern) == val }
end

#with_id(eid) ⇒ Object

Generate a selector which matches entity w/ specified id


31
32
33
# File 'lib/omega/server/dsl/entities.rb', line 31

def with_id(eid)
  with(:id, eid)
end