Exemple #1
0
 def _resolve_owner(self, req, cursor):
     """
     Get the DB owner from the req.
     """
     raw_owner = req.get_param('ownerId')
     if raw_owner:
         source_writer.upsert_user(
             {
                 'name': raw_owner,
                 'source': req.env['wsgi.identity'].source_id
             },
             cursor=cursor)
         owner = cursor.fetchone()[0]
     else:
         owner = req.env['wsgi.identity'].user_id
     return owner
Exemple #2
0
def install_base_data():
    """
    Install the application's base data to the database.
    """
    db_connection = get_connection(
        isolation_level=ISOLATION_LEVEL_READ_COMMITTED
    )
    with db_connection, db_connection.cursor() as cursor:
        for namespace, predicates in rels.RELATIONS.items():
            # Default relationship data.
            relations_writer.upsert_namespace(namespace, cursor=cursor)
            namespace_id, = cursor.fetchone()
            for predicate in predicates:
                relations_writer.upsert_predicate(
                    {'namespace': namespace_id, 'predicate': predicate},
                    cursor=cursor
                )

            # Default user data.
            source_id = source_writer.upsert_source(
                _config['self']['source'],
                cursor=cursor
            ).fetchone()['id']
            user_id = source_writer.upsert_user(
                {'source': source_id, 'name': _config['self']['username']},
                cursor=cursor
            ).fetchone()['id']

            # Default namespace data.
            ns_map = {}
            for namespace in BASE_NAMESPACES:
                ns_map[namespace] = object_writer.upsert_namespace(
                    namespace,
                    cursor=cursor
                ).fetchone()['id']

            # Default object data.
            for obj in BASE_OBJECTS:
                namespace, pid_id = utils.break_pid(obj)
                obj_info = object_writer.upsert_object(
                    {
                        'namespace': ns_map[namespace],
                        'owner': user_id,
                        'pid_id': pid_id,
                    },
                    cursor=cursor
                ).fetchone()
                # Add DC DS as Fedora objects have DC and Islandora expects it.
                foxml.create_default_dc_ds(obj_info['id'], obj, cursor=cursor)

    db_connection.close()
    logger.info('Installed base data.')
Exemple #3
0
def authenticate(identity):
    """
    Check if the given identity is valid, and set the relevant roles.

    Likely used with talons.auth.external.Authenticator.

    Parameters:
        identity: An talons.auth.interfaces.Identity instance.

    Returns:
        A boolean indicating if the given identity authenticates.
    """
    if not hasattr(identity, 'site') or identity.site is None:
        logger.debug('Got request without site token.')
        return None

    if identity.login == 'anonymous' and identity.key == 'anonymous':
        # Quick anonymous check.
        identity.drupal_user_id = 0
        identity.roles.add('anonymous user')

        cursor = source_reader.source_id(identity.site)
        if not cursor.rowcount:
            sources.upsert_source(identity.site, cursor=cursor)
        identity.source_id = cursor.fetchone()['id']
        cursor.close()

        logger.debug('Anonymous user logged in from %s.', identity.site)
        return True

    # Grab the config for the selected site.
    try:
        db_info = _config['drupal_sites'][identity.site]['database']
    except KeyError:
        logger.info('Site not in configuration: %s.', identity.site)
        return False
    query = db_info['query'] if 'query' in db_info else '''SELECT DISTINCT u.uid, r.name
FROM (
  users u
    LEFT JOIN
  users_roles ON u.uid=users_roles.uid
  )
    LEFT JOIN role r ON r.rid=users_roles.rid
WHERE u.name=%s AND u.pass=%s'''

    try:
        # Get a DB connection and cursor for the selected site.
        conn = get_auth_connection(identity.site)
        auth_cursor = conn.cursor()

        # Check the credentials against the selected site (using provided
        # query or a default).
        auth_cursor.execute(query, (identity.login, identity.key))

        if auth_cursor.rowcount > 0:
            identity.drupal_user_id = None
            for uid, role in auth_cursor:
                if identity.drupal_user_id is None:
                    identity.drupal_user_id = uid
                identity.roles.add(role)
            identity.roles.add('authenticated user')
            logger.info('Authenticated %s:%s with roles: %s', identity.site,
                        identity.login, identity.roles)
            with get_connection() as connection:
                with connection.cursor() as cursor:
                    # Most requests won't be from new users.
                    user_info = source_reader.source_and_user_from_raw(
                        identity.site,
                        identity.login,
                        cursor=cursor
                    ).fetchone()
                    if user_info is not None:
                        identity.source_id = user_info['source_id']
                        identity.user_id = user_info['user_id']
                    else:
                        sources.upsert_source(identity.site, cursor=cursor)
                        identity.source_id = cursor.fetchone()['id']
                        sources.upsert_user(
                            {'name': identity.login,
                             'source': identity.source_id},
                            cursor=cursor
                        )
                        identity.user_id = cursor.fetchone()['id']

            return True
        else:
            logger.info('Failed to authenticate %s:%s.', identity.site,
                        identity.login)
            return False
    except:
        logger.exception('Error while authenticating with Drupal credentials.')
    finally:
        try:
            auth_cursor.close()
        except UnboundLocalError:
            logger.debug('Failed before allocating DB cursor.')
        try:
            conn.close()
        except UnboundLocalError:
            logger.debug('Failed before creating DB connection.')
    return False
