Exemple #1
0
def check_privileged():
    """Check if request is trying to make an actor privileged."""
    logger.debug("top of check_privileged")
    # admins have access to all actors:
    if g.admin:
        return True
    data = request.get_json()
    if not data:
        data = request.form
    # various APIs (e.g., the state api) allow an arbitary JSON serializable objects which won't have a get method:
    if not hasattr(data, 'get'):
        return True
    if data.get('privileged'):
        logger.debug("User is trying to set privileged")
        # if we're here, user isn't an admin so must have privileged role:
        if not codes.PRIVILEGED_ROLE in g.roles:
            logger.info("User does not have privileged role.")
            raise PermissionsException("Not authorized -- only admins and privileged users can make privileged actors.")
        else:
            logger.debug("user allowed to set privileged.")

    # when using the UID associated with the user in TAS, admins can still register actors
    # to use the UID built in the container using the use_container_uid flag:
    if Config.get('workers', 'use_tas_uid'):
        if data.get('use_container_uid') or data.get('useContainerUid'):
            logger.debug("User is trying to use_container_uid")
            # if we're here, user isn't an admin so must have privileged role:
            if not codes.PRIVILEGED_ROLE in g.roles:
                logger.info("User does not have privileged role.")
                raise PermissionsException("Not authorized -- only admins and privileged users can use container uid.")
            else:
                logger.debug("user allowed to use container uid.")
    else:
        logger.debug("not trying to use privileged options.")
        return True
Exemple #2
0
def check_nonce():
    """
    This function is an agaveflask authentication callback used to process the existence of a query parameter,
    x-nonce, an alternative authentication mechanism to JWT.
    
    When an x-nonce query parameter is provided, the request context is updated with the identity of the user owning
    the actor to which the nonce belongs. Note that the roles of said user will not be calculated so, in particular, 
    any privileged action cannot be taken via a nonce. 
    """
    logger.debug("top of check_nonce")
    try:
        nonce_id = request.args['x-nonce']
    except KeyError:
        raise PermissionsException("No JWT or nonce provided.")
    logger.debug("checking nonce with id: {}".format(nonce_id))
    # the nonce encodes the tenant in its id:
    g.tenant = Nonce.get_tenant_from_nonce_id(nonce_id)
    g.api_server = get_api_server(g.tenant)
    logger.debug("tenant associated with nonce: {}".format(g.tenant))
    # get the actor_id base on the request path
    actor_id = get_db_id()
    logger.debug("db_id: {}".format(actor_id))
    level = required_level(request)
    Nonce.check_and_redeem_nonce(actor_id, nonce_id, level)
    # if we were able to redeem the nonce, update auth context with the actor owner data:
    logger.debug("nonce valid and redeemed.")
    nonce = Nonce.get_nonce(actor_id, nonce_id)
    g.user = nonce.owner
    # update roles data with that stored on the nonce:
    g.roles = nonce.roles
    # now, manually call our authorization function:
    authorization()
Exemple #3
0
def get_db_id():
    """Get the db_id from the request path."""
    # logger.debug("top of get_db_id. request.path: {}".format(request.path))
    path_split = request.path.split("/")
    if len(path_split) < 3:
        logger.error(
            "Unrecognized request -- could not find the actor id. path_split: {}"
            .format(path_split))
        raise PermissionsException("Not authorized.")
    # logger.debug("path_split: {}".format(path_split))
    actor_identifier = path_split[2]
    # logger.debug("actor_identifier: {}; tenant: {}".format(actor_identifier, g.tenant))
    try:
        actor_id = Actor.get_actor_id(g.tenant, actor_identifier)
    except KeyError:
        logger.info(
            "Unrecoginzed actor_identifier: {}. Actor not found".format(
                actor_identifier))
        raise ResourceError(
            "Actor with identifier '{}' not found".format(actor_identifier),
            404)
    except Exception as e:
        msg = "Unrecognized exception trying to resolve actor identifier: {}; " \
              "exception: {}".format(actor_identifier, e)
        logger.error(msg)
        raise ResourceError(msg)
    logger.debug("actor_id: {}".format(actor_id))
    return Actor.get_dbid(g.tenant, actor_id)
Exemple #4
0
def get_db_id():
    """Get the db_id from the request path."""
    path_split = request.path.split("/")
    if len(path_split) < 3:
        logger.error("Unrecognized request -- could not find the actor id. path_split: {}".format(path_split))
        raise PermissionsException("Not authorized.")
    actor_id = path_split[2]
    logger.debug("actor_id: {}".format(actor_id))
    return Actor.get_dbid(g.tenant, actor_id)
