Пример #1
0
def import_organisations(file):
    """Import organisations from JSON file."""
    click.secho('Importing organisations from {file}'.format(file=file.name))

    indexer = OrganisationIndexer()

    for record in json.load(file):
        try:
            # Check existence in DB
            db_record = OrganisationRecord.get_record_by_pid(record['code'])

            if db_record:
                raise ClickException('Record already exists in DB')

            # Register record to DB
            db_record = OrganisationRecord.create(record)
            db.session.commit()

            indexer.index(db_record)
        except Exception as error:
            click.secho(
                'Organisation {org} could not be imported: {error}'.format(
                    org=record, error=str(error)),
                fg='red')

    click.secho('Finished', fg='green')
Пример #2
0
def test_get_or_create(organisation):
    """Test get or create an organisation."""
    # Existing organisation
    organisation = OrganisationRecord.get_or_create('org', 'Organisation')
    assert organisation['pid'] == 'org'
    assert organisation['name'] == 'org'

    # New organisation
    organisation = OrganisationRecord.get_or_create('new-org', 'Organisation')
    assert organisation['pid'] == 'new-org'
    assert organisation['name'] == 'Organisation'
Пример #3
0
def get_organisations(record):
    """Get list of organisations with full data.

    :param record: Record object.
    """
    organisations = []
    for organisation in record.get('organisation', []):
        organisation_pid = OrganisationRecord.get_pid_by_ref_link(
            organisation['$ref']) if organisation.get(
                '$ref') else organisation['pid']
        organisations.append(
            OrganisationRecord.get_record_by_pid(organisation_pid))

    return organisations
Пример #4
0
    def _make_organisation(code):
        data = {
            'code': code,
            'name': code,
            'isShared': True,
            'isDedicated': False
        }

        record = OrganisationRecord.get_record_by_pid(code)

        if not record:
            record = OrganisationRecord.create(data, dbcommit=True)
            record.reindex()
            db.session.commit()

        return record
Пример #5
0
    def post_process_serialize_search(self, results, pid_fetcher):
        """Post process the search results."""
        if current_user_record:
            # Remove organisation facet for non super users
            if not current_user_record.is_superuser:
                results['aggregations'].pop('organisation', {})

            # Remove user facet for non moderators users
            if not current_user_record.is_moderator:
                results['aggregations'].pop('user', {})

        # Add organisation name
        for org_term in results.get('aggregations',
                                    {}).get('organisation',
                                            {}).get('buckets', []):
            organisation = OrganisationRecord.get_record_by_pid(
                org_term['key'])
            if organisation:
                org_term['name'] = organisation['name']

        # Add user name
        for org_term in results.get('aggregations',
                                    {}).get('user', {}).get('buckets', []):
            user = UserRecord.get_record_by_pid(org_term['key'])
            if user:
                org_term['name'] = '{last_name}, {first_name}'.format(
                    last_name=user['last_name'], first_name=user['first_name'])

        return super(JSONSerializer,
                     self).post_process_serialize_search(results, pid_fetcher)
Пример #6
0
def test_get_organisation_by_user(user):
    """Test getting organisation by user."""
    # No user passed
    organisation = OrganisationRecord.get_organisation_by_user(None)
    assert not organisation

    # OK
    organisation = OrganisationRecord.get_organisation_by_user(user)
    assert 'code' in organisation
    assert organisation['code'] == 'org'

    user.pop('organisation')

    # User has no organisation
    organisation = OrganisationRecord.get_organisation_by_user(user)
    assert not organisation
Пример #7
0
    def delete(cls, user, record):
        """Delete permission check.

        :param user: Logged user.
        :param recor: Record to check.
        :returns: True is action can be done.
        """
        # At least for admin logged users.
        if not current_user_record or not current_user_record.is_admin:
            return False

        # Superuser is allowed
        if current_user_record.is_superuser:
            return True

        # Cannot delete himself
        if current_user_record['pid'] == record['pid']:
            return False

        if not record.get('organisation'):
            return False

        # For admin read is only for logged user organisation
        if record['organisation'].get('$ref'):
            return current_organisation[
                'pid'] == OrganisationRecord.get_pid_by_ref_link(
                    record['organisation']['$ref'])

        return current_organisation['pid'] == record['organisation']['pid']
