Handles scopes logic.
Scopes are case-sensitive strings without any whitespace, that represent authorization access. From OAuth2 RFC (https://tools.ietf.org/html/rfc6749#section-3.3):
The value of the scope parameter is expressed as a list of space- delimited, case-sensitive strings. The strings are defined by the authorization server. If the value contains multiple space-delimited strings, their order does not matter, and each string adds an additional access range to the requested scope.
scope = scope-token ( SP scope-token ) scope-token = 1( %x21 / %x23-5B / %x5D-7E )
In order to manage fine-grained authorizations, this lib uses a convention for scope formats. For example, we often need to distinguish between a full scope that will provides full access to some resource, and read-only access. Sometimes we also want to limit the access to some sub-resource. Here are some examples of our convention:
users
full access to users resource
users/profile
access to users profile only
users/profile:read
access to users profile read-only
users/profile/email:write
access to users profile only email write-only
Mainly :
is only authorized to split between access read/write/rw
(nothing implies rw).
Sub-resources can be separated by /
.
This library provides helper functions to check that
a given scope will also grant e.g. users/profile/email
and users/profile:read
.
We also provide helpers to normalize sets of scopes:
(normalize-scopes #{"users" "users/profile/email:read" "admin"}) #{"users" "admin"}
...as users/profile/email:read
is redundant, it is removed.
Note that scopes are meant to be used in an OAuth2 access in mind, and thus are generally manipulated as a set of scopes.
scopes that do not have any subpath are called root scopes.
This is important because it is easy to add, union scopes. But it is generally impossible to remove just a sub-scope as it would mean we should know all the sub-paths of some root-scope and add the difference.
Scope are additive by nature.
Handles scopes logic. Scopes are case-sensitive strings without any whitespace, that represent authorization access. From OAuth2 RFC (https://tools.ietf.org/html/rfc6749#section-3.3): > The value of the scope parameter is expressed as a list of space- > delimited, case-sensitive strings. The strings are defined by the > authorization server. If the value contains multiple space-delimited > strings, their order does not matter, and each string adds an > additional access range to the requested scope. > > scope = scope-token *( SP scope-token ) > scope-token = 1*( %x21 / %x23-5B / %x5D-7E ) In order to manage fine-grained authorizations, this lib uses a convention for scope formats. For example, we often need to distinguish between a full scope that will provides full access to some resource, and read-only access. Sometimes we also want to limit the access to some sub-resource. Here are some examples of our convention: `users` full access to users resource `users/profile` access to users profile only `users/profile:read` access to users profile read-only `users/profile/email:write` access to users profile only email write-only Mainly `:` is only authorized to split between access read/write/rw (nothing implies rw). Sub-resources can be separated by `/`. This library provides helper functions to check that a given scope will also grant e.g. `users/profile/email` and `users/profile:read`. We also provide helpers to normalize sets of scopes: >>> (normalize-scopes #{"users" "users/profile/email:read" "admin"}) #{"users" "admin"} ...as `users/profile/email:read` is redundant, it is removed. Note that scopes are meant to be used in an OAuth2 access in mind, and thus are generally manipulated as a set of scopes. scopes that do not have any subpath are called _root scopes_. This is important because it is easy to add, union scopes. But it is generally impossible to remove just a sub-scope as it would mean we should know all the sub-paths of some root-scope and add the difference. Scope are additive by nature.
(accepted-by-scopes scopes required)
scopes
should be strings.
if none of the string contains a /
nor a :
.
It works as is a subset of.
:scopes #{"foo" "bar"} only people with scopes which are super sets of #{"foo" "bar"} will be allowed to use the route.
scopes are considered as path with read/write access. so "foo/bar/baz:read" is a sub-scope of "foo" and of "foo:read".
So the more precise rule of access is. All mandatory scopes must be sub-scopes of at least one user scopes.
Also mandatory the scopes and required should be normalized
`scopes` should be strings. if none of the string contains a `/` nor a `:`. It works as is a subset of. :scopes #{"foo" "bar"} only people with scopes which are super sets of #{"foo" "bar"} will be allowed to use the route. scopes are considered as path with read/write access. so "foo/bar/baz:read" is a sub-scope of "foo" and of "foo:read". So the more precise rule of access is. All mandatory scopes must be sub-scopes of at least one user scopes. Also mandatory the scopes and required should be normalized
(access-granted scopes required)
Checks that the first parameter contains all the required scopes given as second parameter.
Checks that the first parameter contains all the required scopes given as second parameter.
(add-scope scope scopes)
Add the scope to a set of scopes.
Add the scope to a set of scopes.
(is-sub-list? lst super-lst)
Does super-lst
begin with lst
?
Does `super-lst` begin with `lst`?
(is-subscope? scope-to-check super-scope)
Returns whether the scope-to-check
is a subscope of the super-scope
Returns whether the `scope-to-check` is a subscope of the `super-scope`
(normalize-scopes scopes)
Given a set of scopes, remove reduntant ones, and merge them by access if possible.
Given a set of scopes, remove reduntant ones, and merge them by access if possible.
(raw-repr-scope-disj rscopes rs-to-remove)
Removes a scope from a set of scopes.
Removes a scope from a set of scopes.
(repr-is-strict-subpath? r1 r2)
Return whether the first argument is strictly a sub-path of the second argument.
Return whether the first argument is strictly a sub-path of the second argument.
(repr-is-subscope? scope-to-check super-scope)
Returns whether the scope-to-check
is a subscope of the super-scope
Returns whether the `scope-to-check` is a subscope of the `super-scope`
(repr-is-subsummed repr-scope repr-scopes)
Return whether a scope is contained by all the scopes.
Examples that return true:
(is-subsummed "foo" #{"foo"}) (is-subsummed "foo:read" #{"foo"}) (is-subsummed "foo/sub/scope" #{"foo"}) (is-subsummed "foo/sub/scope:read" #{"foo"})
Examples that return false:
(is-subsummed "foo" #{"foo:read" "bar"}) (is-subsummed "foo:read" #{"foo:read" "bar"}) (is-subsummed "foo/sub/scope" #{"foo:read"})
Return whether a scope is contained by all the scopes. Examples that return true: (is-subsummed "foo" #{"foo"}) (is-subsummed "foo:read" #{"foo"}) (is-subsummed "foo/sub/scope" #{"foo"}) (is-subsummed "foo/sub/scope:read" #{"foo"}) Examples that return false: (is-subsummed "foo" #{"foo:read" "bar"}) (is-subsummed "foo:read" #{"foo:read" "bar"}) (is-subsummed "foo/sub/scope" #{"foo:read"})
(repr-scope-disj repr-scopes rs-to-rm)
Remove a scope for a set of scopes. Will throw an exception if the scope to remove is a subscope of some scope in the scopes set.
Remove a scope for a set of scopes. Will throw an exception if the scope to remove is a subscope of some scope in the scopes set.
(repr-scope-intersection r1 r2)
Returns the maximal intersection between two scopes reprs.
(to-scope-repr "foo:write")
and (to-scope-repr "foo/bar")
=> (to-scope-repr "foo/bar:write")
Returns the maximal intersection between two scopes reprs. `(to-scope-repr "foo:write")` and `(to-scope-repr "foo/bar")` => `(to-scope-repr "foo/bar:write")`
(repr-scope-remove rs rs-to-remove)
While inputs should be in repr form,
removes the single scope rs-to-remove
from the single scope rs
.
Returns nil
if the two scopes do not intersect.
If the operation is not possible (for example, remove foo/bar
from foo
)
this function throw an exception.
If the two scopes intersect for the path but their access is different that
mean some access should be remove. As exemple, removing foo:write
from
foo/bar/baz
should endup with foo/bar/baz:read
.
While inputs should be in repr form, removes the single scope `rs-to-remove` from the single scope `rs`. Returns `nil` if the two scopes do not intersect. If the operation is not possible (for example, remove `foo/bar` from `foo`) this function throw an exception. If the two scopes intersect for the path but their access is different that mean some access should be remove. As exemple, removing `foo:write` from `foo/bar/baz` should endup with `foo/bar/baz:read`.
(repr-scopes-intersect? r1 r2)
Returns whether r1 and r2 intersect.
For example: (to-scope-repr foo:write)
and (to-scope-repr foo/bar)
intersect, while neither of those scopes reprs is a subscope of another.
Returns whether r1 and r2 intersect. For example: `(to-scope-repr foo:write)` and `(to-scope-repr foo/bar)` intersect, while neither of those scopes reprs is a subscope of another.
(repr-scopes-intersecting rs-1 rs-2)
Asymmetrical operation; returns the list of first scopes repr that intersect with some scopes repr of the second set of scopes repr.
Asymmetrical operation; returns the list of first scopes repr that intersect with some scopes repr of the second set of scopes repr.
(repr-scopes-intersection sr1 sr2)
Return the intersection between two set of scopes.
Return the intersection between two set of scopes.
(repr-scopes-missing scopes-1 scopes-2)
Return the list of scopes-1
that is not in scopes-2
Return the list of `scopes-1` that is not in `scopes-2`
(root-scope scope)
Returns the root of a scope.
(root-scope "foo/bar:read") foo
Returns the root of a scope. >>> (root-scope "foo/bar:read") foo
(safe-scopes-expand scopes aliases)
Same as scope expand but return nil instead of throwing and exception if a scope alias is missing
Same as scope expand but return nil instead of throwing and exception if a scope alias is missing
(scope-difference scopes scopes-to-remove)
Very similar to scopes-missing
, but taking care of throwing an exception if
some sub-scope cannot be removed. This would prevent an error when trying to
reduce a set of scopes.
(scope-difference #{"foo/bar"} #{"foo:write"}) => #{"foo/bar:read"}
keep foo/bar but removed all :write from super-scope foo.
Very similar to `scopes-missing`, but taking care of throwing an exception if some sub-scope cannot be removed. This would prevent an error when trying to reduce a set of scopes. (scope-difference #{"foo/bar"} #{"foo:write"}) => #{"foo/bar:read"} keep foo/bar but removed all :write from super-scope foo.
(scope-disj scopes scope-to-remove)
Remove a scope from a set of scopes. Throw an error if trying to remove a subscope of an existing scope.
Remove a scope from a set of scopes. Throw an error if trying to remove a subscope of an existing scope.
(scope-intersection scope-1 scope-2)
Returns the maximal intersection between two scopes.
foo:write
and foo/bar
=> foo/bar:write
Returns the maximal intersection between two scopes. `foo:write` and `foo/bar` => `foo/bar:write`
(scope-root scope)
Displays the root of a scope.
(scope-root "foo/bar:read") foo
Displays the root of a scope. >>> (scope-root "foo/bar:read") foo
(scope-union scopes-1 scopes-2)
Unionize two set of scopes.
Unionize two set of scopes.
(scopes-compress scopes aliases)
Given a set of scopes and a dictionary of scopes aliases use a fast heuristic to compress scopes with scope aliases.
It is more important to have a fast function than an efficient one. The best possible compression is clearly an NP-complete problem.
What we do, we first sort aliases by the size of string that would be generated to list all the scopes. So for example:
{"+foo" {"x" "y"}
"+bar" {"very-long-name-for-a-scope"}
}
the scope alias +bar will be preferred as even if the set contain fewer elements, the sum of the length of the scopes in the scopes set is longer.
Given a set of scopes and a dictionary of scopes aliases use a fast heuristic to compress scopes with scope aliases. It is more important to have a fast function than an efficient one. The best possible compression is clearly an NP-complete problem. What we do, we first sort aliases by the size of string that would be generated to list all the scopes. So for example: ``` {"+foo" {"x" "y"} "+bar" {"very-long-name-for-a-scope"} } ``` the scope alias +bar will be preferred as even if the set contain fewer elements, the sum of the length of the scopes in the scopes set is longer.
(scopes-expand scopes aliases)
Given a set of scopes containing scope aliases expand them.
Scopes aliases will be replaced, so the output of scopes-expand should not contain any scope alias.
If some scope alias is missing in the scope-aliases-map, scope expand will throw an exception.
Given a set of scopes containing scope aliases expand them. Scopes aliases will be replaced, so the output of scopes-expand should not contain any scope alias. If some scope alias is missing in the scope-aliases-map, scope expand will throw an exception.
(scopes-intersect? scope-1 scope-2)
Returns whether scope-1 and scope-2 intersect.
For example: foo:write
and foo/bar
intersect while
neither of those scope is a subscope of another.
Returns whether scope-1 and scope-2 intersect. For example: `foo:write` and `foo/bar` intersect while neither of those scope is a subscope of another.
(scopes-intersecting scopes-1 scopes-2)
Asymmetrical operation; returns the list of first scopes that intersect with some scopes of the second set of scopes.
Asymmetrical operation; returns the list of first scopes that intersect with some scopes of the second set of scopes.
(scopes-intersection scopes-1 scopes-2)
Return the intersection between two set of scopes.
Return the intersection between two set of scopes.
(scopes-length scopes)
Return the sum of the length of string in a set of scopes.
Return the sum of the length of string in a set of scopes.
(scopes-missing scopes-1 scopes-2)
Return the elements of the first set of scopes, removing those in the second set of scopes
Return the elements of the first set of scopes, removing those in the second set of scopes
(scopes-subset? required scopes)
Flipped version of scopes-superset?. Returns true if the first set is a subset of the second set of scopes.
Flipped version of scopes-superset?. Returns true if the first set is a subset of the second set of scopes.
Returns true if the first set of scopes is a superset of the second set of scopes.
This is another name for access-granted
function
Returns true if the first set of scopes is a superset of the second set of scopes. This is another name for `access-granted` function
(to-scope-repr txt)
Transforms a textual scope as an internal representation to help check rules, typically:
"foo" {:path ["foo"] :access #{:read :write}}
"foo/bar/baz:write" {:path ["foo" "bar" "baz"] :access #{:write}}
Transforms a textual scope as an internal representation to help check rules, typically: > "foo" {:path ["foo"] :access #{:read :write}} > "foo/bar/baz:write" {:path ["foo" "bar" "baz"] :access #{:write}}
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close