예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
파일: generic.py 프로젝트: gklyne/annalist
    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
예제 #7
0
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)
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
 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
예제 #11
0
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)
예제 #12
0
 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, ))
예제 #13
0
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)
예제 #14
0
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)
예제 #15
0
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)
예제 #16
0
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)
예제 #17
0
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)
예제 #18
0
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)
예제 #19
0
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)
예제 #20
0
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)
예제 #21
0
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)
예제 #22
0
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)
예제 #23
0
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)
예제 #24
0
    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)
예제 #25
0
    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)
예제 #26
0
    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)
예제 #27
0
    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
예제 #28
0
    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
예제 #29
0
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)
예제 #30
0
    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
예제 #31
0
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)
예제 #32
0
    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
예제 #33
0
    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
예제 #34
0
    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
예제 #35
0
파일: entity.py 프로젝트: gklyne/annalist
    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
예제 #36
0
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)
예제 #37
0
 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,))
예제 #38
0
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)
예제 #39
0
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)
예제 #40
0
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)
예제 #41
0
    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
예제 #42
0
    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
예제 #43
0
    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
예제 #44
0
파일: entity.py 프로젝트: gklyne/annalist
    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
예제 #45
0
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)
예제 #46
0
파일: entity.py 프로젝트: gklyne/annalist
    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
예제 #47
0
    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)
예제 #48
0
    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
예제 #49
0
    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
예제 #50
0
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
예제 #51
0
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
예제 #52
0
파일: site.py 프로젝트: rklyne/annalist
    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
예제 #54
0
파일: site.py 프로젝트: juandesant/annalist
    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())
예제 #55
0
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