def recordtype_url(coll_id="testcoll", type_id="testtype"): """ URL for record type description data; also view using default entity view """ if not valid_id(type_id): return None return collection_entity_view_url(coll_id=coll_id, type_id="_type", entity_id=type_id)
def annalistuser_url(coll_id="testcoll", user_id="testuser"): """ URI for user permissions data; also view using default entity view """ if not valid_id(user_id): user_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_user", entity_id=user_id)
def recordview_url(coll_id, view_id): """ URI for record view description data; also view using default entity view """ if not valid_id(view_id): view_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_view", entity_id=view_id)
def recordlist_url(coll_id, list_id): """ URI for record list description data; also view using default entity view """ if not valid_id(list_id): list_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_list", entity_id=list_id)
def authorize(self, scope, collection, continuation_url=None): """ Return None if user is authorized to perform the requested operation, otherwise appropriate 401 Authorization Required or 403 Forbidden response. May be called with or without an authenticated user. scope indication of the operation requested to be performed. e.g. "VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", ... collection is the collection to which the requested action is directed, or None if the test is against site-level permissions. continutation_url is a URL to (re)display when any error is dismissed or has otherwise been handled. """ user_id, user_uri = self.get_user_identity() coll_id = collection.get_id() if collection else "(site)" if not util.valid_id(user_id): log.warning("Invalid user_id %s, URI %s"%(user_id, user_uri)) message="Bad request to %(request_uri)s: invalid user_id: '"+user_id+"'" return self.error(self.error400values(message=message), continuation_url=continuation_url) user_perms = self.get_user_permissions(collection, user_id, user_uri) if not user_perms: log.warning("No user permissions found for user_id %s, URI %s"%(user_id, user_uri)) log.warning("".join(traceback.format_stack())) return self.error(self.error403values(scope=scope), continuation_url=continuation_url) # log.info("Authorize %s in %s, %s, %r"%(user_id, coll_id, scope, user_perms[ANNAL.CURIE.user_permission])) # user_perms is an AnnalistUser object coll_id = collection.get_id() if collection else "(No coll)" if scope not in user_perms[ANNAL.CURIE.user_permission]: if user_id == unknown_user_id: err = self.error401values(scope=scope) else: err = self.error403values(scope=scope) return self.error(err, continuation_url=continuation_url) return None
def authorize(self, scope, collection): """ Return None if user is authorized to perform the requested operation, otherwise appropriate 401 Authorization Required or 403 Forbidden response. May be called with or without an authenticated user. scope indication of the operation requested to be performed. e.g. "VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", ... collection is the collection to which the requested action is directed, or None if the test is against site-level permissions. """ user_id, user_uri = self.get_user_identity() coll_id = collection.get_id() if collection else "(site)" if not util.valid_id(user_id): log.warning("Invalid user_id %s, URI %s" % (user_id, user_uri)) message = "Bad request to %(request_uri)s: invalid user_id: '" + user_id + "'" return self.error(self.error400values(message=message)) user_perms = self.get_user_permissions(collection, user_id, user_uri) if not user_perms: log.warning("No user permissions found for user_id %s, URI %s" % (user_id, user_uri)) return self.error(self.error403values(scope=scope)) # log.info("Authorize %s in %s, %s, %r"%(user_id, coll_id, scope, user_perms[ANNAL.CURIE.user_permissions])) # user_perms is an AnnalistrUser object coll_id = collection.get_id() if collection else "(No coll)" if scope not in user_perms[ANNAL.CURIE.user_permissions]: if user_id == "_unknown_user_perms": err = self.error401values(scope=scope) else: err = self.error403values(scope=scope) return self.error(err) return None
def get_entity(self, entity_id, action="view"): """ Loads and returns an entity for the current type, or returns None if the entity does not exist. If `action` is "new" then a new entity is initialized (but not saved). """ # log.debug( # "EntityTypeInfo.get_entity id %s, parent %s, altparent %s, action %s"% # (entity_id, self.entityparent, self.entityaltparent, action) # ) entity = None entity_id = extract_entity_id(entity_id) if valid_id(entity_id): if action == "new": entity = self._new_entity(entity_id) entity_initial_values = self.get_initial_entity_values( entity_id) entity.set_values(entity_initial_values) elif self.entityclass.exists(self.entityparent, entity_id, altscope="all"): entity = self.entityclass.load(self.entityparent, entity_id, altscope="all") else: log.debug( "EntityTypeInfo.get_entity %s/%s at %s not found" % (self.type_id, entity_id, self.entityparent._entitydir)) return entity
def _find_fields(fieldmap, group_list): if fieldmap is None: log.warning("entityedit.find_fields: fieldmap is None") return # Always called with list of field descriptions for field_desc in fieldmap: log.debug("find_fields: field_desc %r" % (field_desc)) if filter_f(field_desc): field_desc['group_list'] = group_list log.info( "entityedit.find_fields: field name %s, prefixes %r" % (field_desc.get_field_name(), group_list)) yield field_desc if field_desc.has_field_group_ref(): groupref = field_desc.group_ref() if not util.valid_id(groupref): # this is for resilience in the face of bad data log.warning( "entityedit.find_fields: invalid group_ref %s in field description for %s" % (groupref, field_desc['field_id'])) else: log.info( "entityedit.find_fields: Group field desc %s: %s" % (groupref, field_desc['field_id'])) group_fields = field_desc['group_field_descs'] new_group_list = group_list + [field_desc['group_id']] for fd in _find_fields(group_fields, new_group_list): yield fd return
def entity_url(coll_id="testcoll", type_id="testtype", entity_id="entity_id"): """ URI for entity data; also view using default entity view """ if not valid_id(entity_id): entity_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id=type_id, entity_id=entity_id)
def get_collection_subtype_ids(self, supertype_id, altscope): """ Returns a iterator of type ids for all subtypes of the supplied type accessible in the indicated scope from the current collection, including the identified type itself. """ if not valid_id(supertype_id): log.warning( "EntityFinder.get_collection_subtype_ids: invalid type_id %s" % (supertype_id, )) return supertype_info = EntityTypeInfo(self._coll, supertype_id) supertype_uri = supertype_info.get_type_uri() if supertype_uri is not None: for try_subtype_id in self.get_collection_type_ids(altscope): try_subtype = self._coll.cache_get_type(try_subtype_id) if try_subtype: try_subtype_uri = try_subtype.get_uri() if ((supertype_uri == try_subtype_uri) or (supertype_uri in self._coll.cache_get_supertype_uris( try_subtype_uri))): yield try_subtype_id else: log.warning( "EntityFinder.get_collection_subtype_ids: no type_uri for %s" % (supertype_id, ))
def recordgroup_url(coll_id, group_id): """ URI for group description data; also view using default entity view """ if not valid_id(group_id): return None # group_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_group", entity_id=group_id)
def recordvocab_url(coll_id, vocab_id): """ URI for namespace vocabulary description data; also view using default entity view """ if not valid_id(vocab_id): return None # vocab_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_vocab", entity_id=vocab_id)
def recordfield_url(coll_id, field_id): """ URI for record field description data; also view using default entity view """ if not valid_id(field_id): return None # field_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_field", entity_id=field_id)
def recordfield_url(coll_id, field_id): """ URI for record field description data; also view using default entity view """ if not valid_id(field_id): field_id = "___" return collection_entity_view_url(coll_id=coll_id, type_id="_field", entity_id=field_id)
def collectiondata_url(coll_id="testcoll"): """ URI for collection description data; also view using default entity view e.g. http://example.com/site/c/_annalist_site/d/_coll/testcoll/ """ if not valid_id(coll_id, reserved_ok=True): coll_id = "___" return collection_entity_view_url(coll_id=layout.SITEDATA_ID, type_id="_coll", entity_id=coll_id)
def collectiondata_url(coll_id="testcoll"): """ URI for collection description data; also view using default entity view e.g. http://example.com/site/c/_annalist_site/d/_coll/testcoll/ """ if not valid_id(coll_id): coll_id = "___" return collection_entity_view_url(coll_id=layout.SITEDATA_ID, type_id="_coll", entity_id=coll_id)
def get_type(self, type_id): """ Retrieve identified type description type_id local identifier for the type to retrieve. returns a RecordType object for the identified type, or None. """ if not valid_id(type_id): msg = "Collection %s get_type(%s) invalid id"%(self.get_id(), type_id) log.error(msg) raise ValueError(msg, type_id) return self.cache_get_type(type_id)
def get_field(self, field_id): """ Retrieve identified field description field_id local identifier for the field to retrieve. returns a RecordField object for the identified field, or None. """ if not valid_id(field_id): msg = "Collection %s get_field(%s) invalid id"%(self.get_id(), field_id) log.error(msg) raise ValueError(msg, field_id) return self.cache_get_field(field_id)
def _base_children(self, cls): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. """ parent_dir = os.path.dirname(os.path.join(self._entitydir, cls._entityroot or "")) assert "%" not in parent_dir, "_entityroot template variable interpolation may be in filename part only" child_files = [] if os.path.isdir(parent_dir): child_files = os.listdir(parent_dir) for fil in child_files: if util.valid_id(fil, reserved_ok=True): yield fil return
def __init__(self, parent, entityid, altparent=None, idcheck=True, use_altpath=False): """ Initialize a new Entity object, possibly without values. The created entity is not saved to disk at this stage - see ._save() method. parent is the parent entity from which the new entity is descended. entityid the collection identifier for the collection altparent is an alternative parent entity to search for this entity, using the alternative path for the entity type: this is used to augment explicitly created entities in a collection with site-wide installed metadata entites (i.e. types, views, etc.) idcheck is set False to skip the valid-identifier check use_altpath is set True if this entity is situated at the alternative path relative to its parent. """ if idcheck and not util.valid_id(entityid): raise ValueError("Invalid entity identifier: %s" % (entityid)) relpath = self.relpath(entityid) if use_altpath: relpath = self.altpath(entityid) super(Entity, self).__init__(parent._entityurl + relpath, parent._entitydir + relpath) self._entityviewuri = parent._entityurl + self._entityview % { 'id': entityid, 'type_id': self._entitytypeid } self._entityalturi = None self._entityaltdir = None if altparent: altpath = self.altpath(entityid) self._entityalturi = altparent._entityurl + altpath self._entityaltdir = altparent._entitydir + altpath self._entityuseuri = None # URI not known until entity is created or accessed log.debug("Entity.__init__: entity alt URI %s, entity alt dir %s" % (self._entityalturi, self._entityaltdir)) self._entityid = entityid log.debug("Entity.__init__: entity_id %s, type_id %s" % (self._entityid, self.get_type_id())) return
def recordfield_edit_url(action=None, coll_id=None, field_id=None): """ URI for record field description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistRecordFieldDeleteView' if action == "delete" else 'unknown') kwargs = {'coll_id': coll_id, 'type_id': "_field", 'view_id': "Field_view"} if action != "delete": kwargs.update({'action': action}) if field_id: if valid_id(field_id): kwargs.update({'entity_id': field_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def _base_children(self, cls): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. """ parent_dir = os.path.dirname( os.path.join(self._entitydir, cls._entityroot or "")) assert "%" not in parent_dir, "_entityroot template variable interpolation may be in filename part only" child_files = [] if os.path.isdir(parent_dir): child_files = os.listdir(parent_dir) for fil in child_files: if util.valid_id(fil): yield fil return
def recordvocab_edit_url(action=None, coll_id=None, vocab_id=None): """ URI for vocabulary description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistRecordVocabDeleteView' if action == "delete" else 'unknown') kwargs = {'coll_id': coll_id, 'type_id': "_vocab", 'view_id': "Vocab_view"} if action != "delete": kwargs.update({'action': action}) if vocab_id: if valid_id(vocab_id): kwargs.update({'entity_id': vocab_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def __init__(self, parent, entityid, altparent=None): """ Initialize a new Entity object, possibly without values. The created entity is not saved to disk at this stage - see ._save() method. parent is the parent entity from which the new entity is descended. entityid the collection identifier for the collection altparent is an alternative parent entity to search for this entity, using the alternative path for the entity type: this is used to augment explicitly created entities in a collection with site-wide installed metadata entites (i.e. types, views, etc.) """ if not util.valid_id(entityid): msg = "Invalid entity identifier: %s" % (entityid) raise ValueError(msg) relpath = self.relpath(entityid) # log.debug( # "@@ _ Entity.__init__: id %s, parenturl %s, parentdir %s, relpath %s"% # (entityid, parent._entityurl, parent._entitydir, relpath) # ) entity_url = urlparse.urljoin(parent._entityurl, relpath) entity_dir = os.path.normpath(os.path.join(parent._entitydir, relpath)) entity_base = parent._entitydir # Used as safety check when removing data if not entity_dir.startswith(entity_base): entity_base = parent._entitybasedir # log.debug( # "@@ _ Entity.__init__: entity_url %s, entity_dir %s"% # (entity_url, entity_dir) # ) entityviewurl = urlparse.urljoin( parent._entityviewurl, self._entityview % { 'id': entityid, 'type_id': self._entitytypeid }) super(Entity, self).__init__(entity_url, entityviewurl, entity_dir, entity_base) self._entityid = entityid self._parent = parent self._ancestorid = entityid # May be changed by subclass _local_find_alt_parents self._altparent = altparent # Alternative to current entity to search # log.debug("Entity.__init__: entity_id %s, type_id %s"%(self._entityid, self.get_type_id())) return
def load(cls, parent, entityid, altscope=None): """ Return an entity with given identifier belonging to some given parent, or None if there is not such identity. cls is the class of the entity to be loaded parent is the parent from which the entity is descended. entityid is the local identifier (slug) for the entity. altscope if supplied, indicates a scope other than the current entity to search for children. See `_find_alt_parents` for more details. Returns an instance of the indicated class with data loaded from the corresponding Annalist storage, or None if there is no such entity. """ # log.debug("Entity.load: entity %s/%s, altscope %s"% # (cls._entitytype, entityid, altscope) # ) # if altscope is not None: # if not isinstance(altscope, (unicode, str)): # log.error("altscope must be string (%r supplied)"%(altscope)) # log.error("".join(traceback.format_stack())) # raise ValueError("altscope must be string (%r supplied)"%(altscope)) entity = None if util.valid_id(entityid): (e, v) = cls.try_alt_parentage( parent, entityid, (lambda e: e._load_values()), altscope=altscope ) # log.info(" __ Entity.load: _load_values "+repr(v)) # log.info("entity.load %r"%(v,)) if v: v = e._migrate_values(v) e.set_values(v) entity = e else: log.debug("Entity.load: invalid id %s"%entityid) # log.warning("@@Entity.load ub %r"%(entity._entityurl)) # log.warning("@@Entity.load uv %r"%(entity._entityviewurl)) # log.warning("@@Entity.load e %r"%(entity)) # log.warning("@@Entity.load v %r"%(v)) return entity
def load(cls, parent, entityid, altscope=None, reserved_ok=False): """ Return an entity with given identifier belonging to some given parent, or None if there is not such identity. cls is the class of the entity to be loaded parent is the parent from which the entity is descended. entityid is the local identifier (slug) for the entity. altscope if supplied, indicates a scope other than the current entity to search for children. See `_find_alt_parents` for more details. Returns an instance of the indicated class with data loaded from the corresponding Annalist storage, or None if there is no such entity. """ # log.debug("Entity.load: entity %s/%s, altscope %s"% # (cls._entitytype, entityid, altscope) # ) # if altscope is not None: # if not isinstance(altscope, (unicode, str)): # log.error("altscope must be string (%r supplied)"%(altscope)) # log.error("".join(traceback.format_stack())) # raise ValueError("altscope must be string (%r supplied)"%(altscope)) entity = None if util.valid_id(entityid, reserved_ok=reserved_ok): (e, v) = cls.try_alt_parentage(parent, entityid, (lambda e: e._load_values()), altscope=altscope) # log.info(" __ Entity.load: _load_values "+repr(v)) # log.info("entity.load %r"%(v,)) if v: v = e._migrate_values(v) e.set_values(v) entity = e else: log.debug("Entity.load: invalid id %s" % entityid) # log.warning("@@Entity.load ub %r"%(entity._entityurl)) # log.warning("@@Entity.load uv %r"%(entity._entityviewurl)) # log.warning("@@Entity.load e %r"%(entity)) # log.warning("@@Entity.load v %r"%(v)) return entity
def __init__(self, parent, entityid, altparent=None): """ Initialize a new Entity object, possibly without values. The created entity is not saved to disk at this stage - see ._save() method. parent is the parent entity from which the new entity is descended. entityid the collection identifier for the collection altparent is an alternative parent entity to search for this entity, using the alternative path for the entity type: this is used to augment explicitly created entities in a collection with site-wide installed metadata entites (i.e. types, views, etc.) """ if not util.valid_id(entityid, reserved_ok=True): msg = "Invalid entity identifier: %s"%(entityid) log.error(msg) raise ValueError(msg) relpath = self.relpath(entityid) # log.debug( # "@@ _ Entity.__init__: id %s, parenturl %s, parentdir %s, relpath %s"% # (entityid, parent._entityurl, parent._entitydir, relpath) # ) entity_url = urljoin(parent._entityurl, relpath) entity_dir = os.path.normpath(os.path.join(parent._entitydir, relpath)) entity_base = parent._entitydir # Used as safety check when removing data if not entity_dir.startswith(entity_base): entity_base = parent._entitybasedir # log.debug( # "@@ _ Entity.__init__: entity_url %s, entity_dir %s"% # (entity_url, entity_dir) # ) entityviewurl = urljoin( parent._entityviewurl, self._entityview%{'id': entityid, 'type_id': self._entitytypeid} ) super(Entity, self).__init__(entity_url, entityviewurl, entity_dir, entity_base) self._entityid = entityid self._parent = parent self._ancestorid = entityid # May be changed by subclass _local_find_alt_parents self._altparent = altparent # Alternative to current entity to search # log.debug("Entity.__init__: entity_id %s, type_id %s"%(self._entityid, self.get_type_id())) return
def annalistuser_edit_url(action=None, coll_id=None, user_id=None): """ URI for user permissions description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistUserDeleteView' if action == "delete" else 'unknown' ) kwargs = {'coll_id': coll_id} if action != "delete": kwargs.update({'action': action, 'type_id': "_user", 'view_id': "User_view"}) if user_id: if valid_id(user_id): kwargs.update({'entity_id': user_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def get_collection_subtype_ids(self, supertype_id, altscope): """ Returns a iterator of type ids for all subtypes of the supplied type accessible in the indicated scope from the current collection, including the identified type itself. """ if not valid_id(supertype_id): log.warning("EntityFinder.get_collection_subtype_ids: invalid type_id %s"%(supertype_id,)) return supertype_info = EntityTypeInfo(self._coll, supertype_id) supertype_uri = supertype_info.get_type_uri() if supertype_uri is not None: for try_subtype_id in self.get_collection_type_ids(altscope): try_subtype = self._coll.cache_get_type(try_subtype_id) if try_subtype: try_subtype_uri = try_subtype.get_uri() if ( ( supertype_uri == try_subtype_uri ) or ( supertype_uri in self._coll.cache_get_supertype_uris(try_subtype_uri) ) ): yield try_subtype_id else: log.warning("EntityFinder.get_collection_subtype_ids: no type_uri for %s"%(supertype_id,))
def recordvocab_edit_url(action=None, coll_id=None, vocab_id=None): """ URI for vocabulary description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistRecordVocabDeleteView' if action == "delete" else 'unknown' ) kwargs = {'coll_id': coll_id, 'type_id': "_vocab", 'view_id': "Vocab_view"} if action != "delete": kwargs.update({'action': action}) if vocab_id: if valid_id(vocab_id): kwargs.update({'entity_id': vocab_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def recordlist_edit_url(action=None, coll_id=None, list_id=None): """ URI for record list description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistRecordListDeleteView' if action == "delete" else 'unknown' ) kwargs = {'coll_id': coll_id} if action != "delete": kwargs.update({'action': action, 'type_id': "_list", 'view_id': "List_view"}) if list_id: if valid_id(list_id): kwargs.update({'entity_id': list_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def recordgroup_edit_url(action=None, coll_id=None, group_id=None): """ URI for group description editing view """ viewname = ( 'AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistRecordFieldDeleteView' if action == "delete" else 'unknown' ) kwargs = {'coll_id': coll_id, 'type_id': "_field", 'view_id': "Field_view"} if action != "delete": kwargs.update({'action': action}) if group_id: if valid_id(group_id): kwargs.update({'entity_id': group_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def _children(self, cls, altscope=None): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. altscope if supplied, indicates a scope other than the current entity to search for children. @@NOTE: The logic in this method is intended to return inherited values before values defined in the current collection. It should probably be re-worked to return entries in order from all inherited definitions. The logic here could possibly be simplified to extract all values in the "alt parents" loop, (though the ordering might be tricky to preserve that way). """ # log.info("@@ Entity._children: parent %s, altscope %s"%(self.get_id(), altscope)) coll_entity_ids = list( super(Entity, self)._children(cls, altscope=None)) alt_parents = self.get_alt_entities(altscope=altscope) # parent_entity_ids = list(itertools.chain.from_iterable( # ( super(Entity, alt)._children(cls, altscope=altscope) # for alt in alt_parents # self.get_alt_entities(altscope=altscope) # ))) # See https://docs.python.org/2/library/itertools.html#itertools.chain parent_entity_ids = [] for alt in alt_parents: for eid in super(Entity, alt)._children(cls, altscope=altscope): # Filter out duplicates if eid not in parent_entity_ids: parent_entity_ids.append(eid) # log.info("@@ Entity._children: coll_entity_ids %r, parent_entity_ids %r"%(coll_entity_ids, parent_entity_ids)) # if altscope == "all" and self._altparent: # parent_entity_ids = self._altparent._children(cls, altscope=altscope) for entity_id in [ f for f in parent_entity_ids if f not in coll_entity_ids ] + coll_entity_ids: if util.valid_id(entity_id): yield entity_id return
def get_entity(self, entity_id, action="view"): """ Loads and returns an entity for the current type, or returns None if the entity does not exist. If `action` is "new" then a new entity is initialized (but not saved). """ log.debug( "get_entity id %s, parent %s, altparent %s, action %s"% (entity_id, self.entityparent, self.entityaltparent, action) ) entity = None if util.valid_id(entity_id): if action == "new": entity = self.entityclass(self.entityparent, entity_id) entity_initial_values = self.get_initial_entity_values(entity_id) entity.set_values(entity_initial_values) elif self.entityclass.exists( self.entityparent, entity_id, altparent=self.entityaltparent ): entity = self.entityclass.load(self.entityparent, entity_id, altparent=self.entityaltparent) return entity
def allocate_new_id(cls, parent, base_id=None): """ Allocate and return an as-yet-unused entity id for a member of the indicated entity class as an offsprintof the indicated parent. If "base_id" is specified, it is used as part of the new Id allocated (used when copying an entity). """ if base_id and util.valid_id(base_id): last_id = 0 name_format = base_id + "_%02d" else: last_id = cls._last_id or 0 name_format = "%08d" while True: last_id += 1 new_id = name_format % last_id if not cls.exists(parent, new_id): break if not base_id: cls._last_id = last_id return new_id
def allocate_new_id(cls, parent, base_id=None): """ Allocate and return an as-yet-unused entity id for a member of the indicated entity class as an offsprintof the indicated parent. If "base_id" is specified, it is used as part of the new Id allocated (used when copying an entity). """ if base_id and util.valid_id(base_id): last_id = 0 name_format = base_id+"_%02d" else: last_id = cls._last_id or 0 name_format = "%08d" while True: last_id += 1 new_id = name_format%last_id if not cls.exists(parent, new_id): break if not base_id: cls._last_id = last_id return new_id
def annalistuser_edit_url(action=None, coll_id=None, user_id=None): """ URI for user permissions description editing view """ viewname = ('AnnalistEntityDataView' if action == "view" else 'AnnalistEntityNewView' if action == "new" else 'AnnalistEntityEditView' if action == "copy" else 'AnnalistEntityEditView' if action == "edit" else 'AnnalistUserDeleteView' if action == "delete" else 'unknown') kwargs = {'coll_id': coll_id} if action != "delete": kwargs.update({ 'action': action, 'type_id': "_user", 'view_id': "User_view" }) if user_id: if valid_id(user_id): kwargs.update({'entity_id': user_id}) else: kwargs.update({'entity_id': "___"}) return reverse(viewname, kwargs=kwargs)
def _children(self, cls, altscope=None): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. altscope if supplied, indicates a scope other than the current entity to search for children. @@NOTE: The logic in this method is intended to return inherited values before values defined in the current collection. It should probably be re-worked to return entries in order from all inherited definitions. The logic here could possibly be simplified to extract all values in the "alt parents" loop, (though the ordering might be tricky to preserve that way). """ # log.info("@@ Entity._children: parent %s, altscope %s"%(self.get_id(), altscope)) coll_entity_ids = list(super(Entity, self)._children(cls, altscope=None)) alt_parents = self.get_alt_entities(altscope=altscope) # parent_entity_ids = list(itertools.chain.from_iterable( # ( super(Entity, alt)._children(cls, altscope=altscope) # for alt in alt_parents # self.get_alt_entities(altscope=altscope) # ))) # See https://docs.python.org/2/library/itertools.html#itertools.chain parent_entity_ids = [] for alt in alt_parents: for eid in super(Entity, alt)._children(cls, altscope=altscope): # Filter out duplicates if eid not in parent_entity_ids: parent_entity_ids.append(eid) # log.info("@@ Entity._children: coll_entity_ids %r, parent_entity_ids %r"%(coll_entity_ids, parent_entity_ids)) # if altscope == "all" and self._altparent: # parent_entity_ids = self._altparent._children(cls, altscope=altscope) for entity_id in [f for f in parent_entity_ids if f not in coll_entity_ids] + coll_entity_ids: if util.valid_id(entity_id, reserved_ok=True): yield entity_id return
def get_field(self, field_id): """ Retrieve identified field description field_id local identifier for the field to retrieve. returns a RecordField object for the identified field, or None. """ if not valid_id(field_id, reserved_ok=True): msg = "Collection %s get_field(%s) invalid id"%(self.get_id(), field_id) log.error(msg) # Construct and return a placeholder field ph_meta = ( { RDFS.CURIE.label: "(field error)" , ANNAL.CURIE.field_render_type: "_enum_render_type/Placeholder" , ANNAL.CURIE.field_value_mode: "_enum_value_mode/Value_direct" , ANNAL.CURIE.field_placement: "small:0,12" , ANNAL.CURIE.placeholder: "(Invalid field id: '%s')"%(field_id,) }) f = RecordField._child_init(self, "_placeholder") f.set_values(ph_meta) return f return self.cache_get_field(field_id)
def _children(self, cls, altparent=None): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. altparent is an alternative parent entity to be checked using the class's alternate relative path, or None if only potential child IDs of the current entity are returned. """ coll_dir, site_dir = self._child_dirs(cls, altparent) assert "%" not in coll_dir, "_entitypath/_entityaltpath template variable interpolation may be in filename part only" site_files = [] coll_files = [] if site_dir and os.path.isdir(site_dir): site_files = os.listdir(site_dir) if os.path.isdir(coll_dir): coll_files = os.listdir(coll_dir) for fil in [ f for f in site_files if f not in coll_files] + coll_files: if util.valid_id(fil): yield fil return
def _children(self, cls, altscope=None): """ Iterates over candidate child identifiers that are possible instances of an indicated class. The supplied class is used to determine a subdirectory to be scanned. cls is a subclass of Entity indicating the type of children to iterate over. altscope if supplied, indicates a scope other than the current entity to search for children. """ # log.info("@@ Entity._children: parent %s, altscope %s"%(self.get_id(), altscope)) coll_entity_ids = list(super(Entity, self)._children(cls, altscope=altscope)) alt_parents = self.get_alt_entities(altscope=altscope) site_entity_ids = list(itertools.chain.from_iterable( ( super(Entity, alt)._children(cls, altscope=altscope) for alt in self.get_alt_entities(altscope=altscope) ))) # if altscope == "all" and self._altparent: # site_entity_ids = self._altparent._children(cls, altscope=altscope) for entity_id in [f for f in site_entity_ids if f not in coll_entity_ids] + coll_entity_ids: if util.valid_id(entity_id): yield entity_id return
def default_view_context_data( entity_id=None, orig_id=None, coll_id="testcoll", type_id="testtype", type_ref=None, type_choices=None, type_ids=[], entity_label=None, entity_descr=None, view_label="Default record view", record_type="annal:EntityData", update="Entity", action=None, continuation_url=None ): """ Returns view context test data for entity presented using default view """ if entity_id: type_ref = value_or_default(type_ref, "_type/"+type_id if valid_id(type_id) else None ) entity_label = value_or_default(entity_label, '%s %s/%s/%s'%(update, coll_id, type_id, entity_id) ) entity_descr = value_or_default(entity_descr, '%s coll %s, type %s, entity %s'%(update, coll_id, type_id, entity_id) ) else: type_ref = type_ref or "" entity_label = value_or_default(entity_label, '%s data ... (%s/%s)'%(update, coll_id, type_id) ) entity_descr = value_or_default(entity_descr, '%s description ... (%s/%s)'%(update, coll_id, type_id) ) continuation_url = value_or_default(continuation_url, entitydata_list_type_url("testcoll", type_id) ) view_title = ( "%s - %s - Collection %s"%(entity_label, view_label, coll_id) if entity_label else "%s - Collection %s"%(view_label, coll_id) ) view_fields = ( [ context_field_row( get_bound_field("Entity_id", entity_id), # 0 (0,0) get_bound_field("Entity_type", type_ref, options=type_choices) # 1 (0,1) ) , context_field_row( get_bound_field("Entity_label", entity_label) # 2 (1,0) ) , context_field_row( get_bound_field("Entity_comment", entity_descr) # 3 (2,0) ) ]) context_dict = ( { 'title': view_title , 'heading': view_label , 'coll_id': coll_id , 'type_id': type_id , 'orig_id': orig_id , 'record_type': record_type , 'fields': view_fields , 'continuation_url': continuation_url }) if orig_id: context_dict['orig_id'] = orig_id elif entity_id and action != "new": context_dict['orig_id'] = entity_id if action: context_dict['action'] = action return context_dict
def entitydata_context_data( entity_id=None, orig_id=None, coll_id="testcoll", type_id="testtype", type_ids=[], action=None, update="Entity", view_label="Default record view" ): if entity_id: entity_label = '%s %s/%s/%s'%(update, coll_id, type_id, entity_id) entity_descr = '%s coll %s, type %s, entity %s'%(update, coll_id, type_id, entity_id) else: entity_label = '%s data ... (%s/%s)'%(update, coll_id, type_id) entity_descr = '%s description ... (%s/%s)'%(update, coll_id, type_id) context_dict = ( { 'title': "%s - %s - Collection %s"%(entity_label, view_label, coll_id) , 'heading': view_label , 'coll_id': 'testcoll' , 'type_id': 'testtype' , 'orig_id': 'orig_entity_id' , 'fields': [ context_field_row( { 'field_label': 'Id' , 'field_id': 'Entity_id' , 'field_name': 'entity_id' , 'field_render_type': 'EntityId' , 'field_placement': get_placement_classes('small:0,12;medium:0,6') , 'field_value_mode': 'Value_direct' , 'field_value_type': "annal:Slug" # , 'field_value': (Supplied separately) , 'options': [] }, { 'field_label': 'Type' , 'field_id': 'Entity_type' , 'field_name': 'entity_type' , 'field_render_type': 'EntityTypeId' , 'field_value_type': "annal:Slug" , 'field_placement': get_placement_classes('small:0,12;medium:6,6') , 'field_value_mode': 'Value_direct' # , 'field_value': (Supplied separately) , 'options': [] }) , context_field_row( { 'field_label': 'Label' , 'field_id': 'Entity_label' , 'field_name': 'Entity_label' , 'field_render_type': 'Text' , 'field_placement': get_placement_classes('small:0,12') , 'field_value_mode': 'Value_direct' , 'field_value_type': "annal:Text" , 'field_value': entity_label , 'options': [] }) , context_field_row( { 'field_label': 'Comment' , 'field_id': 'Entity_comment' , 'field_name': 'Entity_comment' , 'field_render_type': 'Markdown' , 'field_placement': get_placement_classes('small:0,12') , 'field_value_mode': 'Value_direct' , 'field_value_type': "annal:Richtext" , 'field_value': entity_descr , 'options': [] }) ] , 'continuation_url': entitydata_list_type_url("testcoll", type_id) }) if entity_id: context_dict['fields'][0]['row_field_descs'][0]['field_value'] = entity_id context_dict['fields'][0]['row_field_descs'][1]['field_value'] = "_type/"+type_id if valid_id(type_id) else None context_dict['orig_id'] = entity_id if orig_id: context_dict['orig_id'] = orig_id if action: context_dict['action'] = action return context_dict
def post(self, request): """ Process options to add or remove a collection in an Annalist site """ log.debug("site.post: %r" % (request.POST.lists())) collections = request.POST.getlist("select", []) coll_id = collections[0] if collections else "_" coll_ids = {'ids': ", ".join(collections)} perm_req = None perm_scope = None none_msg = None many_msg = None redirect_uri = None http_response = None # Process POST option if "view" in request.POST: # Collection data is considered part of configuration, hence CONFIG_PERMISSIONS: perm_req = CONFIG_PERMISSIONS["view"] # Use Collection or Site permissions: perm_scope = "all" none_msg = message.NO_COLLECTION_VIEW many_msg = message.MANY_COLLECTIONS_VIEW target_uri = self.view_uri("AnnalistEntityEditView", coll_id=layout.SITEDATA_ID, view_id="Collection_view", type_id="_coll", entity_id=coll_id, action="view") redirect_uri = uri_with_params( target_uri, {'continuation_url': self.continuation_here()}) elif "edit" in request.POST: perm_req = CONFIG_PERMISSIONS["edit"] perm_scope = "all" none_msg = message.NO_COLLECTION_EDIT many_msg = message.MANY_COLLECTIONS_EDIT target_uri = self.view_uri("AnnalistEntityEditView", coll_id=layout.SITEDATA_ID, view_id="Collection_view", type_id="_coll", entity_id=coll_id, action="edit") redirect_uri = uri_with_params( target_uri, {'continuation_url': self.continuation_here()}) elif "remove" in request.POST: perm_req = "DELETE_COLLECTION" perm_scope = "all" # Collection or site permissions none_msg = message.NO_COLLECTIONS_REMOVE elif "new" in request.POST: perm_req = "CREATE_COLLECTION" perm_scope = "site" # Site permission required new_id = request.POST["new_id"] new_label = request.POST["new_label"] # Common checks if none_msg and not collections: http_response = self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=none_msg, info_head=message.NO_ACTION_PERFORMED) elif many_msg and len(collections) > 1: http_response = self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=many_msg % coll_ids, info_head=message.NO_ACTION_PERFORMED) elif perm_req: if perm_scope == "all": # Check collections for permissions for cid in collections: if http_response is None: site = self.site(host=self.get_request_host()) sitedata = self.site_data() coll = Collection.load(site, cid, altscope="site") http_response = ( self.authorize("ADMIN", coll) and # Either of these... self.authorize(perm_req, coll)) coll = None else: # Check site only for permissions http_response = (self.authorize("ADMIN", None) and self.authorize(perm_req, None)) if http_response is not None: return http_response # Perform selected option if redirect_uri: log.info("Redirect to %s" % redirect_uri) return HttpResponseRedirect(redirect_uri) if "remove" in request.POST: if layout.SITEDATA_ID in collections: log.warning("Attempt to delete site data collection %(ids)s" % (coll_ids)) http_response = self.error( self.error403values(scope="DELETE_SITE")) else: http_response = ConfirmView.render_form( request, action_description=message.REMOVE_COLLECTIONS % coll_ids, action_params=request.POST, confirmed_action_uri=self.view_uri( 'AnnalistSiteActionView'), cancel_action_uri=self.view_uri('AnnalistSiteView'), title=self.site_data()["title"]) return http_response if "new" in request.POST: log.info("New collection %s: %s" % (new_id, new_label)) error_message = None if not new_id: error_message = message.MISSING_COLLECTION_ID elif not util.valid_id(new_id): error_message = message.INVALID_COLLECTION_ID % { 'coll_id': new_id } if error_message: return self.redirect_error(self.view_uri("AnnalistSiteView"), error_message=error_message) coll_meta = ({RDFS.CURIE.label: new_label, RDFS.CURIE.comment: ""}) # Add collection coll = self.site().add_collection(new_id, coll_meta) coll.generate_coll_jsonld_context() user = self.request.user user_id = user.username user_uri = "mailto:" + user.email user_name = "%s %s" % (user.first_name, user.last_name) user_description = "User %s: permissions for %s in collection %s" % ( user_id, user_name, new_id) coll.create_user_permissions(user_id, user_uri, user_name, user_description, user_permissions=[ "VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", "ADMIN" ]) return self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=message.CREATED_COLLECTION_ID % {'coll_id': new_id}) # elif "remove" in request.POST: # collections = request.POST.getlist("select", []) # if collections: # # Check authorization # if layout.SITEDATA_ID in collections: # log.warning("Attempt to delete site data collection %r"%(collections)) # auth_required = self.error(self.error403values(scope="DELETE_SITE")) # else: # auth_required = ( # self.authorize("ADMIN", None) and # either of these.. # self.authorize("DELETE_COLLECTION", None) # ) # return ( # # Get user to confirm action before actually doing it # auth_required or # ConfirmView.render_form(request, # action_description= message.REMOVE_COLLECTIONS%{'ids': ", ".join(collections)}, # action_params= request.POST, # confirmed_action_uri= self.view_uri('AnnalistSiteActionView'), # cancel_action_uri= self.view_uri('AnnalistSiteView'), # title= self.site_data()["title"] # ) # ) # else: # return self.redirect_info( # self.view_uri("AnnalistSiteView"), # info_message=message.NO_COLLECTIONS_REMOVE, info_head=message.NO_ACTION_PERFORMED # ) # if "new" in request.POST: # # Create new collection with name and label supplied # new_id = request.POST["new_id"] # new_label = request.POST["new_label"] # log.debug("New collection %s: %s"%(new_id, new_label)) # if not new_id: # return self.redirect_error( # self.view_uri("AnnalistSiteView"), # error_message=message.MISSING_COLLECTION_ID # ) # if not util.valid_id(new_id): # return self.redirect_error( # self.view_uri("AnnalistSiteView"), # error_message=message.INVALID_COLLECTION_ID%{'coll_id': new_id} # ) # # Create new collection with name and label supplied # auth_required = ( # self.authorize("ADMIN", None) and # either of these.. # self.authorize("CREATE_COLLECTION", None) # ) # if auth_required: # return auth_required # coll_meta = ( # { RDFS.CURIE.label: new_label # , RDFS.CURIE.comment: "" # }) # coll = self.site().add_collection(new_id, coll_meta) # # Generate initial context # coll.generate_coll_jsonld_context() # # Create full permissions in new collection for creating user # user = self.request.user # user_id = user.username # user_uri = "mailto:"+user.email # user_name = "%s %s"%(user.first_name, user.last_name) # user_description = "User %s: permissions for %s in collection %s"%(user_id, user_name, new_id) # coll.create_user_permissions( # user_id, user_uri, # user_name, user_description, # user_permissions=["VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", "ADMIN"] # ) # return self.redirect_info( # self.view_uri("AnnalistSiteView"), # info_message=message.CREATED_COLLECTION_ID%{'coll_id': new_id} # ) log.warning("Invalid POST request: %r" % (request.POST.lists())) return self.error(self.error400values())
def entitydata_context_data(entity_id=None, orig_id=None, coll_id="testcoll", type_id="testtype", type_ids=[], action=None, update="Entity", view_label="Default record view"): if entity_id: entity_label = '%s %s/%s/%s' % (update, coll_id, type_id, entity_id) entity_descr = '%s coll %s, type %s, entity %s' % (update, coll_id, type_id, entity_id) else: entity_label = '%s data ... (%s/%s)' % (update, coll_id, type_id) entity_descr = '%s description ... (%s/%s)' % (update, coll_id, type_id) context_dict = ({ 'title': "%s - %s - Collection %s" % (entity_label, view_label, coll_id), 'heading': view_label, 'coll_id': 'testcoll', 'type_id': 'testtype', 'orig_id': 'orig_entity_id', 'fields': [ context_field_row( { 'field_label': 'Id', 'field_id': 'Entity_id', 'field_name': 'entity_id', 'field_render_type': 'EntityId', 'field_placement': get_placement_classes('small:0,12;medium:0,6'), 'field_value_mode': 'Value_direct', 'field_value_type': "annal:Slug" # , 'field_value': (Supplied separately) , 'options': [] }, { 'field_label': 'Type', 'field_id': 'Entity_type', 'field_name': 'entity_type', 'field_render_type': 'EntityTypeId', 'field_value_type': "annal:Slug", 'field_placement': get_placement_classes('small:0,12;medium:6,6'), 'field_value_mode': 'Value_direct' # , 'field_value': (Supplied separately) , 'options': [] }), context_field_row({ 'field_label': 'Label', 'field_id': 'Entity_label', 'field_name': 'Entity_label', 'field_render_type': 'Text', 'field_placement': get_placement_classes('small:0,12'), 'field_value_mode': 'Value_direct', 'field_value_type': "annal:Text", 'field_value': entity_label, 'options': [] }), context_field_row({ 'field_label': 'Comment', 'field_id': 'Entity_comment', 'field_name': 'Entity_comment', 'field_render_type': 'Markdown', 'field_placement': get_placement_classes('small:0,12'), 'field_value_mode': 'Value_direct', 'field_value_type': "annal:Richtext", 'field_value': entity_descr, 'options': [] }) ], 'continuation_url': entitydata_list_type_url("testcoll", type_id) }) if entity_id: context_dict['fields'][0]['row_field_descs'][0][ 'field_value'] = entity_id context_dict['fields'][0]['row_field_descs'][1][ 'field_value'] = "_type/" + type_id if valid_id(type_id) else None context_dict['orig_id'] = entity_id if orig_id: context_dict['orig_id'] = orig_id if action: context_dict['action'] = action return context_dict
def post(self, request): """ Process options to add or remove a collection in an Annalist site """ log.debug("site.post: %r"%(request.POST.lists())) collections = request.POST.getlist("select", []) coll_id = collections[0] if collections else "_" coll_ids = {'ids': ", ".join(collections)} perm_req = None perm_scope = None none_msg = None many_msg = None redirect_uri = None http_response = None # Process POST option if "view" in request.POST: # Collection data is considered part of configuration, hence CONFIG_PERMISSIONS: perm_req = CONFIG_PERMISSIONS["view"] # Use Collection or Site permissions: perm_scope = "all" none_msg = message.NO_COLLECTION_VIEW many_msg = message.MANY_COLLECTIONS_VIEW target_uri = self.view_uri("AnnalistEntityEditView", coll_id=layout.SITEDATA_ID, view_id="Collection_view", type_id="_coll", entity_id=coll_id, action="view" ) redirect_uri = uri_with_params( target_uri, {'continuation_url': self.continuation_here()} ) elif "edit" in request.POST: perm_req = CONFIG_PERMISSIONS["edit"] perm_scope = "all" none_msg = message.NO_COLLECTION_EDIT many_msg = message.MANY_COLLECTIONS_EDIT target_uri = self.view_uri("AnnalistEntityEditView", coll_id=layout.SITEDATA_ID, view_id="Collection_view", type_id="_coll", entity_id=coll_id, action="edit" ) redirect_uri = uri_with_params( target_uri, {'continuation_url': self.continuation_here()} ) elif "remove" in request.POST: perm_req = "DELETE_COLLECTION" perm_scope = "all" # Collection or site permissions none_msg = message.NO_COLLECTIONS_REMOVE elif "new" in request.POST: perm_req = "CREATE_COLLECTION" perm_scope = "site" # Site permission required new_id = request.POST["new_id"] new_label = request.POST["new_label"] # Common checks if none_msg and not collections: http_response = self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=none_msg, info_head=message.NO_ACTION_PERFORMED ) elif many_msg and len(collections) > 1: http_response = self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=many_msg%coll_ids, info_head=message.NO_ACTION_PERFORMED ) elif perm_req: if perm_scope == "all": # Check collections for permissions for cid in collections: if http_response is None: site = self.site(host=self.get_request_host()) sitedata = self.site_data() coll = Collection.load(site, cid, altscope="site") http_response = ( self.authorize("ADMIN", coll) and # Either of these... self.authorize(perm_req, coll) ) coll = None else: # Check site only for permissions http_response = ( self.authorize("ADMIN", None) and self.authorize(perm_req, None) ) if http_response is not None: return http_response # Perform selected option if redirect_uri: log.info("Redirect to %s"%redirect_uri) return HttpResponseRedirect(redirect_uri) if "remove" in request.POST: if layout.SITEDATA_ID in collections: log.warning("Attempt to delete site data collection %(ids)s"%(coll_ids)) http_response = self.error(self.error403values(scope="DELETE_SITE")) else: http_response = ConfirmView.render_form(request, action_description= message.REMOVE_COLLECTIONS%coll_ids, action_params= request.POST, confirmed_action_uri= self.view_uri('AnnalistSiteActionView'), cancel_action_uri= self.view_uri('AnnalistSiteView'), title= self.site_data()["title"] ) return http_response if "new" in request.POST: log.info("New collection %s: %s"%(new_id, new_label)) error_message = None if not new_id: error_message = message.MISSING_COLLECTION_ID elif not util.valid_id(new_id): error_message = message.INVALID_COLLECTION_ID%{'coll_id': new_id} if error_message: return self.redirect_error( self.view_uri("AnnalistSiteView"), error_message=error_message ) coll_meta = ( { RDFS.CURIE.label: new_label , RDFS.CURIE.comment: "" }) # Add collection coll = self.site().add_collection(new_id, coll_meta) coll.generate_coll_jsonld_context() user = self.request.user user_id = user.username user_uri = "mailto:"+user.email user_name = "%s %s"%(user.first_name, user.last_name) user_description = "User %s: permissions for %s in collection %s"%(user_id, user_name, new_id) coll.create_user_permissions( user_id, user_uri, user_name, user_description, user_permissions=["VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", "ADMIN"] ) return self.redirect_info( self.view_uri("AnnalistSiteView"), info_message=message.CREATED_COLLECTION_ID%{'coll_id': new_id} ) # elif "remove" in request.POST: # collections = request.POST.getlist("select", []) # if collections: # # Check authorization # if layout.SITEDATA_ID in collections: # log.warning("Attempt to delete site data collection %r"%(collections)) # auth_required = self.error(self.error403values(scope="DELETE_SITE")) # else: # auth_required = ( # self.authorize("ADMIN", None) and # either of these.. # self.authorize("DELETE_COLLECTION", None) # ) # return ( # # Get user to confirm action before actually doing it # auth_required or # ConfirmView.render_form(request, # action_description= message.REMOVE_COLLECTIONS%{'ids': ", ".join(collections)}, # action_params= request.POST, # confirmed_action_uri= self.view_uri('AnnalistSiteActionView'), # cancel_action_uri= self.view_uri('AnnalistSiteView'), # title= self.site_data()["title"] # ) # ) # else: # return self.redirect_info( # self.view_uri("AnnalistSiteView"), # info_message=message.NO_COLLECTIONS_REMOVE, info_head=message.NO_ACTION_PERFORMED # ) # if "new" in request.POST: # # Create new collection with name and label supplied # new_id = request.POST["new_id"] # new_label = request.POST["new_label"] # log.debug("New collection %s: %s"%(new_id, new_label)) # if not new_id: # return self.redirect_error( # self.view_uri("AnnalistSiteView"), # error_message=message.MISSING_COLLECTION_ID # ) # if not util.valid_id(new_id): # return self.redirect_error( # self.view_uri("AnnalistSiteView"), # error_message=message.INVALID_COLLECTION_ID%{'coll_id': new_id} # ) # # Create new collection with name and label supplied # auth_required = ( # self.authorize("ADMIN", None) and # either of these.. # self.authorize("CREATE_COLLECTION", None) # ) # if auth_required: # return auth_required # coll_meta = ( # { RDFS.CURIE.label: new_label # , RDFS.CURIE.comment: "" # }) # coll = self.site().add_collection(new_id, coll_meta) # # Generate initial context # coll.generate_coll_jsonld_context() # # Create full permissions in new collection for creating user # user = self.request.user # user_id = user.username # user_uri = "mailto:"+user.email # user_name = "%s %s"%(user.first_name, user.last_name) # user_description = "User %s: permissions for %s in collection %s"%(user_id, user_name, new_id) # coll.create_user_permissions( # user_id, user_uri, # user_name, user_description, # user_permissions=["VIEW", "CREATE", "UPDATE", "DELETE", "CONFIG", "ADMIN"] # ) # return self.redirect_info( # self.view_uri("AnnalistSiteView"), # info_message=message.CREATED_COLLECTION_ID%{'coll_id': new_id} # ) log.warning("Invalid POST request: %r"%(request.POST.lists())) return self.error(self.error400values())
def entitydata_context_data(entity_id=None, orig_id=None, type_id="testtype", type_ids=[], action=None, update="Entity"): context_dict = ({ 'title': "Collection testcoll", 'coll_id': 'testcoll', 'type_id': 'testtype', 'orig_id': 'orig_entity_id', 'fields': [ { 'field_label': 'Id', 'field_id': 'Entity_id', 'field_name': 'entity_id', 'field_render_type': 'EntityId', 'field_placement': get_placement_classes('small:0,12;medium:0,6'), 'field_value_type': 'annal:Slug' # , 'field_value': (Supplied separately) , 'options': [] }, { 'field_label': 'Type', 'field_id': 'Entity_type', 'field_name': 'entity_type', 'field_render_type': 'EntityTypeId', 'field_placement': get_placement_classes('small:0,12;medium:6,6'), 'field_value_type': 'annal:Slug' # , 'field_value': (Supplied separately) , 'options': [] }, { 'field_label': 'Label', 'field_id': 'Entity_label', 'field_name': 'Entity_label', 'field_render_type': 'Text', 'field_placement': get_placement_classes('small:0,12'), 'field_value_type': 'annal:Text', 'field_value': '%s data ... (testcoll/testtype)' % (update), 'options': [] }, { 'field_label': 'Comment', 'field_id': 'Entity_comment', 'field_name': 'Entity_comment', 'field_render_type': 'Textarea', 'field_placement': get_placement_classes('small:0,12'), 'field_value_type': 'annal:Longtext', 'field_value': '%s description ... (testcoll/testtype)' % (update), 'options': [] } ], 'continuation_url': entitydata_list_type_url("testcoll", type_id) }) if entity_id: context_dict['fields'][0]['field_value'] = entity_id context_dict['fields'][1]['field_value'] = type_id if valid_id( type_id) else None context_dict['fields'][2][ 'field_value'] = '%s testcoll/testtype/%s' % (update, entity_id) context_dict['fields'][3][ 'field_value'] = '%s coll testcoll, type testtype, entity %s' % ( update, entity_id) context_dict['orig_id'] = entity_id if orig_id: context_dict['orig_id'] = orig_id if action: context_dict['action'] = action return context_dict