Exemple #5
0
def get_alias_id():
    """Get the alias from the request path."""
    path_split = request.path.split("/")
    if len(path_split) < 4:
        logger.error(
            "Unrecognized request -- could not find the alias. path_split: {}".
            format(path_split))
        raise PermissionsException("Not authorized.")
    alias = path_split[3]
    logger.debug("alias: {}".format(alias))
    return Alias.generate_alias_id(g.tenant, alias)
Exemple #6
0
def get_config_name():
    """Get the config name from the request path."""
    logger.debug("top of auth.get_config_id()")
    path_split = request.path.split("/")
    if len(path_split) < 4:
        logger.error(
            "Unrecognized request -- could not find the config. path_split: {}"
            .format(path_split))
        raise PermissionsException("Not authorized.")
    config_name = path_split[3]
    logger.debug("returning config_name from path: {}".format(config_name))
    return config_name
Exemple #7
0
def get_db_id():
    """Get the db_id and actor_identifier from the request path."""
    # the location of the actor identifier is different for aliases vs actor_id's.
    # for actors, it is in index 2:
    #     /actors/<actor_id>
    # for aliases, it is in index 3:
    #     /actors/aliases/<alias_id>
    idx = 2
    if 'aliases' in request.path:
        idx = 3
    path_split = request.path.split("/")
    if len(path_split) < 3:
        logger.error(
            "Unrecognized request -- could not find the actor id. path_split: {}"
            .format(path_split))
        raise PermissionsException("Not authorized.")
    logger.debug("path_split: {}".format(path_split))
    try:
        actor_identifier = path_split[idx]
    except IndexError:
        raise ResourceError(
            "Unable to parse actor identifier: is it missing from the URL?",
            404)
    logger.debug("actor_identifier: {}; tenant: {}".format(
        actor_identifier, g.tenant))
    if actor_identifier == 'search':
        raise ResourceError(
            "'x-nonce' query parameter on the '/actors/search/{database}' endpoint does not resolve.",
            404)
    try:
        actor_id = Actor.get_actor_id(g.tenant, actor_identifier)
    except KeyError:
        logger.info(
            "Unrecognized actor_identifier: {}. Actor not found".format(
                actor_identifier))
        raise ResourceError(
            "Actor with identifier '{}' not found".format(actor_identifier),
            404)
    except Exception as e:
        msg = "Unrecognized exception trying to resolve actor identifier: {}; " \
              "exception: {}".format(actor_identifier, e)
        logger.error(msg)
        raise ResourceError(msg)
    logger.debug("actor_id: {}".format(actor_id))
    return Actor.get_dbid(g.tenant, actor_id), actor_identifier
Exemple #8
0
def authorization():
    """Entry point for authorization. Use as follows:

    import auth

    my_app = Flask(__name__)
    @my_app.before_request
    def authz_for_my_app():
        auth.authorization()

    """
    if request.method == 'OPTIONS':
        # allow all users to make OPTIONS requests
        return

    # all other checks are based on actor-id; if that is not present then let
    # request through to fail.
    actor_id = request.args.get('actor_id', None)
    if not actor_id:
        return

    if request.method == 'GET':
        has_pem = check_permissions(user=g.user,
                                    actor_id=actor_id,
                                    level='READ')
    else:
        print(request.url_rule.rule)
        if request.method == 'POST':
            # creating a new actor requires no permissions
            if 'actors' == request.url_rule.rule or 'actors/' == request.url_rule.rule:
                has_pem = True
            # POST to the messages endpoint requires EXECUTE
            elif 'messages' in request.url_rule.rule:
                has_pem = check_permissions(user=g.user,
                                            actor_id=actor_id,
                                            level='EXECUTE')
            # otherwise, we require UPDATE
            else:
                has_pem = check_permissions(user=g.user,
                                            actor_id=actor_id,
                                            level='UPDATE')
    if not has_pem:
        raise PermissionsException("Not authorized")
