Giter VIP home page Giter VIP logo

authzed-ts's People

Contributors

swantzter avatar

Stargazers

 avatar

Watchers

 avatar  avatar

authzed-ts's Issues

[client] alternative usage pattern

There was some comparison of abstractions in the Autzed discord, this client currently opts for TS tuples with [objectType, objectId], but another pattern that came up, which might be fairly realistic to implement on top of this client using the same codegen output types processed another way and a proxy or some object with wildcard getters. Examples of the result, freely extraplorated by me based on the first one as example

p.document('id1').view.check(p.user('abc'))

p.document('id1').edit.assert(p.user('abc'))

p.document.view.resources(p.user('def'), { info: 'this is the caveat context' })

[generator] Resolve arrow references in permissions

Basically, we need recursion.

When an arrow reference (relation->relationOrPermission) is encountered we need to look at the relation on the current object definition, and from that expand the types it references until we have reached all possible object types that can be the subject type.

Given this schema:

definition user {}

definition robot {}

definition lev1 {
    relation member: user | robot
}

definition lev2 {
    relation rel: lev1
    relation direct_member: user
    permission member = rel->member + user
}

definition lev3 {
    relation rel: lev2 | user
    permission member = rel->member
}

to resolve the member permission on lev3 we need to look at the relation from the left hand side of the arrow expression: rel, which points to either a lev2 or a user.
We must then try to find the right hand side of the arrow expression on either of these relations.

On user it is not found either as a permission or relation. Thus we discard this branch

On lev2 however we find a permission named member, and, since it is a permission we must expand it.
It has a direct reference we can resolve to get our first path { objectType: 'lev2', relation: 'direct_member' } and another arrow expression we must expand the same way we just did. We look at the relation defined on lev2 that's references on the right hand side of this new arrow expression: rel, which points to a lev1

On lev1 we try to find a permission named member, we don't, so we try to find a relation named member and we do! this means our search is complete and we get our second path: { objectType: 'lev1', relation: 'member' }

these two relations gets added as the resulting array at the TODO marker here:

if (objRef.target) {
const key = `${objRef.name}->${objRef.target}`
// We've already processed this reference, but it might've been included again in another parenthesis or what have you
if (key in currentObj.permissions[permission.name]) continue
const resolvedRelation = currentObj.relations[objRef.name]
if (!resolvedRelation) throw new TypeError(`Left hand of arrow expression must reference a relation in the same object, '${key}' on '${definition.name}' does not`)
// TODO: resolveArrowReference(definitions.objects, resolvedRelation, objRef.target)
} else {

basically: currentObj.permissions[permission.name] ??= resolveArrowReference(whateverArgsAreNeeded)

[client] assertPermission

basically the same as checkPermission, but instead of returing true or false it throws if the permission isn't granted.

It's probably best implemented as a very thin wrapper over checkPermission and it might be possible to reference the types of checkPermission as to avoid having to compy-paste

[generator] Add CEL tokens to Lexer, skip caveat function body

As it stands the parser is unable to handle schemas with caveats with function bodies. After dome discussion it seems what needs to be done is simply adding all the tokens CEL has (or maybe just one token with a regex matching all currently uncovered CEL tokens, if you want to be lazy) and add them, and the existing tokens that are also valid zed tokens to a category token.

then you'd simply add a this.MANY(() => this.CONSUME(CelToken)) to the commented out line here:

public caveatDefinition = this.RULE('caveatDefinition', () => {
this.CONSUME(Caveat)
this.SUBRULE(this.typePath)
this.CONSUME(LParen)
this.AT_LEAST_ONE_SEP({
SEP: Comma,
DEF: () => {
this.SUBRULE(this.caveatParameter)
}
})
this.CONSUME(RParen)
this.CONSUME(LCurly)
// TODO: this.SUBRULE(this.caveatExpression)
this.CONSUME(RCurly)
})

The caveatExpression could then also be removed:

public caveatExpression = this.RULE('caveatExpression', () => {
// TODO: preferably we just skip this, I do'nt want to implement a CEL parser too
})
}

[client+generator] writePermissions should take tuples with subject relation

likely dependent on #3

Today given a schema

definition user {}

definition group {
  relation memeber: user
}

definition document {
  relation reader: user | group#member
}

We'd expect to be able to write the relation zedClient.defineWriteRelationship(['document', 1], 'reader', ['group', 1, 'member']), but here group is a forbidden subject type. maybe special typings are needed for the subject tuple in three-item form?

[generation] resolve subject relations

Currently if a relation is defined with the # in them, the actual subject types aren't resolved but instead the left hand side of the # gets added as a valid subject

What needs to happen in the code below is that if objRef.target != null, it should be resolved by looking at the object type named on the left hand side (objRef.name), finding a permission or relation on said object named the right hand side (objRef.target), if it's a permission it has to be expanded with the arrow expression logic from #2 until it boils down to one or more object types that can be added as subject types

for (const relation of definition.relations) {
currentObj.relations[relation.name] ??= {}
for (const objRef of relation.objectReferences) {
currentObj.relations[relation.name][objRef.name] ??= {
caveat: [],
wildcard: false
}
if (objRef.caveat) currentObj.relations[relation.name][objRef.name].caveat.push(objRef.caveat)
if (objRef.wildcard) currentObj.relations[relation.name][objRef.name].wildcard = true
}
}

It is likely this needs to happen in a second pass to be able to validate that everything exists - or we just skip validations for these and hope for the best

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.