After deleting & rewriting relationship, related L...
# spicedb
y
after i deleted a relationship and then rewrite it, concerned API lookupResource' return conflicted with CheckPermission's return. Seems the LookupResource API missed a resource brought by rewritten relationship. to be more specific, here's my schema, and the attachment contains a graph describing the schema relationship.
Copy code
definition user {}

definition system {
    relation admin: user // Super administrator

    permission root_access = admin
}

definition application {
    relation belong_to: system
    relation manager: user  // Project manager
    relation member: user | user:* // Project member
    relation tourist: user // Visitor

    permission view = belong_to->root_access + manager + member + tourist
    /* Aggregate roles at this/upper level by permission, for lower level to call when assigning specific permissions */
    permission project_edit = belong_to->root_access + manager + member
    permission project_view = belong_to->root_access + manager + member + tourist
}

definition project {
    relation parent: application

    permission edit = parent->project_edit // project editing permission
    permission execute = parent->project_edit // project execution permission
    permission view = parent->project_view // project viewing permission
}

definition label {
    relation parent: system
    relation authorized_user: user | user:*

    permission edit = parent->admin
    permission access = authorized_user + parent->admin
}
the key is that user with the project_view permission for an application will have view permission for the project whose parent=application. I will rewrite project:X#parent@application:Y relationship's Y to Z(delete the original one and write a new one). If a user has project_view permission for both the application before and after the change, the result of using the lookupResource API should not change, but this is not the case. The lookupResource will miss the resources brought by the rewritten relationship.
and here's my code:
Copy code
@mod.route("/<project_id>/<app_key>/reparent", methods=["POST"])
@project_roles_required(licPermission.PROJECT_EDIT)
def reparent_project(project_id, app_key):
    try:
        # 将指定案例的parent更改为指定项目
        delete_relationship(
            resource_type=licObjectType.PROJECT,
            optional_resource_id=project_id,
            optional_relation=licRelation.PROJECT_PARENT,
            optional_subject_type=licObjectType.APP
        ) # 一个案例同时只能属于一个项目,所以要先删除所有的父级
        write_relationship(
            subject_type=licObjectType.APP,
            subject_id=app_key,
            relation=licRelation.PROJECT_PARENT,
            resource_type=licObjectType.PROJECT,
            resource_id=project_id,
        )
        p: DbProject = DbProject.objects(uid=project_id).first()
        p.reparent_flag = app_key
        p.save()
        return jsonify(code=0, msg="success")
    except Exception as e:
        logging.exception(e)
        return jsonify({})

https://cdn.discordapp.com/attachments/1138361069102968832/1138376707439599798/7669b6c9-7b2e-4cf4-aa3c-17ca91881f78.png

I queried auth data before and after reparent, here's my exec log:
Copy code
--------------------------------------------- [before reparent] lookupResource get 2919 resources ------------------------------------
INFO:root:[zedToken] {'GhUKEzE2OTE0ODA5NjE0NTg5MzYyNTE='} user:6185c6ae-a4dd-4d6d-97ad-94dba9301b05 have [role/permission] view over project:['000bebbb', '00223cc6', '0039275c', ...] [len]2919
--------------------------------------------- [before reparent] read_relationship 'project:f316a77a#parent@application:default' ------------------------------------
DEBUG:root:[read relationship condition] [resourceType] licObjectType.PROJECT [resourceID] f316a77a [relation/permission] licRelation.PROJECT_PARENT [subjectType] licObjectType.APP [subjectID] 
INFO:root:[zedToken] {'GhUKEzE2OTE0ODA5NjE0NTg5MzYyNTE='} [read relationship] success [['project:f316a77a#parent@application:default']]


--------------------------------------------- [reparent (1/2)] delete relationship 'project:f316a77a#parent@application:' ------------------------------------
DEBUG:root:[delete relationship filter] [resourceType] licObjectType.PROJECT [resourceID] f316a77a [relation/permission] licRelation.PROJECT_PARENT [subjectType] licObjectType.APP [subjectID] None
INFO:root:[zedToken] GhUKEzE2OTE0ODEwNzIzOTQ1MTM5MDU= [delete relationship]

--------------------------------------------- [reparent (2/2)] write relationship 'project:f316a77a#parent@application:JX3' ------------------------------------
INFO:root:[zedToken] GhUKEzE2OTE0ODEwNzI0MDM0NzQ2NDg= [relationship] project:f316a77a#parent@application:JX3 operate[OPERATION_TOUCH] write success
Copy code
--------------------------------------------- [after reparent], i can't find expected resource in lookupResource API, but checkPermission returns true, those two conflicted ------------------------------------
INFO:root:[zedToken] {'GhUKEzE2OTE0ODEwNzI0MDM0NzQ2NDg='} user:6185c6ae-a4dd-4d6d-97ad-94dba9301b05 have [role/permission] view over project:['000bebbb', '00223cc6', '0039275c', ...] [len]2918
INFO:root:[zedToken] GhUKEzE2OTE0ODEwNzI0MDM0NzQ2NDg= [permissionship]:PERMISSIONSHIP_HAS_PERMISSION project:f316a77a#view@licObjectType.USER:6185c6ae-a4dd-4d6d-97ad-94dba9301b05 
DEBUG:root:[read relationship condition] [resourceType] licObjectType.PROJECT [resourceID] f316a77a [relation/permission] licRelation.PROJECT_PARENT [subjectType] licObjectType.APP [subjectID] 
INFO:root:[zedToken] {'GhUKEzE2OTE0ODEwNzI0MDM0NzQ2NDg='} [read relationship] success [['project:f316a77a#parent@application:JX3']]
the question is that I reparent project:f316a77#parent from application:default to application:JX3, and user:6185c6ae-a4dd-4d6d-97ad-94dba9301b05 have root access after reparent, CheckPermission shows that user:6185c6ae-a4dd-4d6d-97ad-94dba9301b05 does have view permission over project:f316a77 as expected. But LookupResource filtered by
[permision] view [resource] project [subject]user:6185c6ae-a4dd-4d6d-97ad-94dba9301b05
missed this expected resource project:f316a77.
P.S. all API here set consistency as full_consistent
j
I tried to follow the above steps and was unable to reproduce. What datastore are you using and as you absolutely certain you're using fully consistent (or the zedtoken returned from the writes) for all calls?
this very much feels like one of your calls isn't using full consistencty
(although we would recommend using the zedtoken)
y
I just found that in a new environment I can't reproduce it, neither. I think this shows that there is some difference between the data in the production environment and the reproduction environment, rather than the way the API is called. However, I will take another look and if there is any useful information, I will sync it with you. Thank you.
j
sounds good
2 Views