def get_scopes_for(orm_object):
    """Find scopes for a given user or token from their roles and resolve permissions

    Arguments:
      orm_object: orm object or User wrapper

    Returns:
      expanded scopes (set) for the orm object
      or
      intersection (set) if orm_object == orm.APIToken
    """
    expanded_scopes = set()
    if orm_object is None:
        return expanded_scopes

    if not isinstance(orm_object, orm.Base):
        from .user import User

        if isinstance(orm_object, User):
            orm_object = orm_object.orm_user
        else:
            raise TypeError(
                f"Only allow orm objects or User wrappers, got {orm_object}"
            )

    owner = None
    if isinstance(orm_object, orm.APIToken):
        owner = orm_object.user or orm_object.service
        owner_roles = roles.get_roles_for(owner)
        owner_scopes = roles.roles_to_expanded_scopes(owner_roles, owner)
        if owner is orm_object.user:
            for share in owner.shared_with_me:
                owner_scopes |= frozenset(share.scopes)

        token_scopes = set(orm_object.scopes)
        if 'inherit' in token_scopes:
            # token_scopes includes 'inherit',
            # so we know the intersection is exactly the owner's scopes
            # only thing we miss by short-circuiting here: warning about excluded extra scopes
            return owner_scopes

        token_scopes = set(
            expand_scopes(
                token_scopes,
                owner=owner,
                oauth_client=orm_object.oauth_client,
            )
        )

        if orm_object.client_id != "jupyterhub":
            # oauth tokens can be used to access the service issuing the token,
            # assuming the owner itself still has permission to do so
            token_scopes.update(access_scopes(orm_object.oauth_client))

        # reduce to collapse multiple filters on the same scope
        # to avoid spurious logs about discarded scopes
        token_scopes.update(identify_scopes(owner))
        token_scopes = reduce_scopes(token_scopes)

        intersection = _intersect_expanded_scopes(
            token_scopes,
            owner_scopes,
            db=sa.inspect(orm_object).session,
        )
        discarded_token_scopes = token_scopes - intersection

        # Not taking symmetric difference here because token owner can naturally have more scopes than token
        if discarded_token_scopes:
            app_log.warning(
                f"discarding scopes [{discarded_token_scopes}],"
                f" not present in roles of owner {owner}"
            )
            app_log.debug(
                "Owner %s has scopes: %s\nToken has scopes: %s",
                owner,
                owner_scopes,
                token_scopes,
            )
        expanded_scopes = intersection
        # always include identify scopes
        expanded_scopes
    else:
        expanded_scopes = roles.roles_to_expanded_scopes(
            roles.get_roles_for(orm_object),
            owner=orm_object,
        )

        # add permissions granted from 'shares'
        if hasattr(orm_object, "shared_with_me"):
            for share in orm_object.shared_with_me:
                expanded_scopes |= expand_share_scopes(share)
        if isinstance(orm_object, orm.User):
            for group in orm_object.groups:
                for share in group.shared_with_me:
                    expanded_scopes |= expand_share_scopes(share)

    return expanded_scopes
Find scopes for a given user or token from their roles and resolve permissions

Arguments:
orm_object: orm object or User wrapper

Returns:
expanded scopes (set) for the orm object
or
intersection (set) if orm_object == orm.APIToken
jupyterhub/scopes.py