class Notification(orm.BaseExpando): _kind = 61 name = orm.SuperStringProperty('1', required=True) action = orm.SuperKeyProperty('2', kind='56', required=True) condition = orm.SuperStringProperty('3', required=True, indexed=False) active = orm.SuperBooleanProperty('4', required=True, default=True) templates = orm.SuperPickleProperty('5', required=True, indexed=False, compressed=False) _default_indexed = False _virtual_fields = {'_records': orm.SuperRecordProperty('61')} _global_role = GlobalRole(permissions=[ orm.ActionPermission( '61', [ orm.Action.build_key('61', 'prepare'), orm.Action.build_key('61', 'create'), orm.Action.build_key('61', 'read'), orm.Action.build_key('61', 'update'), orm.Action.build_key('61', 'delete'), orm.Action.build_key('61', 'search') ], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('61', [ orm.Action.build_key('61', 'initiate'), orm.Action.build_key('61', 'send_mail'), orm.Action.build_key('61', 'send_http') ], False, 'True'), orm.ActionPermission( '61', [ orm.Action.build_key('61', 'initiate'), orm.Action.build_key('61', 'send_mail'), orm.Action.build_key('61', 'send_http') ], True, 'entity._original.namespace_entity._original.state == "active" and user._is_taskqueue' ), orm.FieldPermission( '61', ['name', 'action', 'condition', 'active', 'templates', '_records'], False, False, 'entity._original.namespace_entity._original.state != "active"') ]) _actions = [ orm.Action(key=orm.Action.build_key('61', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_notification' }}) ]) ]), orm.Action( key=orm.Action.build_key('61', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'name': orm.SuperStringProperty(required=True), 'action': orm.SuperVirtualKeyProperty(required=True, kind='56'), 'condition': orm.SuperTextProperty(required=True), 'active': orm.SuperBooleanProperty(), 'templates': orm.SuperMultiLocalStructuredProperty(('58', '63'), repeated=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_notification.name': 'input.name', '_notification.action': 'input.action', '_notification.condition': 'input.condition', '_notification.active': 'input.active', '_notification.templates': 'input.templates' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_notification' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('61', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='61', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_notification' }}) ]) ]), orm.Action( key=orm.Action.build_key('61', 'update'), arguments={ 'key': orm.SuperKeyProperty(required=True, kind='61'), 'name': orm.SuperStringProperty(required=True), 'action': orm.SuperVirtualKeyProperty(required=True, kind='56'), 'condition': orm.SuperTextProperty(required=True), 'active': orm.SuperBooleanProperty(), 'templates': orm.SuperMultiLocalStructuredProperty(('58', '63'), repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_notification.name': 'input.name', '_notification.action': 'input.action', '_notification.condition': 'input.condition', '_notification.active': 'input.active', '_notification.templates': 'input.templates' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_notification' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('61', 'delete'), arguments={'key': orm.SuperKeyProperty(required=True, kind='61')}, _plugin_groups=[ orm.PluginGroup( plugins=[Context( ), Read(), RulePrepare(), RuleExec()]), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': { 'output.entity': '_notification' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('61', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={ 'filters': [], 'orders': [{ 'field': 'name', 'operator': 'asc' }] }, cfg={ 'search_arguments': { 'kind': '61', 'options': { 'limit': settings.SEARCH_PAGE } }, 'filters': { 'name': orm.SuperStringProperty(), 'action': orm.SuperVirtualKeyProperty(kind='56'), 'active': orm.SuperBooleanProperty() }, 'indexes': [{ 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('action', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('action', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('name', ['==', '!=']), ('action', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]), orm.Action( key=orm.Action.build_key('61', 'initiate'), arguments={ 'caller_entity': orm.SuperKeyProperty(required=True), 'caller_user': orm.SuperKeyProperty(required=True, kind='0'), 'caller_action': orm.SuperVirtualKeyProperty(required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Set(cfg={ 'd': { '_caller_entity': 'input.caller_entity.entity' } }), Read(cfg={'namespace': '_caller_entity.key_namespace'}), RulePrepare(), RuleExec(), NotificationInitiate(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('61', 'send_mail'), arguments={ 'recipient': orm.SuperStringProperty(repeated=True), 'subject': orm.SuperTextProperty(required=True), 'body': orm.SuperTextProperty(required=True), 'caller_entity': orm.SuperKeyProperty(required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Set(cfg={ 'd': { '_caller_entity': 'input.caller_entity.entity' } }), Read(cfg={'namespace': '_caller_entity.key_namespace'}), RulePrepare(), RuleExec(), NotificationMailSend(cfg={'sender': settings.NOTIFY_EMAIL}) ]) ]), orm.Action( key=orm.Action.build_key('61', 'send_http'), arguments={ 'recipient': orm.SuperStringProperty(required=True), 'subject': orm.SuperTextProperty(required=True), 'body': orm.SuperTextProperty(required=True), 'caller_entity': orm.SuperKeyProperty(required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Set(cfg={ 'd': { '_caller_entity': 'input.caller_entity.entity' } }), Read(cfg={'namespace': '_caller_entity.key_namespace'}), RulePrepare(), RuleExec(), NotificationHttpSend() ]) ]) ]
class Journal(orm.BaseExpando): _kind = 49 created = orm.SuperDateTimeProperty('1', required=True, auto_now_add=True) updated = orm.SuperDateTimeProperty('2', required=True, auto_now=True) name = orm.SuperStringProperty('3', required=True) state = orm.SuperStringProperty('4', required=True, default='draft', choices=['draft', 'active', 'decommissioned']) entry_fields = orm.SuperPickleProperty('5', required=True, indexed=False, compressed=False) line_fields = orm.SuperPickleProperty('6', required=True, indexed=False, compressed=False) _default_indexed = False _virtual_fields = { '_records': orm.SuperRecordProperty('49'), '_code': orm.SuperComputedProperty(lambda self: self.key_id_str), '_transaction_actions': orm.SuperRemoteStructuredProperty(Action, repeated=True), '_transaction_plugin_groups': orm.SuperRemoteStructuredProperty(PluginGroup, repeated=True) } _global_role = GlobalRole( permissions=[ orm.ActionPermission('49', [orm.Action.build_key('49', 'prepare'), orm.Action.build_key('49', 'create'), orm.Action.build_key('49', 'read'), orm.Action.build_key('49', 'update'), orm.Action.build_key('49', 'delete'), orm.Action.build_key('49', 'search'), orm.Action.build_key('49', 'activate'), orm.Action.build_key('49', 'decommission')], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('49', [orm.Action.build_key('49', 'delete')], False, 'entity._original.state != "draft"'), orm.ActionPermission('49', [orm.Action.build_key('49', 'activate')], False, 'entity._original.state == "active"'), orm.ActionPermission('49', [orm.Action.build_key('49', 'decommission')], False, 'entity._is_system or entity._original.state != "active"'), orm.FieldPermission('49', ['created', 'updated', 'state'], False, None, 'True'), orm.FieldPermission('49', ['created', 'updated', 'name', 'state', 'entry_fields', 'line_fields', '_records', '_code', '_transaction_actions', '_transaction_plugin_groups'], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('49', ['created', 'updated', 'name', 'state', 'entry_fields', 'line_fields', '_records', '_code'], False, None, 'entity._original.state != "draft"'), orm.FieldPermission('49', ['_transaction_actions', '_transaction_plugin_groups.name', '_transaction_plugin_groups.subscriptions', '_transaction_plugin_groups.active', '_transaction_plugin_groups.sequence', '_transaction_plugin_groups.transactional'], False, None, 'entity._is_system'), orm.FieldPermission('49', ['_transaction_plugin_groups.plugins'], False, None, 'entity._is_system and entity._original._transaction_plugin_groups.name != "User Plugins"'), # @todo Missing index between _transaction_plugin_groups and name! orm.FieldPermission('49', ['state'], True, None, '(action.key_id_str == "activate" and entity.state == "active") or (action.key_id_str == "decommission" and entity.state == "decommissioned")') ] ) _actions = [ orm.Action( key=orm.Action.build_key('49', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': {'output.entity': '_journal'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), '_code': orm.SuperStringProperty(required=True, max_size=64), # Regarding max_size, take a look at the transaction.JournalUpdateRead() plugin! 'name': orm.SuperStringProperty(required=True), 'entry_fields': orm.SuperPropertyStorageProperty(required=True, cfg=JOURNAL_FIELDS), 'line_fields': orm.SuperPropertyStorageProperty(required=True, cfg=JOURNAL_FIELDS) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_journal.state': 'draft'}, 'd': {'_journal.name': 'input.name', '_journal.entry_fields': 'input.entry_fields', '_journal.line_fields': 'input.line_fields'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_journal'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='49', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': {'output.entity': '_journal'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='49', required=True), 'name': orm.SuperStringProperty(required=True), 'entry_fields': orm.SuperPropertyStorageProperty(required=True, cfg=JOURNAL_FIELDS), 'line_fields': orm.SuperPropertyStorageProperty(required=True, cfg=JOURNAL_FIELDS), '_transaction_actions': orm.SuperLocalStructuredProperty(Action, repeated=True), '_transaction_plugin_groups': orm.SuperLocalStructuredProperty(PluginGroup, repeated=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'d': {'_journal.name': 'input.name', '_journal.entry_fields': 'input.entry_fields', '_journal.line_fields': 'input.line_fields', '_journal._transaction_actions': 'input._transaction_actions', '_journal._transaction_plugin_groups': 'input._transaction_plugin_groups'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_journal'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'delete'), arguments={ 'key': orm.SuperKeyProperty(kind='49', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': {'output.entity': '_journal'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={'filters': [], 'orders': [{'field': 'name', 'operator': 'asc'}]}, cfg={ 'search_arguments': {'kind': '49', 'options': {'limit': settings.SEARCH_PAGE}}, 'filters': {'name': orm.SuperStringProperty(), 'state': orm.SuperStringProperty(choices=[])}, 'indexes': [{'orders': [('name', ['asc', 'desc'])]}, {'orders': [('state', ['asc', 'desc'])]}, {'filters': [('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])]}, {'filters': [('state', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])]}, {'filters': [('state', ['==', '!=']), ('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'activate'), arguments={ 'key': orm.SuperKeyProperty(kind='49', required=True), 'message': orm.SuperTextProperty(required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_journal.state': 'active'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message'}}), CallbackNotify(), CallbackExec() ] ), orm.PluginGroup( plugins=[ RulePrepare(), Set(cfg={'d': {'output.entity': '_journal'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('49', 'decommission'), arguments={ 'key': orm.SuperKeyProperty(kind='49', required=True), 'message': orm.SuperTextProperty(required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_journal.state': 'decommissioned'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message'}}), CallbackNotify(), CallbackExec() ] ), orm.PluginGroup( plugins=[ RulePrepare(), Set(cfg={'d': {'output.entity': '_journal'}}) ] ) ] ) ] @classmethod def prepare_key(cls, input, **kwargs): code = input.get('_code') return cls.build_key(code, namespace=kwargs.get('namespace')) # @todo Possible prefix? @property def _is_system(self): return self.key_id_str.startswith('system_')
class Entry(orm.BaseExpando): '''Notes: In order to make proper instances of entries you must always either provide journal or _model_schema argument in constructor. Fields can only be properly loaded if are: - loaded from datastore - instanced with proper keyword argument Entry (journal or _model_schema) and Line (parent) ''' _kind = 50 _journal_fields_loaded = None # Used to flag if the journal fields were loaded. created = orm.SuperDateTimeProperty('1', required=True, auto_now_add=True) updated = orm.SuperDateTimeProperty('2', required=True, auto_now=True) journal = orm.SuperKeyProperty('3', kind=Journal, required=True) name = orm.SuperStringProperty('4', required=True) state = orm.SuperStringProperty('5', required=True) # @todo Bad thing about this prop being defined statically is that we can not have choices and default value, thus less abstraction! date = orm.SuperDateTimeProperty('6', required=True) _virtual_fields = { '_lines': orm.SuperRemoteStructuredProperty(Line, repeated=True) } _global_roles = {'system_sales_order': GlobalRole( permissions=[ orm.FieldPermission('50', ['created', 'updated', 'state'], False, None, 'True'), orm.FieldPermission('50', ['created', 'updated', 'name', 'state', 'entry_fields', 'line_fields', '_records', '_code', '_transaction_actions', '_transaction_plugin_groups'], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('50', ['created', 'updated', 'name', 'state', 'entry_fields', 'line_fields', '_records', '_code'], False, None, 'entity._original.state != "draft"'), orm.FieldPermission('50', ['_transaction_actions', '_transaction_plugin_groups.name', '_transaction_plugin_groups.subscriptions', '_transaction_plugin_groups.active', '_transaction_plugin_groups.sequence', '_transaction_plugin_groups.transactional'], False, None, 'entity._is_system'), orm.FieldPermission('50', ['_transaction_plugin_groups.plugins'], False, None, 'entity._is_system and entity._original._transaction_plugin_groups.name != "User Plugins"'), # @todo Missing index between _transaction_plugin_groups and name! orm.FieldPermission('50', ['state'], True, None, '(action.key_id_str == "activate" and entity.state == "active") or (action.key_id_str == "decommission" and entity.state == "decommissioned")') ] )} @property def _global_role(self): return self._global_roles.get(self.journal._id_str) def __init__(self, *args, **kwargs): '''Caution! Making instances of Entry() inside a transaction may cause performing non-entity group queries (see journal_key.get() in add journal fields). As for get() itself it will use in-memory cache when it can. ''' journal = kwargs.get('journal') _model_schema = kwargs.pop('_model_schema', None) namespace = kwargs.get('namespace') if journal is None and (_model_schema is not None and namespace is not None): journal = Journal.build_key(_model_schema, namespace=namespace) kwargs['journal'] = journal if journal: self.add_journal_fields(journal) super(Entry, self).__init__(*args, **kwargs) def add_journal_fields(self, journal_key=None): if not self._journal_fields_loaded: # prevent from loading too many times if journal_key is None: journal_key = self.journal journal = journal_key.get() if journal is None: raise Exception('Cannot find journal with key %r.' % journal_key) self._clone_properties() for name, prop in journal.entry_fields.iteritems(): prop._code_name = name self._properties[prop._name] = prop self.add_output(name) self._journal_fields_loaded = True def get_kind(self): # @todo Do we have security breach here, without inclusion of namespace? return '%s_%s' % (self._get_kind(), self.journal.id()) @property def _actions(self): # @todo Cache if possible for performance gains! return Action.query(Action.active == True, ancestor=self.journal).fetch() def get_actions(self): return getattr(self, '_actions', []) def get_action(self, action): if isinstance(action, orm.Key): action_key = action else: try: action_key = orm.Key(urlsafe=action) except: action_key = Action.build_key(action, parent=self.journal) return action_key.get() def get_plugin_groups(self, action): return PluginGroup.query(PluginGroup.active == True, PluginGroup.subscriptions == action.key, ancestor=self.journal).order(PluginGroup.sequence).fetch() def get_fields(self): fields = super(Entry, self.__class__).get_fields() # Calling parent get_fields. for name, prop in self._properties.iteritems(): fields[prop._code_name] = prop return fields @classmethod def _from_pb(cls, pb, set_key=True, ent=None, key=None): '''Internal helper to create an entity from an EntityProto protobuf. First 10 lines of code are copied from original from_pb in order to mimic construction of entity instance based on its function args. The rest of the code bellow is used to forcefully attempt to attach properties from journal entry_fields. This is complicated because in order to properly deserialize from datastore, the deserialization process can only begin after we have successfully retrieved entry_fields from journal. ''' if not isinstance(pb, entity_pb.EntityProto): raise TypeError('pb must be an instance of EntityProto; received %r' % pb) if ent is None: ent = cls() # A key passed in overrides a key in the pb. if key is None and pb.key().path().element_size(): key = orm.Key(reference=pb.key()) # If set_key is not set, skip a trivial incomplete key. if key is not None and (set_key or key.id() or key.parent()): ent._key = key indexed_properties = pb.property_list() unindexed_properties = pb.raw_property_list() projection = [] all_props = [indexed_properties, unindexed_properties] added_fields = False for plist in all_props: for p in plist: # First find the journal. Then load all needed props and break the loop. journal_name = cls.journal._name if journal_name is None: journal_name = cls.journal._code_name if p.name() == journal_name: prop = ent._get_property_for(p, plist is indexed_properties) prop._deserialize(ent, p) # Calling deserialize on entities prop will unpack the property and set the value to the entity. ent.add_journal_fields() # Calling add_journal_fields without argument will use self.journal as journal key. added_fields = True break if not added_fields: raise Exception('Cannot proceed with loading of entry %s. Journal fields failed to set.' % ent) return super(Entry, cls)._from_pb(pb, set_key, ent, ent.key) # Calling parent from_pb to attempt to mantain compatibility with possible NDB upgrades? @classmethod def get_meta(cls): '''This function returns dictionary of meta data (not stored or dynamically generated data) of the model. The returned dictionary can be transalted into other understandable code to clients (e.g. JSON). ''' dic = {} dic['_actions'] = getattr(cls, '_actions', []) dic.update(super(Entry, cls).get_fields()) return dic
class Widget(orm.BaseExpando): _kind = 62 _use_search_engine = True # @todo This is extra added for testing functions of google seach! name = orm.SuperStringProperty( '1', required=True, searchable=True ) # @todo This is extra added for testing functions of google seach! sequence = orm.SuperIntegerProperty( '2', required=True, searchable=True ) # @todo This is extra added for testing functions of google seach! active = orm.SuperBooleanProperty( '3', required=True, default=True, searchable=True ) # @todo This is extra added for testing functions of google seach! role = orm.SuperKeyProperty('4', kind='60', required=True) search_form = orm.SuperBooleanProperty('5', required=True, indexed=False, default=True) filters = orm.SuperLocalStructuredProperty(Filter, '6', repeated=True) _default_indexed = False _virtual_fields = {'_records': orm.SuperRecordProperty('62')} _global_role = GlobalRole(permissions=[ orm.ActionPermission( '62', [ orm.Action.build_key('62', 'prepare'), orm.Action.build_key('62', 'create'), orm.Action.build_key('62', 'read'), orm.Action.build_key('62', 'update'), orm.Action.build_key('62', 'delete'), orm.Action.build_key('62', 'search'), orm.Action.build_key('62', 'build_menu') ], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('62', [ orm.Action.build_key('62', 'create'), orm.Action.build_key('62', 'update'), orm.Action.build_key('62', 'delete') ], False, 'entity._is_system'), orm.FieldPermission( '62', [ 'name', 'sequence', 'active', 'role', 'search_form', 'filters', '_records' ], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('62', [ 'name', 'sequence', 'active', 'role', 'search_form', 'filters', '_records' ], False, None, 'entity._is_system'), orm.FieldPermission( '62', ['role'], False, None, '(action.key_id_str == "create" or action.key_id_str == "update") and (entity.role and entity.role._namespace != entity._original.key_namespace)' ) ]) _actions = [ orm.Action(key=orm.Action.build_key('62', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_widget' }}) ]) ]), orm.Action( key=orm.Action.build_key('62', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'name': orm.SuperStringProperty(required=True), 'sequence': orm.SuperIntegerProperty(required=True), 'active': orm.SuperBooleanProperty(default=True), 'role': orm.SuperKeyProperty(kind='60', required=True), 'search_form': orm.SuperBooleanProperty(default=True), 'filters': orm.SuperLocalStructuredProperty(Filter, repeated=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_widget.name': 'input.name', '_widget.sequence': 'input.sequence', '_widget.active': 'input.active', '_widget.role': 'input.role', '_widget.search_form': 'input.search_form', '_widget.filters': 'input.filters' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('62', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='62', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_widget' }}) ]) ]), orm.Action( key=orm.Action.build_key('62', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='62', required=True), 'name': orm.SuperStringProperty(required=True), 'sequence': orm.SuperIntegerProperty(required=True), 'active': orm.SuperBooleanProperty(default=True), 'role': orm.SuperKeyProperty(kind='60', required=True), 'search_form': orm.SuperBooleanProperty(default=True), 'filters': orm.SuperLocalStructuredProperty(Filter, repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_widget.name': 'input.name', '_widget.sequence': 'input.sequence', '_widget.active': 'input.active', '_widget.role': 'input.role', '_widget.search_form': 'input.search_form', '_widget.filters': 'input.filters' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('62', 'delete'), arguments={'key': orm.SuperKeyProperty(kind='62', required=True)}, _plugin_groups=[ orm.PluginGroup( plugins=[Context( ), Read(), RulePrepare(), RuleExec()]), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': { 'output.entity': '_widget' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('62', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={ 'filters': [], 'orders': [{ 'field': 'sequence', 'operator': 'asc' }] }, cfg={ 'use_search_engine': True, # @todo This is extra added for testing functions of google seach! 'search_arguments': { 'kind': '62', 'options': { 'limit': settings.SEARCH_PAGE } }, 'filters': { 'name': orm.SuperStringProperty(), 'role': orm.SuperKeyProperty(kind='60'), 'active': orm.SuperBooleanProperty() }, 'orders': { 'name': { 'default_value': { 'asc': 'a', 'desc': 'z' } }, # @todo This is extra added for testing functions of google seach! 'sequence': { 'default_value': { 'asc': 0, 'desc': 1000000 } } }, # @todo This is extra added for testing functions of google seach! 'indexes': [{ 'orders': [('name', ['asc', 'desc'])] }, { 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('name', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['=='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('role', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('name', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('role', ['==', '!='])], 'orders': [('sequence', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]), orm.Action(key=orm.Action.build_key('62', 'build_menu'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), WidgetBuildMenu(), Set( cfg={ 'd': { 'output.menu': '_widgets', 'output.domain': 'domain' } }) ]) ]) ] @property def _is_system(self): return self.key_id_str.startswith('system_')
class Category(orm.BaseExpando): _kind = 47 created = orm.SuperDateTimeProperty('1', required=True, auto_now_add=True) updated = orm.SuperDateTimeProperty('2', required=True, auto_now=True) parent_record = orm.SuperKeyProperty('3', kind='47') name = orm.SuperStringProperty('4', required=True) complete_name = orm.SuperTextProperty('5', required=True) active = orm.SuperBooleanProperty('6', required=True, default=True) _default_indexed = False ###################################################### # Primitive example of real time balance calculator! # ###################################################### @classmethod def _get_children(cls, parent_records, children): entities = [] for parent_record in parent_records: entities.extend(cls.query(cls.parent_record == parent_record).fetch(keys_only=True)) if len(entities): children.extend(entities) cls._get_children(entities, children) @classmethod def _get_balance(cls, category): debit = 0 credit = 0 lines = Line.query(Line.categories.IN(category._children_records)).fetch() for line in lines: debit += line.debit credit += line.credit return (debit, credit, (debit - credit)) @classmethod def _post_get_hook(cls, key, future): # @todo Missing super extension! entity = future.get_result() if entity is not None and entity.key: entity._children_records = [entity.key] entity._get_children([entity.key], entity._children_records) entity._debit, entity._credit, entity._balance = entity._get_balance(entity) ################### # End of example! # ################### _expando_fields = { 'description': orm.SuperTextProperty('7'), 'balances': orm.SuperLocalStructuredProperty(CategoryBalance, '8', repeated=True) } _virtual_fields = { '_records': orm.SuperRecordProperty('47'), '_code': orm.SuperComputedProperty(lambda self: self.key_id_str) #'_debit': orm.SuperComputedProperty(lambda self: self._debit), #'_credit': orm.SuperComputedProperty(lambda self: self._credit), #'_balance': orm.SuperComputedProperty(lambda self: self._balance), } _global_role = GlobalRole( permissions=[ orm.ActionPermission('47', [orm.Action.build_key('47', 'prepare'), orm.Action.build_key('47', 'create'), orm.Action.build_key('47', 'read'), orm.Action.build_key('47', 'update'), orm.Action.build_key('47', 'delete'), orm.Action.build_key('47', 'search')], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('47', [orm.Action.build_key('47', 'create'), orm.Action.build_key('47', 'update'), orm.Action.build_key('47', 'delete')], False, 'entity._is_system'), orm.ActionPermission('47', [orm.Action.build_key('47', 'delete')], False, 'entity._is_used'), orm.FieldPermission('47', ['created', 'updated'], False, None, 'True'), orm.FieldPermission('47', ['created', 'updated', 'parent_record', 'name', 'complete_name', 'active', 'description', 'balances', '_records', '_code'], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('47', ['created', 'updated', 'parent_record', 'name', 'complete_name', 'active', 'description', 'balances', '_records', '_code'], False, None, 'entity._is_system') ] ) _actions = [ orm.Action( key=orm.Action.build_key('47', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': {'output.entity': '_category'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('47', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), '_code': orm.SuperStringProperty(required=True, max_size=64), # Regarding max_size, take a look at the transaction.CategoryUpdateRead() plugin! 'parent_record': orm.SuperKeyProperty(kind='47'), 'name': orm.SuperStringProperty(required=True), 'active': orm.SuperBooleanProperty(required=True, default=True), 'description': orm.SuperTextProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), CategoryUpdateSet(), # @todo Unless we decide to implement that complete_name handling property, this will stay. RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_category'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('47', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='47', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': {'output.entity': '_category'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('47', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='47', required=True), 'parent_record': orm.SuperKeyProperty(kind='47'), 'name': orm.SuperStringProperty(required=True), 'active': orm.SuperBooleanProperty(required=True, default=True), 'description': orm.SuperTextProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), CategoryUpdateSet(), # @todo Unless we decide to implement that complete_name handling property, this will stay. RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_category'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('47', 'delete'), arguments={ 'key': orm.SuperKeyProperty(kind='47', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': {'output.entity': '_category'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('47', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={'filters': [{'field': 'active', 'value': True, 'operator': '=='}], 'orders': [{'field': 'name', 'operator': 'asc'}]}, cfg={ 'search_by_keys': True, 'search_arguments': {'kind': '47', 'options': {'limit': settings.SEARCH_PAGE}}, 'filters': {'name': orm.SuperStringProperty(), 'active': orm.SuperBooleanProperty()}, 'indexes': [{'orders': [('name', ['asc', 'desc'])]}, {'orders': [('created', ['asc', 'desc'])]}, {'orders': [('updated', ['asc', 'desc'])]}, {'orders': [('active', ['asc', 'desc'])]}, {'filters': [('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])]}, {'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])]}, {'filters': [('active', ['==']), ('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ) ] @classmethod def prepare_key(cls, input, **kwargs): code = input.get('_code') return cls.build_key(code, namespace=kwargs.get('namespace')) # @todo Possible prefix? @property def _is_system(self): return self.key_id_str.startswith('system_') @property def _is_used(self): if self.key.id() is None: return False category = self.query(self.__class__.parent_record == self.key).get() line = Line.query(Line.categories == self.key).get() return (category is not None) or (line is not None)
class DomainRole(Role): _kind = 60 _virtual_fields = {'_records': orm.SuperRecordProperty('60')} _global_role = GlobalRole(permissions=[ orm.ActionPermission( '60', [ orm.Action.build_key('60', 'prepare'), orm.Action.build_key('60', 'create'), orm.Action.build_key('60', 'read'), orm.Action.build_key('60', 'update'), orm.Action.build_key('60', 'delete'), orm.Action.build_key('60', 'search') ], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission('60', [ orm.Action.build_key('60', 'create'), orm.Action.build_key('60', 'update'), orm.Action.build_key('60', 'delete') ], False, 'entity._is_system'), orm.FieldPermission( '60', ['name', 'active', 'permissions', '_records'], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission( '60', ['name', 'active', 'permissions', '_records'], False, None, 'entity._is_system') ]) _actions = [ orm.Action(key=orm.Action.build_key('60', 'prepare'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_domainrole' }}) ]) ]), orm.Action( key=orm.Action.build_key('60', 'create'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'name': orm.SuperStringProperty(required=True), 'permissions': orm.SuperMultiLocalStructuredProperty(('80', '79'), repeated=True), 'active': orm.SuperBooleanProperty(default=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_domainrole.name': 'input.name', '_domainrole.active': 'input.active', '_domainrole.permissions': 'input.permissions' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_domainrole' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('60', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='60', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_domainrole' }}) ]) ]), orm.Action( key=orm.Action.build_key('60', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='60', required=True), 'name': orm.SuperStringProperty(required=True), 'permissions': orm.SuperMultiLocalStructuredProperty(('80', '79'), repeated=True), 'active': orm.SuperBooleanProperty(default=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_domainrole.name': 'input.name', '_domainrole.active': 'input.active', '_domainrole.permissions': 'input.permissions' } }), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_domainrole' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('60', 'delete'), arguments={'key': orm.SuperKeyProperty(kind='60', required=True)}, _plugin_groups=[ orm.PluginGroup( plugins=[Context( ), Read(), RulePrepare(), RuleExec()]), orm.PluginGroup( transactional=True, plugins=[ Delete(), Set(cfg={'d': { 'output.entity': '_domainrole' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('60', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={ 'filters': [], 'orders': [{ 'field': 'name', 'operator': 'asc' }] }, cfg={ 'search_by_keys': True, 'search_arguments': { 'kind': '60', 'options': { 'limit': settings.SEARCH_PAGE } }, 'filters': { 'name': orm.SuperStringProperty(), 'active': orm.SuperBooleanProperty() }, 'indexes': [{ 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]) ] @property def _is_system(self): return self.key_id_str.startswith('system_')
class DomainUser(orm.BaseExpando): _kind = 8 name = orm.SuperStringProperty('1', required=True) roles = orm.SuperKeyProperty( '2', kind='60', repeated=True ) # It's important to ensure that this list doesn't contain duplicate role keys, since that can pose security issue!! state = orm.SuperStringProperty('3', required=True, choices=['invited', 'accepted']) _default_indexed = False _virtual_fields = { '_primary_email': orm.SuperReferenceProperty( callback=lambda self: self._get_user_async(), format_callback=lambda self, value: value._primary_email), '_user': orm.SuperReferenceStructuredProperty( '0', callback=lambda self: self._get_user_async()), '_records': orm.SuperRecordProperty('8') } _global_role = GlobalRole(permissions=[ orm.ActionPermission( '8', [ orm.Action.build_key('8', 'prepare'), orm.Action.build_key('8', 'invite'), orm.Action.build_key('8', 'read'), orm.Action.build_key('8', 'update'), orm.Action.build_key('8', 'remove'), orm.Action.build_key('8', 'search'), orm.Action.build_key('8', 'accept'), orm.Action.build_key('8', 'clean_roles') ], False, 'entity._original.namespace_entity._original.state != "active"'), orm.ActionPermission( '8', orm.Action.build_key('8', 'remove'), False, 'entity._original.key_id_str == entity._original.namespace_entity._original.primary_contact.entity._original.key_id_str' ), orm.ActionPermission( '8', orm.Action.build_key('8', 'remove'), True, '(entity._original.namespace_entity._original.state == "active" and user.key_id_str == entity._original.key_id_str) and not (entity._original.key_id_str == entity._original.namespace_entity._original.primary_contact.entity._original.key_id_str)' ), orm.ActionPermission('8', orm.Action.build_key('8', 'accept'), False, 'user.key_id_str != entity._original.key_id_str'), orm.ActionPermission( '8', orm.Action.build_key('8', 'accept'), True, 'entity._original.namespace_entity._original.state == "active" and user.key_id_str == entity._original.key_id_str and entity._original.state == "invited"' ), orm.ActionPermission('8', orm.Action.build_key('8', 'clean_roles'), False, 'False'), orm.ActionPermission( '8', orm.Action.build_key('8', 'clean_roles'), True, 'entity._original.namespace_entity._original.state == "active" and user._is_taskqueue' ), orm.FieldPermission( '8', ['name', 'roles', 'state', '_primary_email', '_records'], False, False, 'entity._original.namespace_entity._original.state != "active"'), orm.FieldPermission('8', ['state'], False, None, 'True'), orm.FieldPermission( '8', ['roles'], False, None, 'entity._original.key_id_str == entity._original.namespace_entity._original.primary_contact.entity._original.key_id_str' ), orm.FieldPermission( '8', ['state'], True, None, '(action.key_id_str == "invite" and entity.state == "invited") or (action.key_id_str == "accept" and entity.state == "accepted")' ), orm.FieldPermission( '8', ['state'], None, True, 'entity._original.namespace_entity._original.state == "active" and user.key_id_str == entity._original.key_id_str' ) ]) _actions = [ orm.Action(key=orm.Action.build_key('8', 'prepare'), arguments={'domain': orm.SuperKeyProperty(kind='6')}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_domainuser' }}) ]) ]), orm.Action(key=orm.Action.build_key('8', 'invite'), arguments={ 'domain': orm.SuperKeyProperty(kind='6'), 'name': orm.SuperStringProperty(required=True), 'email': orm.SuperStringProperty(required=True), 'roles': orm.SuperKeyProperty(kind='60', repeated=True) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), DomainUserInviteSet(), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Write(cfg={'path': '_user'}), Set(cfg={'d': { 'output.entity': '_domainuser' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('8', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='8', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': { 'output.entity': '_domainuser' }}) ]) ]), orm.Action(key=orm.Action.build_key('8', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='8', required=True), 'name': orm.SuperStringProperty(required=True), 'roles': orm.SuperKeyProperty(kind='60', repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), DomainUserUpdateSet(), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_domainuser' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action( key=orm.Action.build_key('8', 'remove'), arguments={'key': orm.SuperKeyProperty(kind='8', required=True)}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), DomainUserRemoveSet(), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'path': '_user'}), Delete(), Set(cfg={'d': { 'output.entity': '_domainuser' }}), CallbackNotify(), CallbackExec() ]) ]), orm.Action(key=orm.Action.build_key('8', 'search'), arguments={ 'domain': orm.SuperKeyProperty(kind='6', required=True), 'search': orm.SuperSearchProperty( default={ 'filters': [], 'orders': [{ 'field': 'name', 'operator': 'asc' }] }, cfg={ 'search_by_keys': True, 'search_arguments': { 'kind': '8', 'options': { 'limit': settings.SEARCH_PAGE } }, 'filters': { 'name': orm.SuperStringProperty(), 'state': orm.SuperStringProperty( choices=['invited', 'accepted']) }, 'indexes': [{ 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('state', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('state', ['==', '!=']), ('name', ['==', '!='])], 'orders': [('name', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities'}), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]), orm.Action( key=orm.Action.build_key('8', 'accept'), arguments={'key': orm.SuperKeyProperty(kind='8', required=True)}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set(cfg={'s': { '_domainuser.state': 'accepted' }}), RulePrepare(), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[Write(), CallbackNotify(), CallbackExec()]), orm.PluginGroup(plugins=[ Set(cfg={'d': { '_domain': '_domainuser.namespace_entity' }}), RulePrepare(), RulePrepare(cfg={'path': '_domain'}), Set( cfg={ 'd': { 'output.entity': '_domainuser', 'output.domain': '_domain' } }) ]) ]), orm.Action( key=orm.Action.build_key('8', 'clean_roles'), arguments={'key': orm.SuperKeyProperty(kind='8', required=True)}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), DomainUserCleanRolesSet(), RulePrepare(), RuleExec() ]), orm.PluginGroup(transactional=True, plugins=[Write()]) ]) ] def _get_user_async(self): return orm.Key('0', long(self.key_id_str)).get_async()
class User(orm.BaseExpando): _kind = 0 _use_memcache = True created = orm.SuperDateTimeProperty('1', required=True, auto_now_add=True) updated = orm.SuperDateTimeProperty('2', required=True, auto_now=True) identities = orm.SuperStructuredProperty(Identity, '3', repeated=True) # Soft limit 100 instances. emails = orm.SuperStringProperty('4', repeated=True) # Soft limit 100 instances. state = orm.SuperStringProperty('5', required=True, choices=['active', 'suspended']) # @todo Shall we disable indexing here? sessions = orm.SuperLocalStructuredProperty(Session, '6', repeated=True) # Soft limit 100 instances. domains = orm.SuperKeyProperty('7', kind='6', repeated=True) # Soft limit 100 instances. @todo Shall we disable indexing here? _default_indexed = False _virtual_fields = { 'ip_address': orm.SuperComputedProperty(lambda self: os.environ.get('REMOTE_ADDR')), '_primary_email': orm.SuperComputedProperty(lambda self: self.primary_email()), '_records': orm.SuperRecordProperty('0') } _global_role = GlobalRole( permissions=[ orm.ActionPermission('0', orm.Action.build_key('0', 'login'), True, 'entity._is_guest or entity._original.state == "active"'), orm.ActionPermission('0', [orm.Action.build_key('0', 'read'), orm.Action.build_key('0', 'update'), orm.Action.build_key('0', 'logout'), orm.Action.build_key('0', 'read_domains')], True, 'not entity._is_guest and user.key == entity._original.key'), orm.FieldPermission('0', ['created', 'updated', 'state', 'domains'], False, True, 'not user._is_guest and user.key == entity._original.key'), orm.FieldPermission('0', ['identities', 'emails', 'sessions', '_primary_email'], True, True, 'not user._is_guest and user.key == entity._original.key'), # User is unit of administration, hence root admins need control over it! # Root admins can always: read user; search for users (exclusively); # read users history (exclusively); perform sudo operations (exclusively). orm.ActionPermission('0', [orm.Action.build_key('0', 'read'), orm.Action.build_key('0', 'search'), orm.Action.build_key('0', 'sudo')], True, 'user._root_admin'), orm.FieldPermission('0', ['created', 'updated', 'identities', 'emails', 'state', 'sessions', 'domains', 'ip_address', '_primary_email', '_records'], None, True, 'user._root_admin'), orm.FieldPermission('0', ['state'], True, None, 'action.key_id_str == "sudo" and user._root_admin') ] ) _actions = [ orm.Action( key=orm.Action.build_key('0', 'login'), arguments={ 'login_method': orm.SuperStringProperty(required=True, choices=settings.LOGIN_METHODS.keys()), 'code': orm.SuperStringProperty(), 'error': orm.SuperStringProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), UserLoginInit(cfg={'methods': settings.LOGIN_METHODS}) ] ), orm.PluginGroup( transactional=True, plugins=[ UserLoginWrite() ] ) ] ), orm.Action( key=orm.Action.build_key('0', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='0', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Set(cfg={'d': {'output.entity': '_user'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('0', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='0', required=True), 'primary_email': orm.SuperStringProperty(), 'disassociate': orm.SuperStringProperty(repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), UserUpdateSet(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_user'}}), # CallbackNotify(), # CallbackExec() notify cannot work here ] ) ] ), orm.Action( key=orm.Action.build_key('0', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={'filters': [], 'orders': [{'field': 'created', 'operator': 'desc'}]}, cfg={ 'search_arguments': {'kind': '0', 'options': {'limit': settings.SEARCH_PAGE}}, 'filters': {'emails': orm.SuperStringProperty(), 'state': orm.SuperStringProperty()}, 'indexes': [{'orders': [('emails', ['asc', 'desc'])]}, {'orders': [('created', ['asc', 'desc'])]}, {'orders': [('updated', ['asc', 'desc'])]}, {'filters': [('emails', ['==', '!='])], 'orders': [('created', ['asc', 'desc'])]}, {'filters': [('state', ['==', '!='])], 'orders': [('created', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities', 'skip_user_roles': True}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ), # @todo Treba obratiti paznju na to da suspenzija usera ujedno znaci # i izuzimanje svih negativnih i neutralnih feedbackova koje je user ostavio dok je bio aktivan. orm.Action( key=orm.Action.build_key('0', 'sudo'), arguments={ 'key': orm.SuperKeyProperty(kind='0', required=True), 'state': orm.SuperStringProperty(required=True, choices=['active', 'suspended']), 'message': orm.SuperStringProperty(required=True), 'note': orm.SuperStringProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'d': {'_user.state': 'input.state'}, 's': {'_user.sessions': []}}), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message', 'note': 'input.note'}}), Set(cfg={'d': {'output.entity': '_user'}}), # CallbackNotify(), # CallbackExec() notify cannot work here ] ) ] ), orm.Action( key=orm.Action.build_key('0', 'logout'), arguments={ 'key': orm.SuperKeyProperty(kind='0', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_user.sessions': []}}), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'ip_address': '_user.ip_address'}}), UserLogoutOutput() ] ) ] ), # We need this action in order to properly prepare entities for client side access control! orm.Action( key=orm.Action.build_key('0', 'read_domains'), arguments={ 'key': orm.SuperKeyProperty(kind='0', required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), UserReadDomains() ] ) ] ) ] def get_output(self): dic = super(User, self).get_output() dic.update({'_csrf': self._csrf, # We will need the csrf but it has to be incorporated into security mechanism (http://en.wikipedia.org/wiki/Cross-site_request_forgery). '_is_guest': self._is_guest, '_root_admin': self._root_admin}) return dic @property def _root_admin(self): return self._primary_email in settings.ROOT_ADMINS @property def _is_taskqueue(self): return mem.temp_get('_current_request_is_taskqueue') @property def _is_cron(self): return mem.temp_get('_current_request_is_cron') def set_taskqueue(self, is_it): return mem.temp_set('_current_request_is_taskqueue', is_it) def set_cron(self, is_it): return mem.temp_set('_current_request_is_cron', is_it) def primary_email(self): if not self.identities.value: return None for identity in self.identities.value: if identity.primary == True: return identity.email return identity.email @property def _csrf(self): session = self.current_user_session() if not session: return None return hashlib.md5(session.session_id).hexdigest() @property def _is_guest(self): return self.key is None @classmethod def set_current_user(cls, user, session=None): mem.temp_set('_current_user', user) mem.temp_set('_current_user_session', session) @classmethod def current_user(cls): current_user = mem.temp_get('_current_user') if not current_user: current_user = cls() cls.set_current_user(current_user) return current_user @classmethod def get_system_user(cls): user_key = cls.build_key('system') user = user_key.get() if not user: identities = [Identity(email='System', identity='1-0', associated=True, primary=True)] user = cls(key=user_key, state='active', emails=['System'], identities=identities) user.put() return user @classmethod def current_user_session(cls): return mem.temp_get('_current_user_session') def session_by_id(self, session_id): for session in self.sessions.value: if session.session_id == session_id: return session return None @classmethod def set_current_user_from_auth_code(cls, auth_code): try: user_key, session_id = auth_code.split('|') except: return False # Fail silently if the authorization code is not set properly, or it is corrupted somehow. if not session_id: return False # Fail silently if the session id is not found in the split sequence. user_key = orm.Key(urlsafe=user_key) if user_key.kind() != cls.get_kind(): return False # Fail silently if the kind is not valid user = user_key.get() if user and user.key_id != 'system': user.read() session = user.session_by_id(session_id) if session: cls.set_current_user(user, session) return user
class Unit(orm.BaseExpando): _kind = 19 _use_record_engine = False _use_cache = True _use_memcache = True measurement = orm.SuperStringProperty( '1', required=True ) # By definition, once a unit is created, measurement can not be modified! @todo We can implement choices=['Currency', 'Mass'...], or we can use query projections for data presentation from this property! Shall we incorporate measurement value into key_id? name = orm.SuperStringProperty('2', required=True) symbol = orm.SuperStringProperty('3', required=True, indexed=False) rate = orm.SuperDecimalProperty( '4', indexed=False ) # The coefficient for the formula: 1 (base unit) = coef (this unit) - digits=(12, 12). factor = orm.SuperDecimalProperty( '5', indexed=False ) # The coefficient for the formula: coef (base unit) = 1 (this unit) - digits=(12, 12). rounding = orm.SuperDecimalProperty( '6', indexed=False) # Rounding Precision - digits=(12, 12). digits = orm.SuperIntegerProperty('7', indexed=False) active = orm.SuperBooleanProperty('8', required=True, default=True) _default_indexed = False _expando_fields = { 'code': orm.SuperStringProperty('9'), 'numeric_code': orm.SuperStringProperty('10'), 'grouping': orm.SuperIntegerProperty('11', repeated=True), 'decimal_separator': orm.SuperStringProperty('12'), 'thousands_separator': orm.SuperStringProperty('13'), 'positive_sign_position': orm.SuperIntegerProperty('14'), 'negative_sign_position': orm.SuperIntegerProperty('15'), 'positive_sign': orm.SuperStringProperty('16'), 'negative_sign': orm.SuperStringProperty('17'), 'positive_currency_symbol_precedes': orm.SuperBooleanProperty('18', default=True), 'negative_currency_symbol_precedes': orm.SuperBooleanProperty('19', default=True), 'positive_separate_by_space': orm.SuperBooleanProperty('20', default=True), 'negative_separate_by_space': orm.SuperBooleanProperty('21', default=True) } _global_role = GlobalRole(permissions=[ orm.ActionPermission('19', [ orm.Action.build_key('19', 'update_currency'), orm.Action.build_key('19', 'update_unit') ], True, 'user._root_admin or user._is_taskqueue'), orm.ActionPermission('19', [orm.Action.build_key('19', 'search')], True, 'not user._is_guest'), orm.FieldPermission('19', [ 'measurement', 'name', 'symbol', 'rate', 'factor', 'rounding', 'digits', 'active', 'code', 'numeric_code', 'grouping', 'decimal_separator', 'thousands_separator', 'positive_sign_position', 'negative_sign_position', 'positive_sign', 'positive_currency_symbol_precedes', 'negative_currency_symbol_precedes', 'positive_separate_by_space', 'negative_separate_by_space' ], False, True, 'True'), orm.FieldPermission('19', [ 'measurement', 'name', 'symbol', 'rate', 'factor', 'rounding', 'digits', 'active', 'code', 'numeric_code', 'grouping', 'decimal_separator', 'thousands_separator', 'positive_sign_position', 'negative_sign_position', 'positive_sign', 'positive_currency_symbol_precedes', 'negative_currency_symbol_precedes', 'positive_separate_by_space', 'negative_separate_by_space' ], True, True, 'user._root_admin or user._is_taskqueue') ]) _actions = [ orm.Action(key=orm.Action.build_key('19', 'update_currency'), arguments={}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), UnitCurrencyUpdateWrite( cfg={'file': settings.CURRENCY_DATA_FILE}) ]) ]), orm.Action( key=orm.Action.build_key('19', 'update_unit'), arguments={}, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), UnitUpdateWrite(cfg={'file': settings.UOM_DATA_FILE}) ]) ]), orm.Action( key=orm.Action.build_key('19', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={ 'filters': [{ 'field': 'active', 'value': True, 'operator': '==' }], 'orders': [{ 'field': 'name', 'operator': 'asc' }] }, cfg={ 'search_by_keys': True, 'search_arguments': { 'kind': '19', 'options': { 'limit': 1000 } }, 'filters': { 'measurement': orm.SuperStringProperty(), 'active': orm.SuperBooleanProperty(choices=[True]) }, 'indexes': [{ 'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])] }, { 'filters': [('active', ['==']), ('measurement', ['=='])], 'orders': [('name', ['asc', 'desc'])] }] }) }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), UnitRemoveCurrencies( ), # @todo This will be probably be removed!! RulePrepare(cfg={ 'path': '_entities', 'skip_user_roles': True }), Set( cfg={ 'd': { 'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more' } }) ]) ]) ] # @todo Do we make this a property named _uom or something similar ? def get_uom(self): '''This is because using unit_key.get() does not guarantee fresh new instance of unit that can be referenced as a entity, thats why we always create new instance of UOM. ''' new_uom = UOM() uom_fields = UOM.get_fields() for field_key, field in uom_fields.iteritems(): setattr(new_uom, field_key, getattr(self, field_key)) return new_uom
class Domain(orm.BaseExpando): _kind = 6 _use_memcache = True created = orm.SuperDateTimeProperty('1', required=True, auto_now_add=True) updated = orm.SuperDateTimeProperty('2', required=True, auto_now=True) name = orm.SuperStringProperty('3', required=True) primary_contact = orm.SuperKeyProperty('4', kind='8', indexed=False) # This field is required, and is handeled in update action via argument! state = orm.SuperStringProperty('5', required=True, choices=['active', 'suspended', 'su_suspended']) logo = SuperImageLocalStructuredProperty(Image, '6', required=True) _default_indexed = False _virtual_fields = { '_primary_contact_email': orm.SuperReferenceProperty(target_field='primary_contact', format_callback=lambda self, value: value._primary_email), '_records': orm.SuperRecordProperty('6') } _global_role = GlobalRole( permissions=[ orm.ActionPermission('6', [orm.Action.build_key('6', 'prepare'), orm.Action.build_key('6', 'create')], True, 'not user._is_guest'), orm.ActionPermission('6', orm.Action.build_key('6', 'update'), False, 'entity._original.state != "active"'), orm.ActionPermission('6', orm.Action.build_key('6', 'suspend'), False, 'entity._original.state != "active"'), orm.ActionPermission('6', orm.Action.build_key('6', 'activate'), False, 'entity._original.state == "active" or entity._original.state == "su_suspended"'), orm.FieldPermission('6', ['created', 'updated', 'state'], False, None, 'True'), orm.FieldPermission('6', ['name', 'primary_contact', 'logo', '_records', '_primary_contact_email'], False, None, 'entity._original.state != "active"'), orm.FieldPermission('6', ['state'], True, None, '(action.key_id_str == "activate" and entity.state == "active") or (action.key_id_str == "suspend" and entity.state == "suspended")'), # Domain is unit of administration, hence root admins need control over it! # Root admins can always: read domain; search for domains (exclusively); # read domain history; perform sudo operations (exclusively); log messages; read _records.note field (exclusively). orm.ActionPermission('6', [orm.Action.build_key('6', 'read'), orm.Action.build_key('6', 'search'), orm.Action.build_key('6', 'sudo'), orm.Action.build_key('6', 'log_message')], True, 'user._root_admin'), orm.ActionPermission('6', [orm.Action.build_key('6', 'search'), orm.Action.build_key('6', 'sudo')], False, 'not user._root_admin'), orm.FieldPermission('6', ['created', 'updated', 'name', 'primary_contact', 'state', 'logo', '_records', '_primary_contact_email'], None, True, 'user._root_admin'), orm.FieldPermission('6', ['_records.note'], True, True, 'user._root_admin'), orm.FieldPermission('6', ['_records.note'], False, False, 'not user._root_admin'), orm.FieldPermission('6', ['state'], True, None, '(action.key_id_str == "sudo") and user._root_admin and (entity.state == "active" or entity.state == "su_suspended")'), orm.FieldPermission('6', ['created', 'updated', 'name', 'state', 'logo'], None, True, 'entity._original.state == "active"') ] ) _actions = [ orm.Action( key=orm.Action.build_key('6', 'prepare'), arguments={ 'upload_url': orm.SuperStringProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), BlobURL(cfg={'bucket': settings.BUCKET_PATH}), Set(cfg={'d': {'output.entity': '_domain', 'output.upload_url': '_blob_url'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'create'), arguments={ 'name': orm.SuperStringProperty(required=True), 'logo': SuperImageLocalStructuredProperty(Image, required=True, process_config={'measure': False, 'transform': True, 'width': 240, 'height': 100, 'crop_to_fit': True}) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ DomainCreateWrite(), Set(cfg={'d': {'output.entity': '_domain'}}), CallbackExec(cfg=[('callback', {'action_id': 'install', 'action_model': '57'}, {'key': '_config.key_urlsafe'})]) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'read'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec(), Set(cfg={'d': {'output.entity': '_domain'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'update'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'name': orm.SuperStringProperty(required=True), 'primary_contact': orm.SuperKeyProperty(required=True, kind='8', validator=primary_contact_validator), 'logo': SuperImageLocalStructuredProperty(Image, process_config={'measure': False, 'transform': True, 'width': 240, 'height': 100, 'crop_to_fit': True}), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'d': {'_domain.name': 'input.name', '_domain.primary_contact': 'input.primary_contact', '_domain.logo': 'input.logo'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': {'output.entity': '_domain'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={'filters': [], 'orders': [{'field': 'created', 'operator': 'desc'}]}, cfg={ 'search_arguments': {'kind': '6', 'options': {'limit': settings.SEARCH_PAGE}}, 'filters': {'name': orm.SuperStringProperty(), 'state': orm.SuperStringProperty()}, 'indexes': [{'orders': [('name', ['asc', 'desc'])]}, {'orders': [('created', ['asc', 'desc'])]}, {'orders': [('updated', ['asc', 'desc'])]}, {'filters': [('name', ['==', '!='])], 'orders': [('created', ['asc', 'desc'])]}, {'filters': [('state', ['==', '!='])], 'orders': [('created', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities', 'skip_user_roles': True}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'suspend'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'message': orm.SuperTextProperty(required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_domain.state': 'suspended'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message'}}), CallbackNotify(), CallbackExec() ] ), orm.PluginGroup( plugins=[ RulePrepare(), Set(cfg={'d': {'output.entity': '_domain'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'activate'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'message': orm.SuperTextProperty(required=True) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'s': {'_domain.state': 'active'}}), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message'}}), CallbackNotify(), CallbackExec() ] ), orm.PluginGroup( plugins=[ RulePrepare(), Set(cfg={'d': {'output.entity': '_domain'}}) ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'sudo'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'state': orm.SuperStringProperty(required=True, choices=['active', 'suspended', 'su_suspended']), 'message': orm.SuperTextProperty(required=True), 'note': orm.SuperTextProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), Set(cfg={'d': {'_domain.state': 'input.state'}}), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message', 'note': 'input.note'}}), RulePrepare(cfg={'skip_user_roles': True}), Set(cfg={'d': {'output.entity': '_domain'}}), CallbackNotify(), CallbackExec() ] ) ] ), orm.Action( key=orm.Action.build_key('6', 'log_message'), arguments={ 'key': orm.SuperKeyProperty(kind='6', required=True), 'message': orm.SuperTextProperty(required=True), 'note': orm.SuperTextProperty() }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(), RuleExec() ] ), orm.PluginGroup( transactional=True, plugins=[ Write(cfg={'dra': {'message': 'input.message', 'note': 'input.note'}}), Set(cfg={'d': {'output.entity': '_domain'}}), CallbackNotify(), CallbackExec() ] ) ] ) ] @property def key_namespace(self): return self.key.urlsafe() @property def namespace_entity(self): return self
class Country(orm.BaseModel): _kind = 15 _use_record_engine = False _use_cache = True _use_memcache = True code = orm.SuperStringProperty('1', required=True, indexed=False) name = orm.SuperStringProperty('2', required=True) active = orm.SuperBooleanProperty('3', required=True, default=True) _global_role = GlobalRole( permissions=[ orm.ActionPermission('15', [orm.Action.build_key('15', 'update')], True, 'user._root_admin or user._is_taskqueue'), orm.ActionPermission('15', [orm.Action.build_key('15', 'search')], True, 'not user._is_guest'), orm.FieldPermission('15', ['code', 'name', 'active'], False, True, 'True'), orm.FieldPermission('15', ['code', 'name', 'active'], True, True, 'user._root_admin or user._is_taskqueue') ] ) _actions = [ orm.Action( key=orm.Action.build_key('15', 'update'), arguments={}, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), CountryUpdateWrite(cfg={'file': settings.LOCATION_DATA_FILE, 'prod_env': settings.DEVELOPMENT_SERVER}) ] ) ] ), orm.Action( key=orm.Action.build_key('15', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={'filters': [{'field': 'active', 'value': True, 'operator': '=='}], 'orders': [{'field': 'name', 'operator': 'asc'}]}, cfg={ 'search_by_keys': True, 'search_arguments': {'kind': '15', 'options': {'limit': 1000}}, 'filters': {'active': orm.SuperBooleanProperty(choices=[True])}, 'indexes': [{'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities', 'skip_user_roles': True}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ) ]
class CountrySubdivision(orm.BaseModel): _kind = 16 _use_record_engine = False _use_cache = True _use_memcache = True parent_record = orm.SuperKeyProperty('1', kind='16', indexed=False) code = orm.SuperStringProperty('2', required=True, indexed=False) name = orm.SuperStringProperty('3', required=True) complete_name = orm.SuperTextProperty('4', required=True) type = orm.SuperStringProperty('5', required=True, indexed=False) active = orm.SuperBooleanProperty('6', required=True, default=True) _global_role = GlobalRole( permissions=[ orm.ActionPermission('16', [orm.Action.build_key('16', 'search')], True, 'not user._is_guest'), orm.FieldPermission('16', ['parent_record', 'code', 'name', 'complete_name', 'type', 'active'], False, True, 'True'), orm.FieldPermission('16', ['parent_record', 'code', 'name', 'complete_name', 'type', 'active'], True, True, 'user._root_admin or user._is_taskqueue') ] ) _actions = [ orm.Action( key=orm.Action.build_key('16', 'search'), arguments={ 'search': orm.SuperSearchProperty( default={'filters': [{'field': 'active', 'value': True, 'operator': '=='}], 'orders': [{'field': 'name', 'operator': 'asc'}]}, cfg={ 'ancestor_kind': '15', 'search_by_keys': True, 'search_arguments': {'kind': '16', 'options': {'limit': settings.SEARCH_PAGE}}, 'filters': {'name': orm.SuperStringProperty(value_filters=[lambda p, s: s.capitalize()]), 'active': orm.SuperBooleanProperty(choices=[True])}, 'indexes': [{'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])]}, {'ancestor': True, 'filters': [('active', ['=='])], 'orders': [('name', ['asc', 'desc'])]}, {'filters': [('active', ['==']), ('name', ['==', '!=', 'contains'])], 'orders': [('name', ['asc', 'desc'])]}, {'ancestor': True, 'filters': [('active', ['==']), ('name', ['==', '!=', 'contains'])], 'orders': [('name', ['asc', 'desc'])]}] } ) }, _plugin_groups=[ orm.PluginGroup( plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Search(), RulePrepare(cfg={'path': '_entities', 'skip_user_roles': True}), Set(cfg={'d': {'output.entities': '_entities', 'output.cursor': '_cursor', 'output.more': '_more'}}) ] ) ] ) ]
class Addresses(orm.BaseModel): _kind = 77 addresses = orm.SuperLocalStructuredProperty(Address, '1', repeated=True) _virtual_fields = {'_records': orm.SuperRecordProperty('77')} _global_role = GlobalRole(permissions=[ orm.ActionPermission( '77', [ orm.Action.build_key('77', 'update'), orm.Action.build_key('77', 'read') ], True, 'entity._original.key_parent == user.key and not user._is_guest'), orm.FieldPermission( '77', ['addresses', '_records'], True, True, 'entity._original.key_parent == user.key and not user._is_guest') ]) _actions = [ orm.Action( key=orm.Action.build_key('77', 'update'), arguments={ 'user': orm.SuperKeyProperty(kind='0', required=True), 'addresses': orm.SuperLocalStructuredProperty(Address, repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set(cfg={'d': { '_addresses.addresses': 'input.addresses' }}), AddressesUpdateSet(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_addresses' }}) ]) ]), orm.Action(key=orm.Action.build_key('77', 'read'), arguments={ 'user': orm.SuperKeyProperty(kind='0', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Set(cfg={'d': { 'output.entity': '_addresses' }}) ]) ]) ] @classmethod def prepare_key(cls, input, **kwargs): user_key = input.get('user') return cls.build_key(user_key._id_str, parent=user_key)
class Collection(orm.BaseModel): _kind = 10 notify = orm.SuperBooleanProperty('1', required=True, default=False) domains = orm.SuperKeyProperty('2', kind='6', repeated=True) _virtual_fields = { '_records': orm.SuperRecordProperty('10'), '_domains': orm.SuperReferenceStructuredProperty( '6', autoload=False, callback=lambda self: orm.get_multi_async( [domain_key for domain_key in self.domains]), format_callback=lambda self, entities: orm.get_async_results( entities)) } _global_role = GlobalRole(permissions=[ orm.ActionPermission( '10', [ orm.Action.build_key('10', 'update'), orm.Action.build_key('10', 'read') ], True, 'entity._original.key_parent == user.key and not user._is_guest'), orm.FieldPermission( '10', [ 'notify', 'domains', '_records', '_domains.name', '_domains.logo' ], True, True, 'entity._original.key_parent == user.key and not user._is_guest') ]) _actions = [ orm.Action(key=orm.Action.build_key('10', 'update'), arguments={ 'user': orm.SuperKeyProperty(kind='0', required=True), 'notify': orm.SuperBooleanProperty(default=True), 'domains': orm.SuperKeyProperty(kind='6', repeated=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), Set( cfg={ 'd': { '_collection.notify': 'input.notify', '_collection.domains': 'input.domains' } }), RulePrepare(cfg={'skip_user_roles': True}), RuleExec() ]), orm.PluginGroup( transactional=True, plugins=[ Write(), Set(cfg={'d': { 'output.entity': '_collection' }}) ]) ]), orm.Action(key=orm.Action.build_key('10', 'read'), arguments={ 'user': orm.SuperKeyProperty(kind='0', required=True), 'read_arguments': orm.SuperJsonProperty() }, _plugin_groups=[ orm.PluginGroup(plugins=[ Context(), Read(), RulePrepare(cfg={'skip_user_roles': True}), RuleExec(), Set(cfg={'d': { 'output.entity': '_collection' }}) ]) ]) ] @classmethod def prepare_key(cls, input, **kwargs): user_key = input.get('user') return cls.build_key(user_key._id_str, parent=user_key)