Пример #8
0
    def aggregations(self):
        """Get the search result aggregations."""
        aggregations = self._results.aggregations.to_dict()

        if current_user_record:
            # Remove organisation facet for non super users
            if not current_user_record.is_superuser:
                aggregations.pop('organisation', {})

            # Remove user facet for non moderators users
            if not current_user_record.is_moderator:
                aggregations.pop('user', {})

        # Add organisation name
        for org_term in aggregations.get('organisation',
                                         {}).get('buckets', []):
            organisation = OrganisationRecord.get_record_by_pid(
                org_term['key'])
            if organisation:
                org_term['name'] = organisation['name']

        # Add user name
        for org_term in aggregations.get('user', {}).get('buckets', []):
            user = UserRecord.get_record_by_pid(org_term['key'])
            if user:
                org_term['name'] = '{last_name}, {first_name}'.format(
                    last_name=user['last_name'], first_name=user['first_name'])

        return aggregations
Пример #9
0
    def post_process_serialize_search(self, results, pid_fetcher):
        """Post process the search results."""
        view = request.args.get('view')

        if results['aggregations'].get('year'):
            results['aggregations']['year']['type'] = 'range'
            results['aggregations']['year']['config'] = {
                'min': 1950,
                'max': int(datetime.now().year),
                'step': 1
            }

        # Add organisation name
        for org_term in results.get('aggregations',
                                    {}).get('organisation',
                                            {}).get('buckets', []):
            organisation = OrganisationRecord.get_record_by_pid(
                org_term['key'])
            if organisation:
                org_term['name'] = organisation['name']

        # Add collection name
        for org_term in results.get('aggregations',
                                    {}).get('collection',
                                            {}).get('buckets', []):
            collection = CollectionRecord.get_record_by_pid(org_term['key'])
            if collection:
                org_term['name'] = get_language_value(collection['name'])

        return super(JSONSerializer,
                     self).post_process_serialize_search(results, pid_fetcher)
Пример #10
0
def marc21_to_type_and_organisation(self, key, value):
    """Get document type and organisation from 980 field."""
    # organisation
    if value.get('b'):
        organisation = value.get('b').lower()

        # Specific transformation for `unisi`, because the real acronym is
        # `usi`.
        if organisation == 'unisi':
            organisation = 'usi'

        if organisation not in overdo.registererd_organisations:
            overdo.create_organisation(organisation)
            overdo.registererd_organisations.append(organisation)

        self['organisation'] = [{
            '$ref':
            OrganisationRecord.get_ref_link('organisations', organisation)
        }]

    # get doc type by mapping
    key = value.get('a', '') + '|' + value.get('f', '')
    if key not in TYPE_MAPPINGS:
        current_app.logger.warning(
            'Document type not found in mapping for type "{type}"'.format(
                type=key))
        return None

    # Store types to records
    self['documentType'] = TYPE_MAPPINGS[key]

    return None
Пример #11
0
    def post_process_serialize_search(self, results, pid_fetcher):
        """Post process the search results."""
        view = request.args.get('view')

        if view:
            if view != current_app.config.get(
                    'SONAR_APP_DEFAULT_ORGANISATION'):
                results['aggregations'].pop('organisation', {})
        else:
            if current_user_record and not current_user_record.is_superuser:
                results['aggregations'].pop('organisation', {})

        if results['aggregations'].get('year'):
            results['aggregations']['year']['type'] = 'range'
            results['aggregations']['year']['config'] = {
                'min': 1950,
                'max': int(datetime.now().year),
                'step': 1
            }

        # Add organisation name
        for org_term in results.get('aggregations',
                                    {}).get('organisation',
                                            {}).get('buckets', []):
            organisation = OrganisationRecord.get_record_by_pid(
                org_term['key'])
            if organisation:
                org_term['name'] = organisation['name']

        return super(JSONSerializer,
                     self).post_process_serialize_search(results, pid_fetcher)