Exemple #9
0
def check_privileged():
    """Check if request is trying to make an actor privileged."""
    logger.debug("top of check_privileged")
    # admins have access to all actors:
    if g.admin:
        return True
    data = request.get_json()
    if not data:
        data = request.form
    if data.get('privileged'):
        logger.debug("User is trying to set privileged")
        # if we're here, user isn't an admin so must have privileged role:
        if not codes.PRIVILEGED_ROLE in g.roles:
            logger.info("User does not have privileged role.")
            raise PermissionsException(
                "Not authorized -- only admins and privileged users can make privileged actors."
            )
        else:
            logger.debug("user allowed to set privileged.")
            return True
    else:
        logger.debug("not trying to set privileged.")
        return True
Exemple #10
0
def get_db_id():
    """Get the db_id and actor_identifier from the request path."""
    # the location of the actor identifier is different for aliases vs actor_id's.
    # for actors, it is in index 2:
    #     /actors/<actor_id>
    # for aliases, it is in index 3:
    #     /actors/aliases/<alias_id>
    idx = 2
    if 'aliases' in request.path:
        idx = 3
    path_split = request.path.split("/")
    if len(path_split) < 3:
        logger.error(
            "Unrecognized request -- could not find the actor id. path_split: {}"
            .format(path_split))
        raise PermissionsException("Not authorized.")
    logger.debug("path_split: {}".format(path_split))
    actor_identifier = path_split[idx]
    logger.debug("actor_identifier: {}; tenant: {}".format(
        actor_identifier, g.tenant))
    try:
        actor_id = Actor.get_actor_id(g.tenant, actor_identifier)
    except KeyError:
        logger.info(
            "Unrecoginzed actor_identifier: {}. Actor not found".format(
                actor_identifier))
        raise ResourceError(
            "Actor with identifier '{}' not found".format(actor_identifier),
            404)
    except Exception as e:
        msg = "Unrecognized exception trying to resolve actor identifier: {}; " \
              "exception: {}".format(actor_identifier, e)
        logger.error(msg)
        raise ResourceError(msg)
    logger.debug("actor_id: {}".format(actor_id))
    return Actor.get_dbid(g.tenant, actor_id), actor_identifier
Exemple #11
0
def authorization():
    """This is the agaveflask authorization callback and implements the main Abaco authorization
    logic. This function is called by agaveflask after all authentication processing and initial
    authorization logic has run.
    """
    g.admin = False
    if request.method == 'OPTIONS':
        # allow all users to make OPTIONS requests
        logger.info("Allowing request because of OPTIONS method.")
        return True

    # the 'ALL' role is a role set by agaveflask in case the access_control_type is none
    if codes.ALL_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ALL role.")
        return True

    # all other requests require some kind of abaco role:
    if set(g.roles).isdisjoint(codes.roles):
        logger.info("NOT allowing request - user has no abaco role.")
        raise PermissionsException("Not authorized -- missing required role.")
    else:
        logger.debug("User has an abaco role.")
        if hasattr(request, 'url_rule'):
            logger.debug("request.url_rule: {}".format(request.url_rule))
            if hasattr(request.url_rule, 'rule'):
                logger.debug("url_rule.rule: {}".format(request.url_rule.rule))
            else:
                logger.info("url_rule has no rule.")
                raise ResourceError("Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.", 405)
        else:
            logger.info("Request has no url_rule")
            raise ResourceError(
                "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.", 405)
    logger.debug("request.path: {}".format(request.path))

    # the admin role when JWT auth is configured:
    if codes.ADMIN_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ADMIN_ROLE.")
        return True

    # the admin API requires the admin role:
    if 'admin' in request.path or '/actors/admin' in request.url_rule.rule or '/actors/admin/' in request.url_rule.rule:
        if g.admin:
            return True
        else:
            raise PermissionsException("Abaco Admin role required.")

    # there are special rules on the root collection:
    if '/actors' == request.url_rule.rule or '/actors/' == request.url_rule.rule:
        logger.debug("Checking permissions on root collection.")
        # first, only admins can create/update actors to be privileged, so check that:
        if request.method == 'POST':
            check_privileged()
        # if we are here, it is either a GET or a new actor, so the request is allowed:
        logger.debug("new actor or GET on root connection. allowing request.")
        return True

    # all other checks are based on actor-id:
    db_id = get_db_id()
    logger.debug("db_id: {}".format(db_id))
    if request.method == 'GET':
        # GET requests require READ access
        has_pem = check_permissions(user=g.user, actor_id=db_id, level=codes.READ)
    elif request.method == 'DELETE':
        has_pem = check_permissions(user=g.user, actor_id=db_id, level=codes.UPDATE)
    else:
        logger.debug("URL rule in request: {}".format(request.url_rule.rule))
        # first, only admins can create/update actors to be privileged, so check that:
        if request.method == 'POST' or request.method == 'PUT':
            check_privileged()
            # only admins have access to the workers endpoint, and if we are here, the user is not an admin:
            if 'workers' in request.url_rule.rule:
                raise PermissionsException("Not authorized -- only admins are authorized to update workers.")
            # POST to the messages endpoint requires EXECUTE
            if 'messages' in request.url_rule.rule:
                has_pem = check_permissions(user=g.user, actor_id=db_id, level=codes.EXECUTE)
            # otherwise, we require UPDATE
            else:
                has_pem = check_permissions(user=g.user, actor_id=db_id, level=codes.UPDATE)
    if not has_pem:
        logger.info("NOT allowing request.")
        raise PermissionsException("Not authorized -- you do not have access to this actor.")
