A small but flexible API for controlling an authenticated client's access to resources.
Some use cases are listed at the bottom of this README.
All resources (subtypes of
AbstractResource) have an
Resources may also have fields other than
A client is a type (subtype of
AbstractClient) that represents an entity wishing to access some resources.
Clients may represent users, web apps, data storage clients, etc.
A client's access to a resource is determined by its
Permission for the resource.
Permission type is defined as:
struct Permission create::Bool read::Bool update::Bool delete::Bool expiry::DateTime end
Permissions created without an expiry are given an (almost) infinite expiry.
A client can loosely be thought of as a mapping from resources to
More precisely, the mapping is a hierarchy of 3 maps.
As we move up the hierarchy:
The levels are:
At the bottom of the hierarchy is the map from resource type to permission.
This allows the same permission to be applied to all resources with the same type.
For example a client may have read-only access to the entire local system.
In this case the resources are directories and files and the associated permission is
Permission(false, true, false, false, expiry).
In the middle of the hierarchy is the map from resource ID pattern (
Regexs) to permission.
This mapping overrides the permissions specified in the type-to-permission mapping.
Continuing our file system example, the same client could also have write access to a particular directory using this mapping.
At the top of the hierarchy is the map from resource ID to permission. This mapping allows access control for specific resources.
This framework allows both fine-grained and somewhat coarse access control within the same client, provided the permissions don't conflict within a level of the hierarchy (test for conflicts via
Here's a quick sample of the API:
# Allow cRud (read-only) access without expiry to resources with type resource_type setpermission!(client, resource_type, Permission(false, true, false, false)) # Allow CRUD (read/write) access for 5 minutes to resources with IDs starting with "mycollection/" setpermission!(client, r"mycollection/*", Permission(true, true, true, true, now() + Minute(5))) p = getpermission(client, resource) # Get the permission settings for the specific resource setexpiry!(client, now() + Hour(1)) # Set an expiry for all the resources that the client has access to haspermission(client, resource, :create) # True if the client has :create access to the resource permissions_conflict(client, "myresource") # True if the rules that define the client's access to the resource with ID "myresource" conflict
haspermission(client, resource, action) to determine whether the client has permission to act on the resource (create/read/update/delete).
action is one of
This package also provides
Each has the same signature, namely
(client, resource, args...).
Each works as follows:
nothingwhen creating/updating/deleting, and return
(true, value)when reading
(false, error message)when reading
(false, error message)when reading
In object storage, data is stored as objects and objects are grouped into buckets. The ObjectStores package defines a common API for object storage that allows the storage back-end to be swapped without changing any code.
Examples of object stores include:
This authorization framework is used to control access to buckets and objects.
Authorization.jl can be used to implement web-app sessions.
Suppose a user's access is determined by his/her subscription to an app.
Then, for example,
setpermission!(client, App, permission) sets permissions for all resources related to the app with type
setexpiry(client, expiry) can be used to set an expiry on all resources to which the client has access.
The client can then be used as the session object.
When a request comes in, the client and requested resource can be identified from the request (and perhaps server state).
Determining whether the client has permission to access the resource is then a matter of calling
If you are developing a new client for some resources and would like to use this framework:
Ensure that the type of your client is a subtype of
Concrete subtypes are required to include some mandatory fields - see the
You can also include fields that are specific to your client type.
Similarly, ensure that the types of your resources are subtypes of
Also ensure that your concrete subtypes of
AbstractResource have an
10 months ago