Пример #12
0
def populate_files_properties(record):
    """Add restriction, link and thumbnail to file.

    :param record: Record object
    :param file: File dict
    """
    # Load organisation for the record
    organisation_pid = OrganisationRecord.get_pid_by_ref_link(
        record['organisation']['$ref']) if record['organisation'].get(
            '$ref') else record['organisation']['pid']
    organisation = OrganisationRecord.get_record_by_pid(organisation_pid)

    for file in record['_files']:
        if file.get('type') == 'file':
            file['restriction'] = get_file_restriction(file, organisation)
            file['thumbnail'] = get_thumbnail(file, record)
            file['links'] = get_file_links(file, record)
Пример #13
0
def store_organisation():
    """Add organisation record to global variables."""
    view = request.view_args.get(
        'view', current_app.config.get('SONAR_APP_DEFAULT_ORGANISATION'))

    if view != current_app.config.get('SONAR_APP_DEFAULT_ORGANISATION'):
        organisation = OrganisationRecord.get_record_by_pid(view)

        if not organisation or not organisation.get('isShared'):
            abort(404)

        g.organisation = organisation.dumps()
Пример #14
0
def store_organisation(endpoint, values):
    """Add organisation record to global variables."""
    view = values.pop('view',
                      current_app.config.get('SONAR_APP_DEFAULT_ORGANISATION'))

    if view != current_app.config.get('SONAR_APP_DEFAULT_ORGANISATION'):
        organisation = OrganisationRecord.get_record_by_pid(view)

        if not organisation or not organisation['isShared']:
            raise Exception('Organisation\'s view is not accessible')

        g.organisation = organisation.dumps()
Пример #15
0
def import_organisations(file):
    """Import organisations from JSON file."""
    click.secho('Importing organisations from {file}'.format(file=file.name))

    directory = os.path.dirname(file.name)

    indexer = OrganisationIndexer()

    for record in json.load(file):
        try:
            # Check existence in DB
            db_record = OrganisationRecord.get_record_by_pid(record['code'])

            if db_record:
                raise ClickException('Record already exists in DB')

            files = record.pop('files', [])

            # Register record to DB
            db_record = OrganisationRecord.create(record)

            # Add files
            for file in files:
                file_path = os.path.join(directory, file['path'])
                if os.path.isfile(file_path):
                    with open(file_path, 'rb') as f:
                        db_record.files[file['key']] = BytesIO(f.read())

            db_record.commit()
            db.session.commit()

            indexer.index(db_record)
        except Exception as error:
            click.secho(
                'Organisation {org} could not be imported: {error}'.format(
                    org=record, error=str(error)),
                fg='red')

    click.secho('Finished', fg='green')
Пример #16
0
    def create_organisation(organisation_key):
        """Create organisation if not existing and return it.

        :param str organisation_key: Key (PID) of the organisation.
        """
        if not organisation_key:
            raise Exception('No key provided')

        # Get organisation record from database
        organisation = OrganisationRecord.get_record_by_pid(organisation_key)

        if not organisation:
            # Create organisation record
            organisation = OrganisationRecord.create(
                {
                    'code': organisation_key,
                    'name': organisation_key,
                    'isShared': False,
                    'isDedicated': False
                },
                dbcommit=True)
            organisation.reindex()
Пример #17
0
def test_create_organisation(app, bucket_location, without_oaiset_signals):
    """Test create organisation."""
    Overdo.create_organisation('test')

    # Organisation creation OK
    organisation = OrganisationRecord.get_record_by_pid('test')
    assert organisation
    assert organisation['pid'] == 'test'

    # No organisation key provided
    with pytest.raises(Exception) as exception:
        Overdo.create_organisation(None)
    assert str(exception.value) == 'No key provided'
Пример #18
0
    def _make_organisation(code, is_shared=True):
        data = {
            'code': code,
            'name': code,
            'isShared': is_shared,
            'isDedicated': not is_shared,
            'documentsCustomField1': {
                'label': [{
                    'language': 'eng',
                    'value': 'Test'
                }],
                'includeInFacets': True
            }
        }

        record = OrganisationRecord.get_record_by_pid(code)

        if not record:
            record = OrganisationRecord.create(data, dbcommit=True)
            record.reindex()
            db.session.commit()

        return record