Exemple #12
0
def check_nonce():
    """
    This function is an agaveflask authentication callback used to process the existence of a query parameter,
    x-nonce, an alternative authentication mechanism to JWT.
    
    When an x-nonce query parameter is provided, the request context is updated with the identity of the user owning
    the actor to which the nonce belongs. Note that the roles of said user will not be calculated so, in particular, 
    any privileged action cannot be taken via a nonce. 
    """
    logger.debug("top of check_nonce")
    # first check whether the request is even valid -
    if hasattr(request, 'url_rule'):
        logger.debug("request.url_rule: {}".format(request.url_rule))
        if hasattr(request.url_rule, 'rule'):
            logger.debug("url_rule.rule: {}".format(request.url_rule.rule))
        else:
            logger.info("url_rule has no rule.")
            raise ResourceError(
                "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
                405)
    else:
        logger.info("Request has no url_rule")
        raise ResourceError(
            "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
            405)
    try:
        nonce_id = request.args['x-nonce']
    except KeyError:
        raise PermissionsException("No JWT or nonce provided.")
    logger.debug("checking nonce with id: {}".format(nonce_id))
    # the nonce encodes the tenant in its id:
    g.tenant = Nonce.get_tenant_from_nonce_id(nonce_id)
    g.api_server = get_api_server(g.tenant)
    logger.debug(
        "tenant associated with nonce: {}; api_server assoicated with nonce: {}"
        .format(g.tenant, g.api_server))
    # get the actor_id base on the request path
    actor_id, actor_identifier = get_db_id()
    logger.debug("db_id: {}; actor_identifier: {}".format(
        actor_id, actor_identifier))
    level = required_level(request)

    # if the actor_identifier is an alias, then the nonce must be attached to that, so we must pass that in the
    # nonce check:
    if is_hashid(actor_identifier):
        Nonce.check_and_redeem_nonce(actor_id=actor_id,
                                     alias=None,
                                     nonce_id=nonce_id,
                                     level=level)
    else:
        alias_id = Alias.generate_alias_id(tenant=g.tenant,
                                           alias=actor_identifier)
        Nonce.check_and_redeem_nonce(actor_id=None,
                                     alias=alias_id,
                                     nonce_id=nonce_id,
                                     level=level)
    # if we were able to redeem the nonce, update auth context with the actor owner data:
    logger.debug("nonce valid and redeemed.")
    if is_hashid(actor_identifier):
        nonce = Nonce.get_nonce(actor_id=actor_id,
                                alias=None,
                                nonce_id=nonce_id)
    else:
        nonce = Nonce.get_nonce(actor_id=None,
                                alias=alias_id,
                                nonce_id=nonce_id)
    g.user = nonce.owner
    # update roles data with that stored on the nonce:
    g.roles = nonce.roles
    # now, manually call our authorization function:
    authorization()
