Partial Table Access: app and context
Each Right has two attributes called app and context. If you inspect the available Rights for the Ocean Core Services, you will notice that all Rights have * as the value of these two attributes. So, why are they there?
Sometimes you need to restrict a user's access to a particular table to a subset of records. For instance, some users might be given the right to change the UI strings for an application, whilst others may be given read access only to the same strings in that application.
The app and context attributes specify that the Right is applies only to records which match the app and context attributes. This happens automatically, behind the scenes so to speak: whenever the backend code requests all available records, or a specific record or set of records, the result is constricted to the set specified by the app and context combinations to which the ApiUser has access.
In this way you create logical applications and, optionally, logical contexts within each such application. What constitutes an app is entirely up to you; it's merely a logical organisation of records and doesn't need to correspond to a real world application. The same goes for the context, which can be seen as a subapp or logical area of the app. Either attribute (but not both) may be wildcarded in the Right.
For instance, let's assume that you are creating a web application in Ocean, and you want to use the CMS service to store the strings for its user interface. You also want to grant certain users the ability to create and edit the UI strings for your app, which we could call webshop. The web shop application may furthermore be subdivided into one or more areas.
To support this, you would create a number of new Rights, the names of which would be something like the following:
cms:texts:self:GET:webshop:* cms:texts:self:GET*:webshop:* cms:texts:self:*:webshop:*
The first two new Rights would be assigned to end users of the webshop application; they grant the right to read single resources and collections of Texts with an app value of webshop.
The third Right would be assigned to those ApiUsers who are the designated editors of UI strings in the webshop application: it grants full CRUD rights to those texts only.
The context could be used to create access rights for parts of an app, e.g.:
cms:texts:self:GET:webshop:* cms:texts:self:GET*:webshop:* cms:texts:self:*:webshop:error_strings cms:texts:self:*:webshop:main cms:texts:self:*:webshop:checkout
The above defines three admin rights, one for the error strings in the webshop, one for the main content, and one for the checkout strings. This allows you to set up fine grained access rights to the same set of resources for different users and admins.
Whenever a resource request has been granted by means of a Right containing non-wildcarded app and context values, Ocean will restrict access by means of extra SQL conditions for all accesses to that table. The support for this is built into the ocean-rails gem's handling of collections, and also into the generators used to set up Ocean resources.
Setting up support for app and context
The Text resource already supports app and context fully. To set up your own resource to support partial table access, you need to add database columns for app and context, typically through a Rails migration such as the following:
class AddAppAndContext < ActiveRecord::Migration def change add_column :doodads, :app, :string add_column :doodads, :context, :string end end
Controller resource finder
Access to resource collections is automatically restricted by the Ocean collection handling logic, so there's nothing to configure there. It will simply work. To restrict accesses to individual resources in GET, PUT, and DELETE operations, you must go to the bottom of the controller for the resource and locate the auto-generated finder function. It looks something like this:
private def find_doodad @doodad = Doodad.find_by_id params[:id] # If your table has app and context columns and you have created Rights utilising them, # comment out the line above this comment and uncomment the following one: #@doodad = add_right_restrictions(Doodad.where(id: params[:id]), @right_restrictions).first return true if @doodad render_api_error 404, "Doodad not found" false end
All you need to do is comment out one line and uncomment another. You can of course also delete the commented-out lines, yielding:
def find_doodad @doodad = add_right_restrictions(Doodad.where(id: params[:id]), @right_restrictions).first return true if @doodad render_api_error 404, "Doodad not found" false end
That's all you need to do. Accesses to apps and contexts without authorisation of a corresponding Right will now simply return 404s.