Пример #19
0
    def dump(self, record, data):
        """Dump the data for indexing."""
        if data['metadata'].get('user'):
            data['metadata']['user'] = {
                'pid':
                UserRecord.get_pid_by_ref_link(
                    data['metadata']['user']['$ref'])
            }

        if data['metadata'].get('organisation'):
            organisation = OrganisationRecord.get_record_by_ref_link(
                data['metadata']['organisation']['$ref'])
            data['metadata']['organisation'] = {
                'pid': organisation['pid'],
                'name': organisation['name']
            }
Пример #20
0
def marc21_to_specific_collection(self, key, value):
    """Extract collection for record."""
    if not value.get('a'):
        return None

    # No organisation found, the collection is not imported.
    if not self.get('organisation'):
        return None

    organisation_pid = OrganisationRecord.get_pid_by_ref_link(
        self['organisation'][0]['$ref'])

    hash_key = hashlib.md5(
        (value.get('a') + organisation_pid).encode()).hexdigest()

    collection_pid = CollectionRecord.get_pid_by_hash_key(hash_key)

    # No collection found
    if not collection_pid:
        collection = CollectionRecord.create({
            'name': [{
                'language': 'eng',
                'value': value.get('a')
            }],
            'organisation': {
                '$ref': self['organisation'][0]['$ref']
            },
            'hashKey':
            hash_key
        })
        collection.commit()
        collection.reindex()
        db.session.commit()
        collection_pid = collection['pid']

    return {
        '$ref': CollectionRecord.get_ref_link('collections', collection_pid)
    }
Пример #21
0
def test_import_organisations(app, script_info):
    """Test import organisations."""
    runner = CliRunner()

    datastore = app.extensions['security'].datastore
    datastore.create_role(name='admin')

    # Import ok
    result = runner.invoke(Cli.import_organisations,
                           ['./tests/ui/organisations/data/valid.json'],
                           obj=script_info)
    organisation = OrganisationRecord.get_record_by_pid('test')
    assert organisation
    assert organisation['pid'] == 'test'

    # Already existing
    result = runner.invoke(Cli.import_organisations,
                           ['./tests/ui/organisations/data/valid.json'],
                           obj=script_info)
    assert result.output.find(
        'Organisation {\'code\': \'test\', \'name\': \'Test\'} could not be '
        'imported: Record already exists in DB'
    )
Пример #22
0
def aggregations():
    """Get aggregations list."""
    view = request.args.get('view')
    collection = request.args.get('collection')

    customFields = [
        'customField1',
        'customField2',
        'customField3',
    ]

    aggregations_list = [
        'document_type',
        'controlled_affiliation',
        'year',
        'collection',
        'language',
        'author',
        'subject',
        'organisation',
        'subdivision',
    ] + customFields

    if view and view != current_app.config.get(
            'SONAR_APP_DEFAULT_ORGANISATION'):
        organisation = OrganisationRecord.get_record_by_pid(view)
        if organisation and organisation.get('isDedicated') \
        and organisation.get('publicDocumentFacets'):
            aggregations_list = organisation.get('publicDocumentFacets')\
                + customFields
    else:
        organisation = current_organisation

    # Remove organisation in dedicated view
    if 'organisation' in aggregations_list:
        if view and view != current_app.config.get(
                'SONAR_APP_DEFAULT_ORGANISATION'):
            aggregations_list.remove('organisation')
        elif current_user_record and not current_user_record.is_superuser:
            aggregations_list.remove('organisation')

    # Remove collection in collection context
    if collection and 'collection' in aggregations_list:
        aggregations_list.remove('collection')

    # Custom fields
    for i in range(1, 4):
        # Remove custom fields if we are in global view, or the fields is not
        # configured in organisation.
        if view == current_app.config.get(
                'SONAR_APP_DEFAULT_ORGANISATION'
        ) or not organisation or not organisation.get(
                f'documentsCustomField{i}', {}).get('includeInFacets'):
            aggregations_list.remove(f'customField{i}')
        elif organisation[f'documentsCustomField{i}'].get('label'):
            aggregations_list[aggregations_list.index(f'customField{i}')] = {
                'key':
                f'customField{i}',
                'name':
                get_language_value(
                    organisation[f'documentsCustomField{i}']['label'])
            }

    # Don't display subdivision in global context
    if view and 'subdivision' in aggregations_list and \
        view == current_app.config.get('SONAR_APP_DEFAULT_ORGANISATION'):
        aggregations_list.remove('subdivision')

    return jsonify(aggregations_list)
