Jello Framework

Data Access Control (DAC) is an important aspect of any data oriented solution. One of Jello's key features is its inline Authorization Model. With Jello you can assign different access levels for data elements at any resolution (Namespaces, Entities, Fields, Actions) and specify who is authorized to access the data via the REST API.

You define an access control by adding @Accessible (or @Expose for data fields) annotation to a data element. These annotations affect only the elements accessed via REST API while the Java access scope is determined, as usual, by the Java access modifiers (public/protected/private).




Data Elements Access Granularity

By default, none of the data model elements is accessible via the REST API. In order to expose a data element you need to explicitly mark it as accessible. The @Accessible (or @Expose for data fields) annotation lets you specify which of the elements in your data model to expose.

Cascading access check: Whenever a REST request is trying to access a data element, Jello will start checking access, starting from the top of the model hierarchy. First the Namespace, then the Entity, and lastly the Fields and Actions. For example - in order to access a Field or an Action, The Entity must be marked as accessible and the Namespace must be accessible as well.


Namespace

Packages are accessible by default.

Add @Accessible (jello.security.Accessible) annotation to the package info file to restrict access to entities under specific namespace via REST API.

Example:

1
2
3
4
5
// File: demo/package-info.java
@Accessible(Role.ADMIN)
package demo;

import jello.security.Accessible;

Entity

Add @Accessible (jello.security.Accessible) annotation to an Entity class to mark the entity as a accessible via REST API.

Example:
1
2
@Accessible
public class Product extends JelloEntity {

Note: Entity class can be marked, at the same time, as private for internal Java scope and as @Accessible for external REST scope.


Field

Add @Expose (jello.annotation.Expose) annotation to a data Field class to mark the field as a accessible via REST API.

Example:
1
2
@Expose
private Double price;

Note: Fields can be marked, at the same time, as private for internal Java scope and as @Expose for external REST scope.


Action

Add @Accessible (jello.security.Accessible) annotation to a public method to mark the method as an accessible Action via REST API.

Example:
1
2
@Accessible
public static List<Product> getProductsByRating(Integer rating) {

Note: The @Accessible annotation has no effect on none public methods. Jello annotation processor should issue an error upon such cases.


Authorization Role Types

Specifies which Role is authorized to access the data.

Role Syntax Description
ALL [default] jello.security.Role.ALL Allow access for all users, both authenticated and unauthenticated (Guests).
USER jello.security.Role.USER Allow access for authenticated users.
ADMIN jello.security.Role.ADMIN Allow access to user logged-in as Administrator.
SYSTEM jello.security.Role.SYSTEM Allow access for system calls such as Scheduled tasks and others
OWNER jello.security.Role.OWNER Allow access to the user who created the Instance. Tests against the createdBy Audit field.
Role Based Group Role ID - String Allow access to all users assigned to a specific role.
See: Define Custom Roles
Access By Action Security.ByAction + method full path Allow access by specific action

Syntax:

@Accessible(role) | 
@Accessible({role1, ....}) |
@Accessible(
   retrieve = role | {roles},
   create =   role | {roles}",
   update =   role | {roles},
   query =    role | {roles},
   delete =   role | {roles}
)

@Expose(role) | 
@Expose({role1, ....})

Examples:

1
@Accessible(Role.ALL) // Default, Same as @Accessible with no parameters

1
2
@Expose({Role.OWNER, "ManagerRole"})
private Integer salary;

1
2
@Accessible({Role.ADMIN, Role.SYSTEM})
public static String createCatalog() {

1
2
3
4
5
6
7
8
@Accessible(
   retrieve = Role.ALL,
   create = "AppAdminRole",
   update = { Role.ADMIN, Role.OWNER, Security.ByAction + "app.partners.SendInvite" },
   query = Role.USER,
   delete = { Role.ADMIN, Role.SYSTEM}
)
public class Supplier extends JelloEntity {

Note: When you set an Instance level access rule such as OWNER role, Jello will add an implicit 'filter by user' to each select request to ensure all REST requests are always secured. Most of the select methods available in the JAVA API execute 'secured' select query unless suggested otherwise in the method name, e.g JelloModel.unsecureSelectWithParameters(...).


REST API Method Privilege

REST API Method Description
Any [default] Applies to any of the REST API Methods.
Retrieve Privilege to retrieve a single Entity's Instance.
Query Privilege to Query an Entity's data set.
Create Privilege to Create a single Entity's Instance.
Update Privilege to Update a single Entity's Instance.
Delete Privilege to Delete a single Entity's Instance.

To be able to Delete By Query, both Query and Delete privileges must be given.


Examples:

1
2
@Accessible(Role.ADMIN)
public class Supplier extends JelloEntity {

1
2
3
4
5
6
7
8
@Accessible(
   retrieve = Role.ALL,
   create = Role.ADMIN,
   update = Role.ADMIN,
   query = Role.ALL,
   delete = Role.ADMIN
)
public class Supplier extends JelloEntity {


Define Custom Roles

Jello provides two core entities under jello.security to managed roles. These entities are accessible only for the app administrator.

jello.security.Role - you can add custom roles by providing a unique role name identifier.

jello.security.UserRole - you can assign users to a custom role by adding a UserRole instance that specifies the user ID and the role name.


security Role Entity
security UserRole Entity

Handle User login and authentication

Jello provides a Userprofile REST service that you can call from the client to get details on the logged in user. It returns a jello.services.UserProfile.Profile object as shown below:

REST call:

GET /jello/data/jello.services/UserProfile/whoAmI()

Response in case of logged in user:

result: {
	user: "John@Doe.org",
	isAdmin: false,
	roles: [
		"BusinessPartner",
		"ContentEditor"
	],
	logoutLink: "/_ah/logout?continue=/"
}

Response in case of guest user:

result: {
	isAdmin: false,
	roles: [ ],
	loginLink: "/_ah/login?continue=/"
}

Last updated March 12, 2019.