Introduction#

Makumba focuses on combining query fragments to obtain high-performance systems with a minimum number of queries sent to the database back-end, while keeping its concerns about easy learnability and rapid development. The mak:list engine already combines query fragments for embedded mak:lists by combining their FROM and WHERE sections, but we found a need for a better formalization and sharing of query fragments across the system. The elementary concept of such formalization is the MDD function.

MDD functions#

A simple function for an MDD called Leveler that has a level integer field looks like

level=int
function(int a) { level+a }

Note

In principle, a function is inlined in queries whenever it is encountered in a projection or WHERE condition as follows: SELECT label.function($param) FROM Leveler label

Note

The above query is inlined like this: SELECT label.level + $param FROM Leveler label

Some properties of MDD functions:

  • If the underlying query language allows it, functions can use subqueries.
  • If functions wish to refer to the owner object, functions can use this which will be inlined with the label or the expression denoting the object in the query
  • If a function is not using MDD fields at all, then it is static and can be invoked like MDDname.function(params)
  • If functions wish to define labels, they can use a FROM section and if needed a WHERE section to constrain the labels defined.

Note

In principle it is possible to translate the functions into database-level stored procedures or equivalent but a lot can be achieved already just by inlining the functions.

The main uses of MDD functions are:

  • reuse of query code
  • query simplification and improved lisibility
  • authentication using well-known function names
  • authorisation using well-known function names
  • data view using well-known function names

Function specification#

The complete specification of function definition is as follows:

[sessionVar%]function([type parameter]*){ expression [FROM supplementaryLabels [WHERE condition]]} [: "errorMessage" ] [; comment] 
  • sessionVar may be used for MDDs that define actors (or those related to them) to indicate the name of a session variable where the function result will be stored. This is only possible for functions with no parameters. (this is currently implemented but may be deprecated)
  • parameter type can be either the primitive types (int, char, date, text, binary, boolean) or an MDD name
  • expression is a query language expression and may use MDD field names, this, function parameter names, supplementary labels (see below), other functions calls, actor invocations and $attributes from the query context
    • Since functions are inlined, recursive calls are not possible (this is not yet checked though)
    • $attributes are discouraged because using them would mean counting on "global variables", it is advised that they are passed as function parameters (in case of e.g. page parameters or page/request attributes), or that actor invocations are used to retrieve session attributes
  • supplementaryLabels may need to be defined, in which case a normal query language FROM section is used
  • sometimes conditions are needed to join the supplementary labels with this.
  • if the function is boolean and returns false, an error message will be needed to construct an exception e.g. when an actor() function fails (UnauthenticatedException) or when a canRead() function fails (UnauthorizedException). If that functions calls other functions, their error messages might be composed to provide a more accurate reason for failure.

Note

A static keyword may be added to function definitions.

Note

A return type may be added to function definitions.

Actor functions#

Actors are a special type of function that, when mentioned in queries or functions, may trigger authentication. An actor invocation looks like

actor(MDDName) 

i.e. it indicates which type (MDD) is the entity representing the actor. A query invoking an actor:

SELECT actor(Person).name 
SELECT obj.hasDoneJob(actor(Person)) FROM SomeType obj 

These queries are inlined as follows:

SELECT actor_Person.name FROM Person actor_Person WHERE actor_Person=$actor_Person
SELECT obj.hasDoneJob($actor_Person) FROM SomeType obj

(in the second example, the function hasDoneJob() will be inlined further)

$actor_Person is a special attribute retrieved from the query context. The query context handler will check for the attribute and if it is not defined, it will look in the MDD indicated by the actor attribute name (Person) for actor functions. Assuming that Person has a username and a passoword field, some actor functions may look like

username=char[255] 
password=char[255] 
actor(char[] user){username=user}
actor1(char[] admin){ username=admin }
actor2(char[] user, char []pass){ username=user AND password=pass } 

First, the context handler will look for a suitable function to use. For example if the attribute user is defined in the context, the first function (actor()) will match. However if both the attributes user and pass are defined in the context, the actor2() function will match (so the function with most matching parameters will be chosen). Finally, if the admin attribute is found, the actor1() function will match.

The functions above correspond to different authentication mechanisms that may be used. The first two functions use an external authentication mechanism, where the role of a correctly authenticated user is provided. In such a case, the Makumba query context handler will define an attribute with th role as name (user, admin) and the username as value. The third function (actor2()) will be useful when authentication is managed by the web application (for example using the mak:login feature) and the authentication data is passed as request parameter, in this case they are expected to be called user and pass.

Once a function has been selected (say actor2()) the following query is ran:

SELECT x FROM Person x WHERE x.actor($user, $pass) 

which inlines to

SELECT x FROM Person x WHERE x.username=$user AND x.password=$pass 

Once the actor is authenticated, the $actor_Person attribute is put in the session part of the query context. It can be removed using mak:logout

<mak:logout actor="Person" /> 

Some fields of Person (the MDD declaring the actor) may also be put in the session, along with the results of functions with no parameters, and along with related objects.

Explicit authorisation#

Explicit authorisation constraints are associations between web application paths and query language expressions. When an access is made to a resource whose path matches an authorisation constraint (partial matches supported, longest match considered), the corresponding expression is evaluated. If the expression produces an error (like UnauthenticatedException), that will be handled. If the exception returns 0, false or null an UnauthorizedException is raised with an error message indicated in the constraint.

Currently explicit authorisation constraints can be put in the file Makumba.conf (see the configuration documentation). Authorisation constraints looks like:

authorize%/={actor(Person)}
authorize%/admin=(char[]admin){actor(Person).username=admin} You are not an administrator  

The first example makes the whole site accessible to users who can authenticate as a Person actor.

The second example makes the /admin part of the site accesible only if there is an admin attribute in the context, and if that is the username of the Person actor. If any constraint fails, an UnauthorizedException will be raised. The second example also shows how to indicate a specific message for the exception, which will then be displayed to the user.

Implicit authorisation #

Implicit authorisation constraints are defined in functions like canRead(), canInsert(), canUpdate(), canDelete() in the respective MDDs. Only canRead() is honoured right now. These functions will be used whenever a mak:list, mak:object or mak:*Form attempts to view, create, change or delete an object of the respective type. The following features are partially implemented:

  • filter out from mak:list and mak:object objects that the user is not authorized to see, but do not r|aise any exception if there are such objects.This will probably be the default for mak:list

  • not link to a page that is not authorized

Query context#

A query execution context is a set of known attributes. In the case of JSP this concept maps on the page, request, and session attributes, as well as request parameters. If however application logic is executed before launching a JSP, the context will be made of the session and request attributes and of request parameters. This is managed by two different query context handlers (implementing the interface Attributes) and other such handlers can be defined.

Actor functions define a special type of session attributes that are computed based on other attributes from the query context.

CategoryDocumentation


Add Comment
« This page was last updated on April 4 2016