Exemple #13
0
def authorization():
    """This is the agaveflask authorization callback and implements the main Abaco authorization
    logic. This function is called by agaveflask after all authentication processing and initial
    authorization logic has run.
    """
    # first check whether the request is even valid -
    if hasattr(request, 'url_rule'):
        logger.debug("request.url_rule: {}".format(request.url_rule))
        if hasattr(request.url_rule, 'rule'):
            logger.debug("url_rule.rule: {}".format(request.url_rule.rule))
        else:
            logger.info("url_rule has no rule.")
            raise ResourceError(
                "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
                405)
    else:
        logger.info("Request has no url_rule")
        raise ResourceError(
            "Invalid request: the API endpoint does not exist or the provided HTTP method is not allowed.",
            405)

    # get the actor db_id from a possible identifier once and for all -
    # these routes do not have an actor id in them:
    if request.url_rule.rule == '/actors' \
        or request.url_rule.rule == '/actors/' \
        or '/actors/admin' in request.url_rule.rule \
        or '/actors/aliases' in request.url_rule.rule \
        or '/actors/utilization' in request.url_rule.rule \
        or '/actors/search/' in request.url_rule.rule:
        db_id = None
        logger.debug("setting db_id to None; rule: {}".format(
            request.url_rule.rule))
    else:
        # every other route should have an actor identifier
        logger.debug("fetching db_id; rule: {}".format(request.url_rule.rule))
        db_id, _ = get_db_id()
    g.db_id = db_id
    logger.debug("db_id: {}".format(db_id))

    g.admin = False
    if request.method == 'OPTIONS':
        # allow all users to make OPTIONS requests
        logger.info("Allowing request because of OPTIONS method.")
        return True

    # the 'ALL' role is a role set by agaveflask in case the access_control_type is None
    if codes.ALL_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ALL role.")
        return True

    # there is a bug in wso2 that causes the roles claim to sometimes be missing; this should never happen:
    if not g.roles:
        g.roles = ['Internal/everyone']

    # all other requests require some kind of abaco role:
    if set(g.roles).isdisjoint(codes.roles):
        logger.info("NOT allowing request - user has no abaco role.")
        raise PermissionsException("Not authorized -- missing required role.")
    else:
        logger.debug("User has an abaco role.")
    logger.debug("request.path: {}".format(request.path))

    # the admin role when JWT auth is configured:
    if codes.ADMIN_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ADMIN_ROLE.")
        return True

    # the admin API requires the admin role:
    if 'admin' in request.path or '/actors/admin' in request.url_rule.rule or '/actors/admin/' in request.url_rule.rule:
        if g.admin:
            return True
        else:
            raise PermissionsException("Abaco Admin role required.")

    # the utilization endpoint is available to every authenticated user
    if '/actors/utilization' == request.url_rule.rule or '/actors/utilization/' == request.url_rule.rule:
        return True

    if '/actors/search/<string:search_type>' == request.url_rule.rule:
        return True

    # there are special rules on the actors root collection:
    if '/actors' == request.url_rule.rule or '/actors/' == request.url_rule.rule:
        logger.debug("Checking permissions on root collection.")
        # first, only admins can create/update actors to be privileged, so check that:
        if request.method == 'POST':
            check_privileged()
        # if we are here, it is either a GET or a new actor, so the request is allowed:
        logger.debug("new actor or GET on root connection. allowing request.")
        return True

    # aliases root collection has special rules as well -
    if '/actors/aliases' == request.url_rule.rule or '/actors/aliases/' == request.url_rule.rule:
        return True

    # request to a specific alias needs to check aliases permissions
    if '/actors/aliases' in request.url_rule.rule:
        alias_id = get_alias_id()
        noun = 'alias'
        # we need to compute the db_id since it is not computed in the general case for
        # alias endpoints
        db_id, _ = get_db_id()
        # reading/creating/updating nonces for an alias requires permissions for both the
        # alias itself and the underlying actor
        if 'nonce' in request.url_rule.rule:
            noun = 'alias and actor'
            # logger.debug("checking user {} has permissions for "
            #              "alias: {} and actor: {}".format(g.user, alias_id, db_id))
            if request.method == 'GET':
                # GET requests require READ access

                has_pem = check_permissions(user=g.user,
                                            identifier=alias_id,
                                            level=codes.READ)
                has_pem = has_pem and check_permissions(
                    user=g.user, identifier=db_id, level=codes.READ)
            elif request.method in ['DELETE', 'POST', 'PUT']:
                has_pem = check_permissions(user=g.user,
                                            identifier=alias_id,
                                            level=codes.UPDATE)
                has_pem = has_pem and check_permissions(
                    user=g.user, identifier=db_id, level=codes.UPDATE)

        # otherwise, this is a request to manage the alias itself; only requires permissions on the alias
        else:
            if request.method == 'GET':
                # GET requests require READ access
                has_pem = check_permissions(user=g.user,
                                            identifier=alias_id,
                                            level=codes.READ)
                # all other requests require UPDATE access
            elif request.method in ['DELETE', 'POST', 'PUT']:
                has_pem = check_permissions(user=g.user,
                                            identifier=alias_id,
                                            level=codes.UPDATE)
    else:
        # all other checks are based on actor-id:
        noun = 'actor'
        if request.method == 'GET':
            # GET requests require READ access
            has_pem = check_permissions(user=g.user,
                                        identifier=db_id,
                                        level=codes.READ)
        elif request.method == 'DELETE':
            has_pem = check_permissions(user=g.user,
                                        identifier=db_id,
                                        level=codes.UPDATE)
        else:
            logger.debug("URL rule in request: {}".format(
                request.url_rule.rule))
            # first, only admins can create/update actors to be privileged, so check that:
            if request.method == 'POST' or request.method == 'PUT':
                check_privileged()
                # only admins have access to the workers endpoint, and if we are here, the user is not an admin:
                if 'workers' in request.url_rule.rule:
                    raise PermissionsException(
                        "Not authorized -- only admins are authorized to update workers."
                    )
                # POST to the messages endpoint requires EXECUTE
                if 'messages' in request.url_rule.rule:
                    has_pem = check_permissions(user=g.user,
                                                identifier=db_id,
                                                level=codes.EXECUTE)
                # otherwise, we require UPDATE
                else:
                    has_pem = check_permissions(user=g.user,
                                                identifier=db_id,
                                                level=codes.UPDATE)
    if not has_pem:
        logger.info("NOT allowing request.")
        raise PermissionsException(
            "Not authorized -- you do not have access to this {}.".format(
                noun))