Пример #23
0
def marc21_to_type_and_organisation(self, key, value):
    """Get document type and organisation from 980 field."""
    subdivision_name = None

    # organisation
    if value.get('b'):
        organisation = value.get('b').lower()

        # Specific transformation for `unisi`, because the real acronym is
        # `usi`.
        if organisation == 'unisi':
            organisation = 'usi'

        # Specific transformation for `hep bejune`, in order to fill out
        # custom fields `Filière` (`customField1`) and `Titre obtenu`
        # (`customField2`)
        if organisation == 'hepbejune' and value.get('f'):
            document_subtype = value.get('f').lower()
            customField1 = ''
            customField2 = ''
            if document_subtype == 'diss_bachelor':
                customField1 = 'Enseignement primaire'
                customField2 = 'Bachelor of Arts in Pre-Primary and Primary Education'
            elif document_subtype == 'diss_master':
                customField1 = 'Enseignement secondaire'
                customField2 = 'Master of Arts or of Science in Secondary Education'
            if customField1:
                self['customField1'] = [customField1]
            if customField2:
                self['customField2'] = [customField2]

        # Specific transformation for `hepfr`, which should be imported as
        # a faculty AND a subdivision of FOLIA/unifr
        if organisation == 'hepfr':
            organisation = 'unifr'
            self['organisation'] = [{
                '$ref':
                OrganisationRecord.get_ref_link('organisations', organisation)
            }]
            # `hepfr` is a faculty of FOLIA/unifr
            self['customField1'] = ['HEP|PH FR']
            # `hepfr` is a subdivision of FOLIA/unifr
            subdivision_name = 'HEP Fribourg'
            # Store subdivision
            # TODO: avoid possible clashes between subdivision
            # names in different languages
            result = RecordSearch()\
                .filter('term', organisation__pid=organisation)\
                .filter('term', name__value__raw=subdivision_name)\
                .source(includes='pid').scan()
            subdivision_pid = next(result).pid
            # If the subdivision exists, assign it to the record
            if subdivision_pid:
                self['subdivisions'] = [{
                    '$ref':
                    SubdivisionRecord.get_ref_link('subdivisions',
                                                   subdivision_pid)
                }]

        # Specific transformation for `bpuge` and `mhnge`, because the real
        # acronym is `vge`.
        subdivision_name = None

        if organisation in [
                'bpuge', 'mhnge', 'baage', 'bmuge', 'imvge', 'mhsge'
        ]:
            subdivision_name = 'bge' if organisation == 'bpuge' else organisation
            organisation = 'vge'

        if organisation not in overdo.registererd_organisations:
            overdo.create_organisation(organisation)
            overdo.registererd_organisations.append(organisation)

        self['organisation'] = [{
            '$ref':
            OrganisationRecord.get_ref_link('organisations', organisation)
        }]

        if subdivision_name:
            # Store subdivision
            hash_key = hashlib.md5(
                (subdivision_name + organisation).encode()).hexdigest()

            subdivision_pid = SubdivisionRecord.get_pid_by_hash_key(hash_key)

            # No subdivision found
            if not subdivision_pid:
                subdivision = SubdivisionRecord.create({
                    'name': [{
                        'language': 'eng',
                        'value': subdivision_name
                    }],
                    'organisation': {
                        '$ref':
                        OrganisationRecord.get_ref_link(
                            'organisations', organisation)
                    },
                    'hashKey':
                    hash_key
                })
                subdivision.commit()
                subdivision.reindex()
                db.session.commit()
                subdivision_pid = subdivision['pid']

            self['subdivisions'] = [{
                '$ref':
                SubdivisionRecord.get_ref_link('subdivisions', subdivision_pid)
            }]

    # get doc type by mapping
    key = value.get('a', '') + '|' + value.get('f', '')
    if key not in TYPE_MAPPINGS:
        current_app.logger.warning(
            'Document type not found in mapping for type "{type}"'.format(
                type=key))
        return None

    # Store types to records
    self['documentType'] = TYPE_MAPPINGS[key]

    return None