def _rdf_object_from_element(predicate, relation, source, cursor):
    """
    Pull out an RDF object form an RDF XML element.

    Returns:
        A tuple of:
        - the resolved RDF object
        - the type; one of:
            - OBJECT_RDF_OBJECT
            - DATASTREAM_RDF_OBJECT
            - USER_RDF_OBJECT
            - ROLE_RDF_OBJECT

    Raises:
        ReferencedObjectDoesNotExistError: If the value appeared to
            reference a repo object, but it could not be found.
        ValueError: If the value could not be resolved in general.
    """
    user_tags = frozenset([
        (relations.ISLANDORA_RELS_EXT_NAMESPACE,
         relations.IS_VIEWABLE_BY_USER_PREDICATE),
        (relations.ISLANDORA_RELS_INT_NAMESPACE,
         relations.IS_VIEWABLE_BY_USER_PREDICATE),
        (relations.ISLANDORA_RELS_EXT_NAMESPACE,
         relations.IS_MANAGEABLE_BY_USER_PREDICATE),
        (relations.ISLANDORA_RELS_INT_NAMESPACE,
         relations.IS_MANAGEABLE_BY_USER_PREDICATE),
    ])
    role_tags = frozenset([
        (relations.ISLANDORA_RELS_EXT_NAMESPACE,
         relations.IS_VIEWABLE_BY_ROLE_PREDICATE),
        (relations.ISLANDORA_RELS_INT_NAMESPACE,
         relations.IS_VIEWABLE_BY_ROLE_PREDICATE),
        (relations.ISLANDORA_RELS_EXT_NAMESPACE,
         relations.IS_MANAGEABLE_BY_ROLE_PREDICATE),
        (relations.ISLANDORA_RELS_INT_NAMESPACE,
         relations.IS_MANAGEABLE_BY_ROLE_PREDICATE),
    ])
    if relation.text:
        if predicate in user_tags:
            cursor = source_writer.upsert_user({'name': relation.text,
                                                'source': source},
                                               cursor=cursor)
            return (cursor.fetchone()['id'], USER_RDF_OBJECT)
        elif predicate in role_tags:
            cursor = source_writer.upsert_role({'role': relation.text,
                                                'source': source},
                                               cursor=cursor)
            return (cursor.fetchone()['id'], ROLE_RDF_OBJECT)
        else:
            logger.debug(('No dereferencing performed for relationship %s for '
                          'value %s.'), predicate, relation.text)
            return (relation.text, RAW_RDF_OBJECT)
    else:
        resource = relation.attrib['{{{}}}resource'.format(RDF_NAMESPACE)]

        pid = pid_from_fedora_uri(resource)
        dsid = dsid_from_fedora_uri(resource)
        if pid:
            cursor = object_reader.object_info_from_raw(pid, cursor=cursor)
            try:
                object_id = cursor.fetchone()['id']
            except TypeError as e:
                logger.error('Referenced object %s does not exist.', pid)
                raise ReferencedObjectDoesNotExistError(pid) from e
            else:
                if dsid:
                    try:
                        cursor = datastream_reader.datastream_id(
                            {'object_id': object_id, 'dsid': dsid},
                            cursor=cursor
                        )
                        return (cursor.fetchone()['id'], DATASTREAM_RDF_OBJECT)
                    except TypeError as e:
                        logger.error(
                            'Referenced datastream %s/%s does not exist.',
                            pid,
                            dsid
                        )
                        raise ReferencedDatastreamDoesNotExist(pid,
                                                               dsid) from e

                return (object_id, OBJECT_RDF_OBJECT)

        raise ValueError('Failed to resolve relationship %s with value %s.',
                         predicate, resource)