Exemple #14
0
def authorization():
    """Entry point for authorization. Use as follows:

    import auth

    my_app = Flask(__name__)
    @my_app.before_request
    def authz_for_my_app():
        auth.authorization()

    """
    g.admin = False
    if request.method == 'OPTIONS':
        # allow all users to make OPTIONS requests
        logger.info("Allowing request because of OPTIONS method.")
        return True

    # the 'ALL' role is a role set by agaveflask in case the access_control_type is none
    if codes.ALL_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ALL role.")
        return True

    # the admin role when JWT auth is configured:
    if codes.ADMIN_ROLE in g.roles:
        g.admin = True
        logger.info("Allowing request because of ADMIN_ROLE.")
        return True

    # all other requests require some kind of abaco role:
    if set(g.roles).isdisjoint(codes.roles):
        logger.info("NOT allowing request - user has no abaco role.")
        raise PermissionsException("Not authorized -- missing required role.")
    else:
        logger.debug("User has an abaco role.")
    logger.debug("URL rule: {}".format(request.url_rule.rule or 'actors/'))
    logger.debug("request.path: {}".format(request.path))
    # there are special rules on the root collection:
    if '/actors' == request.url_rule.rule or '/actors/' == request.url_rule.rule:
        logger.debug("Checking permissions on root collection.")
        # first, only admins can create/update actors to be privileged, so check that:
        if request.method == 'POST':
            check_privileged()
        # if we are here, it is either a GET or a new actor, so the request is allowed:
        logger.debug("new actor or GET on root connection. allowing request.")
        return True

    # all other checks are based on actor-id:
    db_id = get_db_id()
    logger.debug("db_id: {}".format(db_id))
    if request.method == 'GET':
        # GET requests require READ access
        has_pem = check_permissions(user=g.user,
                                    actor_id=db_id,
                                    level=codes.READ)
    elif request.method == 'DELETE':
        has_pem = check_permissions(user=g.user,
                                    actor_id=db_id,
                                    level=codes.UPDATE)
    else:
        logger.debug("URL rule in request: {}".format(request.url_rule.rule))
        # first, only admins can create/update actors to be privileged, so check that:
        if request.method == 'POST' or request.method == 'PUT':
            check_privileged()
            # only admins have access to the workers endpoint, and if we are here, the user is not an admin:
            if 'workers' in request.url_rule.rule:
                raise PermissionsException(
                    "Not authorized -- only admins are authorized to update workers."
                )
        if request.method == 'POST':
            # POST to the messages endpoint requires EXECUTE
            if 'messages' in request.url_rule.rule:
                has_pem = check_permissions(user=g.user,
                                            actor_id=db_id,
                                            level=codes.EXECUTE)
            # otherwise, we require UPDATE
            else:
                has_pem = check_permissions(user=g.user,
                                            actor_id=db_id,
                                            level=codes.UPDATE)
    if not has_pem:
        logger.info("NOT allowing request.")
        raise PermissionsException(
            "Not authorized -- you do not have access to this actor.")