예제 #1
0
def search_users(exact=False, include_deleted=False, include_pending=False, external=False, allow_system_user=False,
                 **criteria):
    """Searches for users.

    :param exact: Indicates if only exact matches should be returned.
                  This is MUCH faster than a non-exact saerch,
                  especially when searching external users.
    :param include_deleted: Indicates if also users marked as deleted
                            should be returned.
    :param include_pending: Indicates if also users who are still
                            pending should be returned.
    :param external: Indicates if identity providers should be searched
                     for matching users.
    :param allow_system_user: Whether the system user may be returned
                              in the search results.
    :param criteria: A dict containing any of the following keys:
                     name, first_name, last_name, email, affiliation, phone,
                     address
    :return: A set of matching users. If `external` was set, it may
             contain both :class:`~flask_multipass.IdentityInfo` objects
             for external users not yet in Indico and :class:`.User`
             objects for existing users.
    """

    criteria = {key: value.strip() for key, value in criteria.iteritems() if value.strip()}

    if not criteria:
        return set()

    query = (build_user_search_query(dict(criteria), exact=exact, include_deleted=include_deleted,
                                     include_pending=include_pending)
             .options(db.joinedload(User.identities),
                      db.joinedload(User.merged_into_user)))

    found_emails = {}
    found_identities = {}
    system_user = set()
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user
        if user.is_system and not user.all_emails and allow_system_user:
            system_user = {user}

    # external user providers
    if external:
        identities = multipass.search_identities(exact=exact, **criteria)

        for ident in identities:
            if not ident.data.get('email'):
                # Skip users with no email
                continue
            if ((ident.provider.name, ident.identifier) not in found_identities and
                    ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident

    return set(found_emails.viewvalues()) | system_user
예제 #2
0
def build_user_search_query(criteria, exact=False, include_deleted=False, include_pending=False):
    unspecified = object()
    query = User.query.options(db.joinedload(User._all_emails))

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    affiliation = criteria.pop('affiliation', unspecified)
    if affiliation is not unspecified:
        query = query.join(UserAffiliation).filter(unaccent_match(UserAffiliation.name, affiliation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(unaccent_match(UserEmail.email, email, exact))

    # search on any of the name fields (first_name OR last_name)
    name = criteria.pop('name', unspecified)
    if name is not unspecified:
        if exact:
            raise ValueError("'name' is not compatible with 'exact'")
        if 'first_name' in criteria or 'last_name' in criteria:
            raise ValueError("'name' is not compatible with (first|last)_name")
        name = name.split()
        query = query.filter(_build_name_search(name))

    for k, v in criteria.iteritems():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    return query
예제 #3
0
파일: provider.py 프로젝트: imfht/flaskapps
def load_token(access_token, refresh_token=None):
    if not access_token:
        return None
    # ugly hack so we can know in other places that we received a token
    # e.g. to show an error if there was an invalid token specified but
    # not if there was no token at all
    g.received_oauth_token = True
    try:
        UUID(hex=access_token)
    except ValueError:
        # malformed oauth token
        return None
    token = OAuthToken.query.filter_by(access_token=access_token).options(
        db.joinedload(OAuthToken.application)).first()
    if not token or not token.application.is_enabled:
        return None

    token_id = token.id  # avoid DetachedInstanceError in the callback

    @after_this_request
    def _update_last_use(response):
        with db.tmp_session() as sess:
            # do not modify `token` directly, it's attached to a different session!
            sess.query(OAuthToken).filter_by(id=token_id).update(
                {OAuthToken.last_used_dt: now_utc()})
            sess.commit()
        return response

    return token
예제 #4
0
파일: provider.py 프로젝트: jacquesd/indico
def load_token(access_token, refresh_token=None):
    if not access_token:
        return None
    # ugly hack so we can know in other places that we received a token
    # e.g. to show an error if there was an invalid token specified but
    # not if there was no token at all
    g.received_oauth_token = True
    try:
        UUID(hex=access_token)
    except ValueError:
        # malformed oauth token
        return None
    token = OAuthToken.find(access_token=access_token).options(db.joinedload(OAuthToken.application)).first()
    if not token or not token.application.is_enabled:
        return None

    token_id = token.id  # avoid DetachedInstanceError in the callback

    @after_this_request
    def _update_last_use(response):
        with db.tmp_session() as sess:
            # do not modify `token` directly, it's attached to a different session!
            sess.query(OAuthToken).filter_by(id=token_id).update({OAuthToken.last_used_dt: now_utc()})
            sess.commit()
        return response

    return token
예제 #5
0
def search_users(exact=False, include_deleted=False, include_pending=False, external=False, **criteria):
    unspecified = object()
    query = User.query.options(db.joinedload(User.identities),
                               db.joinedload(User._all_emails),
                               db.joinedload(User.merged_into_user))
    original_criteria = dict(criteria)

    if not criteria:
        return set()

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    organisation = criteria.pop('affiliation', unspecified)
    if organisation is not unspecified:
        query = query.join(UserAffiliation).filter(_build_match(UserAffiliation.name, organisation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(_build_match(UserEmail.email, email, exact))

    for k, v in criteria.iteritems():
        query = query.filter(_build_match(getattr(User, k), v, exact))

    found_emails = {}
    found_identities = {}
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user

    # external user providers
    if external:
        from indico.core.auth import multipass
        identities = multipass.search_identities(exact=exact, **original_criteria)

        for ident in identities:
            if ((ident.provider.name, ident.identifier) not in found_identities and
                    ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident

    return set(found_emails.viewvalues())
예제 #6
0
파일: util.py 프로젝트: d-demirci/indico
def build_user_search_query(criteria,
                            exact=False,
                            include_deleted=False,
                            include_pending=False,
                            include_blocked=False,
                            favorites_first=False):
    unspecified = object()
    query = User.query.distinct(User.id).options(
        db.joinedload(User._all_emails))

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)
    if not include_blocked:
        query = query.filter(~User.is_blocked)

    affiliation = criteria.pop('affiliation', unspecified)
    if affiliation is not unspecified:
        query = query.join(UserAffiliation).filter(
            unaccent_match(UserAffiliation.name, affiliation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(
            unaccent_match(UserEmail.email, email, exact))

    # search on any of the name fields (first_name OR last_name)
    name = criteria.pop('name', unspecified)
    if name is not unspecified:
        if exact:
            raise ValueError("'name' is not compatible with 'exact'")
        if 'first_name' in criteria or 'last_name' in criteria:
            raise ValueError("'name' is not compatible with (first|last)_name")
        query = query.filter(_build_name_search(name.replace(',', '').split()))

    for k, v in criteria.items():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    # wrap as subquery so we can apply order regardless of distinct-by-id
    query = query.from_self()

    if favorites_first:
        query = (query.outerjoin(
            favorite_user_table,
            db.and_(favorite_user_table.c.user_id == session.user.id,
                    favorite_user_table.c.target_id == User.id)).order_by(
                        nullslast(favorite_user_table.c.user_id)))
    query = query.order_by(
        db.func.lower(db.func.indico.indico_unaccent(User.first_name)),
        db.func.lower(db.func.indico.indico_unaccent(User.last_name)), User.id)
    return query
예제 #7
0
파일: util.py 프로젝트: indico/indico
def build_user_search_query(criteria, exact=False, include_deleted=False, include_pending=False,
                            favorites_first=False):
    unspecified = object()
    query = User.query.distinct(User.id).options(db.joinedload(User._all_emails))

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    affiliation = criteria.pop('affiliation', unspecified)
    if affiliation is not unspecified:
        query = query.join(UserAffiliation).filter(unaccent_match(UserAffiliation.name, affiliation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(unaccent_match(UserEmail.email, email, exact))

    # search on any of the name fields (first_name OR last_name)
    name = criteria.pop('name', unspecified)
    if name is not unspecified:
        if exact:
            raise ValueError("'name' is not compatible with 'exact'")
        if 'first_name' in criteria or 'last_name' in criteria:
            raise ValueError("'name' is not compatible with (first|last)_name")
        query = query.filter(_build_name_search(name.replace(',', '').split()))

    for k, v in criteria.iteritems():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    # wrap as subquery so we can apply order regardless of distinct-by-id
    query = query.from_self()

    if favorites_first:
        query = (query.outerjoin(favorite_user_table, db.and_(favorite_user_table.c.user_id == session.user.id,
                                                              favorite_user_table.c.target_id == User.id))
                 .order_by(nullslast(favorite_user_table.c.user_id)))
    query = query.order_by(db.func.lower(db.func.indico.indico_unaccent(User.first_name)),
                           db.func.lower(db.func.indico.indico_unaccent(User.last_name)),
                           User.id)
    return query
예제 #8
0
파일: util.py 프로젝트: DavidAndreev/indico
def search_users(exact=False,
                 include_deleted=False,
                 include_pending=False,
                 external=False,
                 **criteria):
    """Searches for users.

    :param exact: Indicates if only exact matches should be returned.
                  This is MUCH faster than a non-exact saerch,
                  especially when searching external users.
    :param include_deleted: Indicates if also users marked as deleted
                            should be returned.
    :param include_pending: Indicates if also users who are still
                            pending should be returned.
    :param external: Indicates if identity providers should be searched
                     for matching users.
    :param criteria: A dict containing any of the following keys:
                     first_name, last_name, email, affiliation, phone,
                     address
    :return: A set of matching users. If `external` was set, it may
             contain both :class:`~flask_multipass.IdentityInfo` objects
             for external users not yet in Indico and :class:`.User`
             objects for existing users.
    """
    unspecified = object()
    query = User.query.options(db.joinedload(User.identities),
                               db.joinedload(User._all_emails),
                               db.joinedload(User.merged_into_user))
    criteria = {
        key: value.strip()
        for key, value in criteria.iteritems() if value.strip()
    }
    original_criteria = dict(criteria)

    if not criteria:
        return set()

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    organisation = criteria.pop('affiliation', unspecified)
    if organisation is not unspecified:
        query = query.join(UserAffiliation).filter(
            unaccent_match(UserAffiliation.name, organisation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(
            unaccent_match(UserEmail.email, email, exact))

    for k, v in criteria.iteritems():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    found_emails = {}
    found_identities = {}
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user

    # external user providers
    if external:
        identities = multipass.search_identities(exact=exact,
                                                 **original_criteria)

        for ident in identities:
            if not ident.data.get('email'):
                # Skip users with no email
                continue
            if ((ident.provider.name, ident.identifier) not in found_identities
                    and ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident

    return set(found_emails.viewvalues())
예제 #9
0
파일: util.py 프로젝트: belokop/indico_bare
def search_users(exact=False, include_deleted=False, include_pending=False, external=False, **criteria):
    """Searches for users.

    :param exact: Indicates if only exact matches should be returned.
                  This is MUCH faster than a non-exact saerch,
                  especially when searching external users.
    :param include_deleted: Indicates if also users marked as deleted
                            should be returned.
    :param include_pending: Indicates if also users who are still
                            pending should be returned.
    :param external: Indicates if identity providers should be searched
                     for matching users.
    :param criteria: A dict containing any of the following keys:
                     first_name, last_name, email, affiliation, phone,
                     address
    :return: A set of matching users. If `external` was set, it may
             contain both :class:`~flask_multipass.IdentityInfo` objects
             for external users not yet in Indico and :class:`.User`
             objects for existing users.
    """
    unspecified = object()
    query = User.query.options(db.joinedload(User.identities),
                               db.joinedload(User._all_emails),
                               db.joinedload(User.merged_into_user))
    criteria = {key: value.strip() for key, value in criteria.iteritems() if value.strip()}
    original_criteria = dict(criteria)

    if not criteria:
        return set()

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    organisation = criteria.pop('affiliation', unspecified)
    if organisation is not unspecified:
        query = query.join(UserAffiliation).filter(unaccent_match(UserAffiliation.name, organisation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(unaccent_match(UserEmail.email, email, exact))

    for k, v in criteria.iteritems():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    found_emails = {}
    found_identities = {}
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user

    # external user providers
    if external:
        identities = multipass.search_identities(exact=exact, **original_criteria)

        for ident in identities:
            if not ident.data.get('email'):
                # Skip users with no email
                continue
            if ((ident.provider.name, ident.identifier) not in found_identities and
                    ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident

    return set(found_emails.viewvalues())
예제 #10
0
파일: util.py 프로젝트: jas01/indico
def search_users(exact=False, include_deleted=False, include_pending=False, external=False, allow_system_user=False,
                 **criteria):
    """Searches for users.

    :param exact: Indicates if only exact matches should be returned.
                  This is MUCH faster than a non-exact saerch,
                  especially when searching external users.
    :param include_deleted: Indicates if also users marked as deleted
                            should be returned.
    :param include_pending: Indicates if also users who are still
                            pending should be returned.
    :param external: Indicates if identity providers should be searched
                     for matching users.
    :param allow_system_user: Whether the system user may be returned
                              in the search results.
    :param criteria: A dict containing any of the following keys:
                     name, first_name, last_name, email, affiliation, phone,
                     address
    :return: A set of matching users. If `external` was set, it may
             contain both :class:`~flask_multipass.IdentityInfo` objects
             for external users not yet in Indico and :class:`.User`
             objects for existing users.
    """

    criteria = {key: value.strip() for key, value in criteria.iteritems() if value.strip()}

    if not criteria:
        return set()

    query = (build_user_search_query(
                dict(criteria),
                exact=exact,
                include_deleted=include_deleted,
                include_pending=include_pending)
             .options(db.joinedload(User.identities),
                      db.joinedload(User.merged_into_user)))

    found_emails = {}
    found_identities = {}
    system_user = set()
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user
        if user.is_system and not user.all_emails and allow_system_user:
            system_user = {user}

    # external user providers
    if external:
        identities = multipass.search_identities(exact=exact, **criteria)

        for ident in identities:
            if not ident.data.get('email'):
                # Skip users with no email
                continue
            if ((ident.provider.name, ident.identifier) not in found_identities and
                    ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident

    return set(found_emails.viewvalues()) | system_user
예제 #11
0
파일: util.py 프로젝트: manikm/indico2
def search_users(exact=False,
                 include_deleted=False,
                 include_pending=False,
                 external=False,
                 allow_system_user=False,
                 **criteria):
    """Searches for users.

    :param exact: Indicates if only exact matches should be returned.
                  This is MUCH faster than a non-exact saerch,
                  especially when searching external users.
    :param include_deleted: Indicates if also users marked as deleted
                            should be returned.
    :param include_pending: Indicates if also users who are still
                            pending should be returned.
    :param external: Indicates if identity providers should be searched
                     for matching users.
    :param allow_system_user: Whether the system user may be returned
                              in the search results.
    :param criteria: A dict containing any of the following keys:
                     first_name, last_name, email, affiliation, phone,
                     address
    :return: A set of matching users. If `external` was set, it may
             contain both :class:`~flask_multipass.IdentityInfo` objects
             for external users not yet in Indico and :class:`.User`
             objects for existing users.
    """
    unspecified = object()
    query = User.query.options(db.joinedload(User.identities),
                               db.joinedload(User._all_emails),
                               db.joinedload(User.merged_into_user))
    criteria = {
        key: value.strip()
        for key, value in criteria.iteritems() if value.strip()
    }
    original_criteria = dict(criteria)

    if not criteria:
        return set()

    if not include_pending:
        query = query.filter(~User.is_pending)
    if not include_deleted:
        query = query.filter(~User.is_deleted)

    affiliation = criteria.pop('affiliation', unspecified)
    if affiliation is not unspecified:
        query = query.join(UserAffiliation).filter(
            unaccent_match(UserAffiliation.name, affiliation, exact))

    email = criteria.pop('email', unspecified)
    if email is not unspecified:
        query = query.join(UserEmail).filter(
            unaccent_match(UserEmail.email, email, exact))

    abstract = criteria.pop('abstract', unspecified)
    track = criteria.pop('track', unspecified)
    query2 = query
    if abstract is not unspecified:
        if track is unspecified:
            query = query.join(Abstract,
                               (Abstract.submitter_id == User.id)).filter(
                                   unaccent_match(Abstract.title, abstract,
                                                  exact))
            query2 = query2.join(
                Abstract, (Abstract.submitter_id == User.id)).filter(
                    unaccent_match(Abstract.title, abstract,
                                   exact)).add_columns(
                                       User.id, Track.title.label('track'),
                                       Abstract.title.label('abstract'))
        else:
            query = query.join(
                Abstract, (Abstract.submitter_id == User.id)).join(
                    Track, (Abstract.accepted_track_id == Track.id)).filter(
                        unaccent_match(
                            Abstract.title, abstract, exact)).filter(
                                Track.title.op("~*")(
                                    r'[[:<:]]{}[[:>:]]'.format(track)))
            query2 = query2.join(
                Abstract, (Abstract.submitter_id == User.id)).add_columns(
                    User.id, Track.title.label('track'),
                    Abstract.title.label('abstract')).join(
                        Track,
                        (Abstract.accepted_track_id == Track.id)).filter(
                            unaccent_match(
                                Abstract.title, abstract, exact)).filter(
                                    Track.title.op("~*")(
                                        r'[[:<:]]{}[[:>:]]'.format(track)))
    elif track is not unspecified:
        query = query.join(Abstract, (Abstract.submitter_id == User.id)).join(
            Track, (Abstract.accepted_track_id == Track.id)).filter(
                Track.title.op("~*")(r'[[:<:]]{}[[:>:]]'.format(track)))
        query2 = query2.join(
            Abstract, (Abstract.submitter_id == User.id)).add_columns(
                User.id, Track.title.label('track'),
                Abstract.title.label('abstract')).join(
                    Track, (Abstract.accepted_track_id == Track.id)).filter(
                        Track.title.op("~*")(
                            r'[[:<:]]{}[[:>:]]'.format(track)))

    for k, v in criteria.iteritems():
        query = query.filter(unaccent_match(getattr(User, k), v, exact))

    for user1 in query:
        for user2 in query2:
            if (user1.id == user2.id) and ((abstract is not unspecified) or
                                           (track is not unspecified)):
                user1.abstract = user2.abstract
                user1.track = user2.track

    found_emails = {}
    found_identities = {}
    system_user = set()
    for user in query:
        for identity in user.identities:
            found_identities[(identity.provider, identity.identifier)] = user
        for email in user.all_emails:
            found_emails[email] = user
        if user.is_system and not user.all_emails and allow_system_user:
            system_user = {user}

    # external user providers
    if external:
        identities = multipass.search_identities(exact=exact,
                                                 **original_criteria)

        for ident in identities:
            if not ident.data.get('email'):
                # Skip users with no email
                continue
            if ((ident.provider.name, ident.identifier) not in found_identities
                    and ident.data['email'].lower() not in found_emails):
                found_emails[ident.data['email'].lower()] = ident
                found_identities[(ident.provider, ident.identifier)] = ident
    return set(found_emails.viewvalues()) | system_user