Exemple #5
0
    def end(self, tag):
        """
        Internalize data at the end of tags.

        Raises:
            ObjectExistsError: The object already exists.
        """
        # Create the object.
        if tag == '{{{0}}}objectProperties'.format(FOXML_NAMESPACE):
            object_db_info = {}

            raw_namespace, object_db_info['pid_id'] = utils.break_pid(
                self.object_info['PID'])
            object_db_info['namespace'] = cache.repo_object_namespace_id(
                raw_namespace, cursor=self.cursor)

            raw_log = 'Object created through FOXML import.'
            upsert_log(raw_log, cursor=self.cursor)
            object_db_info['log'] = self.cursor.fetchone()[0]

            try:
                raw_owner = self.object_info['{}{}'.format(
                    relations.FEDORA_MODEL_NAMESPACE,
                    relations.OWNER_PREDICATE)]
            except KeyError:
                pass
            else:
                upsert_user({
                    'name': raw_owner,
                    'source': self.source
                },
                            cursor=self.cursor)
                object_db_info['owner'] = self.cursor.fetchone()[0]

            try:
                object_db_info['created'] = self.object_info['{}{}'.format(
                    relations.FEDORA_MODEL_NAMESPACE,
                    relations.CREATED_DATE_PREDICATE)]
            except KeyError:
                pass

            try:
                object_db_info['modified'] = self.object_info['{}{}'.format(
                    relations.FEDORA_VIEW_NAMESPACE,
                    relations.LAST_MODIFIED_DATE_PREDICATE)]
            except KeyError:
                pass

            try:
                object_db_info['state'] = OBJECT_STATE_LABEL_MAP[
                    self.object_info['{}{}'.format(
                        relations.FEDORA_MODEL_NAMESPACE,
                        relations.STATE_PREDICATE)]]
            except KeyError:
                try:
                    object_db_info['state'] = self.object_info['{}{}'.format(
                        relations.FEDORA_MODEL_NAMESPACE,
                        relations.STATE_PREDICATE)]
                except KeyError:
                    pass

            object_db_info['label'] = self.object_info['{}{}'.format(
                relations.FEDORA_MODEL_NAMESPACE, relations.LABEL_PREDICATE)]

            object_writer.jump_pids(object_db_info['namespace'],
                                    object_db_info['pid_id'],
                                    cursor=self.cursor)
            try:
                object_writer.write_object(object_db_info, cursor=self.cursor)
            except IntegrityError:
                raise ObjectExistsError(self.object_info['PID'])
            self.object_id = self.cursor.fetchone()[0]

        # Stash content.
        if (tag == '{{{0}}}xmlContent'.format(FOXML_NAMESPACE)
                and self.dsid != 'AUDIT'):
            base_element = self.tree_builder.close()
            xml_ds = BytesIO(etree.tostring(base_element))
            self.ds_info[self.dsid]['versions'][-1]['data'] = xml_ds
            self.tree_builder = None
        elif self.tree_builder is not None:
            self.tree_builder.end(tag)

        if tag == '{{{0}}}binaryContent'.format(FOXML_NAMESPACE):
            self.ds_file.seek(0)
            decoded_file = utils.SpooledTemporaryFile()
            base64.decode(self.ds_file, decoded_file)
            self.ds_file.close()
            self.ds_file = None
            decoded_file.seek(0)
            self.ds_info[self.dsid]['versions'][-1]['data'] = decoded_file

        # Store old and current DSs, passing off RELS/DC.
        if (tag == '{{{0}}}datastream'.format(FOXML_NAMESPACE)
                and self.dsid != 'AUDIT'):
            last_ds = self.ds_info[self.dsid]['versions'].pop()
            last_ds.update(self.ds_info[self.dsid])
            try:
                last_ds['actually_created'] = (
                    self.ds_info[self.dsid]['versions'][0]['CREATED'])
            except IndexError:
                try:
                    last_ds['actually_created'] = last_ds['CREATED']
                except KeyError:
                    last_ds['actually_created'] = None
                    last_ds['CREATED'] = None

            # Populate relations.
            if self.dsid == 'DC':
                internalize_rels_dc(last_ds['data'],
                                    self.object_id,
                                    purge=False,
                                    cursor=self.cursor)
                self.cursor.fetchall()
            elif self.dsid == 'RELS-EXT':
                internalize_rels_ext(last_ds['data'],
                                     self.object_id,
                                     self.source,
                                     purge=False,
                                     cursor=self.cursor)
                self.cursor.fetchall()
            elif self.dsid == 'RELS-INT':
                self.rels_int = etree.parse(last_ds['data'])
                last_ds['data'].seek(0)

            # Write DS.
            ds_db_id = self._create_ds(last_ds)

            # Write old DSs.
            for ds_version in self.ds_info[self.dsid]['versions']:
                ds_version.update(self.ds_info[self.dsid])
                ds_version['datastream'] = ds_db_id
                ds_version['actually_created'] = None
                self._create_ds(ds_version, old=True)

            # Reset current datastream.
            self.dsid = None