PKG-INFO Format --------------- PKG-INFO should be a [YAML](http://www.yaml.org/spec/) file with the following key-value items. ### `entry-point` Entry-point is *mandatory*. The value refers to the entry point of the application code from the framework. Value of the entry-point should in the following format module.path:callable_name For example, if the entry point callable `app_entry(state)` is in `aalam_base.main` module, the entry point will be aalam_base.main:app_entry ### `statics-url` statics-url is *optional* It is the prefix of the URL on which all the static files are served. The static resource can be accessed with the prefix followed by the path of the file. The absolute path of the file be obtained with the help of `statics-path` value. Example, if the prefix is `///s` and the file is installed in `/images/static.png`, the URL to this resource will be like `///s/images/static.png`. The static resources that are not served through URLs starting with this prefix, has to have a URL route registered for the same. With this setting, the application need not register explicit URLs to serve static resources. The framework will automatically control the response to the request of these static resources. ### `statics-path` `statics-path` is *mandatory* when `statics-url` is used. Otherwise not required. It contains the name of the directory under which all the static files are installed. The directory name should be relative to the installed root. For example, if the static files are all installed in `$ROOT/resource/statics/`, value for this will be `resource/statics` The framework derives the path of the resource with the help of the URL. For example, for a URL `/aalam/base/s/contacts/script.js` with the `statics-url` as `/aalam/base/s`, the path of the file will be os.path.join(cfg.CONF.package_dir, statics_path, "contacts/script.js") ### `permissions` 'permissions' is *optional* The value to this another key-value dictionary. This describes the list of permissions that the application supports. Every permission name will have a group name.A permission is referred by `provider-code/app-code/group-name/permission-name`. The permission map should be in the following format permissions: permission-groups: group-name-1: "Group 1's description" group-name-2: "Group 2's description" . . group-name-n: "Group n's description" group-name-1: permission-name-11: "Permission 11's description" permission-name-12: "Permission 12's description" . . permission-name-1n: "Permission 1n's description" . . group-name-n: permission-name-n1: "Permission n1's description" . . permission-name-nn: "Permission nn's description" requires: provider-1/app-1: group-name-p1a1-1: - permission-p1a1-11 - permission-p1a1-22 group-name-p1a1-n: - permission-pa-nn provider-2/app-2: group-name-p2a2-1: - permission-p2a2-11 - permission-p2a2-22 group-name-p2a2-n: - permission-pa-nn The permissions map contains the list of dictionary objects. Out of all the keys, `permission-groups` and `requires` are standard. Rest of the key names are dynamic based on the keys in `permission-groups` object. Here, `requires` object contains the list of permissions that are defined in other applications but required by this application. Note that 'group-name' and 'permission-name' should contain only alpha numeric characters and the special character hyphen `-`, however it should not start with a hyphen. A real world example of the `permissions` value can be seen below. permission-groups: Journal-Books: "Journal Book management" Journal-Books: create: "Create a journal book" delete: "Delete a journal book" access: "Access book details" requires: aalam/base: Contacts: - create - delete The application in the above example defines the following set of permissions Journal-Books/create, Journal-Books/delete, Journal-Books/access It also needs the following permissions from the base application aalam/base/Contacts/create, aalam/base/Contacts/delete ### `messages` `messages` is *optional* The value of this item is a key-value dictionary object. This item defines the list of message templates used for sending alerts. For example,when an app is installed in a server, an alert will be posted to some users with a fixed template. Each key in the value refers to the name of a message group. Message can be grouped, so that it becomes easier for the users to follow/unfollow all the message in a group. Each message template is identified by it's `index` value. The index value should be unique across this message map. Format of `messages` is as below ```eval_rst .. code-block:: yaml messages: MessageGroup-1: - index: 0 body: Template value 1, {dynamic_variable} - index: 1 body: Template value 2, {dynamic_variable} MessageGroup-2 - index: 2 body: Template value 3, a static template - index: 3 body: Template value 4. ``` Here ,`body` contains the message template. Any dynamic value that needs to formatted on the template should be put within `{}`. The value for the dynamic variables will be given the application while posting the message. For example, when an application is stopped, the template can have the `{app_name}` as a dynamic variable and will supply the value for the `{app_name}` which is stopped, at the time of posting this message. A real world example will be like ```eval_rst .. code-block:: yaml message: WelcomeMessages: - index: 0 body: Welcome to this portal. You are the administrator to this portal. - index: 1 body: Welcome! You can check you permissions here. AppMessages: - index: 2 body: New app - {app_name} is installed by {user} - index: 3 body: '{app_name}' is uninstalled by '{user}' ``` In the above example, we have two groups. - `WelcomeMessages` are the messages that the application sends whenever a new user joins the portal. The index 0 message is used for posting the owner and index 1 is used for posting other users. - `AppMessages` are the messages sent when any app is installed or uninstalled. Items with `{}` will be replaced by relevant values. ### `settings` `settings` is *optional* The value to this item is a key-value dictionary object. This item defines the list of `settings` for an application. `settings` are variables for which the user chooses the values. A settings variable is of two types - Global > Global settings are variables that is applicable to the entire server and the values of which are same for all users. To modify a global setting, a user needs to have `aalam/base/Settings/modify-globals` permission. Example, date and time format is a global setting. - Personal > Personal settings are the variables that are user customizable. A user doesn't need any extra permission to modify personal settings. Example, choice of a theme's colour is a personal setting. The `settings` format is as below ```eval_rst .. code-block:: yaml settings: - code: short_form_descritpion. See "Code Specification" name: Detailed name, which will be seen by the user default: Default value of this setting property: see "Property Specification" type: Global/Personal help: Information on how to input the values validator: Method name to be invoked for validation. See "Method Specification" - Similiar to the above format ``` #### Code Specification Settings code is a short code for describing for a setting variable. The code value will not be displayed to the user.It is to identify the `setting` by the framework and other applications. It should abide by the following rules. - Can contain only alpha numeric and hyphen `-` characters. - Should not start with hyphen character. - It should be unique for an application. #### Property Specification: Every setting can have following property type - Number > Integer or decimal value - Text > String - Choices > Lets the user to choose from a list of choices. If the choice type and method are > - single, dropdown: A listbox will be displayed to choose the value > - single, boxes: A set of radio buttons will be displayed > - multiple, dropdown: List box with support for multiple selection will be displayed > - multiple, boxes: A set of check boxes will be displayed. Property will be of the following format ```eval_rst .. code-block:: yaml property: type: Ex. number/text/choices(??) number: max: Maximum value for a number, applicable only for number. This is optional. min: Minimum value for a number, applicable only for number. This is optional. text: max_len: Maximum length of text, applicable only for text. This is optional. choices: type: single/multiple, applicable only for choices. This is mandatory method: dropdown/boxes, applicable only for choices. This is mandatory. values: - value1 - value2 - value3 ``` #### Method Specification: This is the method that will be invoked by the framework whenever a setting is fed by the user. The method name should be of the format module.path:method_name The validator method should accept two parameters 1. `settings_code` The code defined for a setting in the application's settings map object. 2. `input_value` The value that was fed by the user for this `settings_code`. The validator method should return either of the following - `None` When the method finds the `input_value` to be valid for the `settings_code` - `String message` When the validator finds an error with the `input_value`, this message will be displayed to the user for further assistance. A sample validator can be seen below def color_validator(settings_code, input_value) : if input_value not in ['red', 'green', 'blue']: # Value is invalid, return an error message. return "Value should be either 'red', 'green' or 'blue'" # Value is valid, so return None return None ### `hooks` `hooks` are *optional*. Value should be a key-value dictionary. 'hooks' lists the set of hooks that an application is interested in. Please see the [python framework documentation](http://docs.aalam.io/_/pycommon/latest/hooks.html) for more information on hooks. Value contains just two keys. - `hook` > List of URLs in other applications that this application wants to hook. - `restrict` > List of URLs in this application that it desires to restrict being hooked by other applications. One can include exceptions to the restrictions. `hooks` format is as below. ```eval_rst .. code-block:: yaml hook: - url: Url to be hooked, See "Hook Url Format" app: App which has this URL in the format provider-code/app-code method: HTTP Method filter for the url handler: Hooker's handler to be invoked on hook, see "Hook callback" type: Before or After or Both (B | A | BA) - Same as above restrict: - url: The url to be restricted, See "Hook Url Format" method: The method of the url to be restricted type: (B | A | BA) to be restricted except: - provider-code-1/app-code-1 - provider-code-2/app-code-2 - provider-code-3/app-code-3 ``` #### Hook URL format If the URL needs to be matched statically, then a static url can be used. For example, if you want to hook `GET /aalam/base/user/user@test.test`, you can input the URL path directly. But if you want to include a wildcard match) you have to use /aalam/base/user/* The asterik `*` matches an element with the slashes `/ By setting this property to `True`, you mean that this web application can serve the `'/' (slash/root)` page for the public (anonymous) users.Server administrators can choose one such public rootable app from the list of their apps to serve it as a website for the public users as home page. Apps that are publicly rootable should have the routes registered for the same. > For example, if your app is public rootable, then you should be having a route for `'/'`. These routes work only for the anonymous users. For users who are authenticated, these routes will never be used. For authenticated users, routes starting with `///` alone will work. ``eval_rst .. note:: Except `'/'` all other routes should begin with `'/_/'`. Only then the requests will be routed to the public rootable app. `` The value should be added to the configuration like ```eval_rst .. code-block:: yaml properties: public_rootable: True ``` ### `depends` When your application depends on other applications, those dependecies must be listed under this section. These dependencies are used while installing or updating any application. Each dependency should be given in the following format. ```eval_rst .. code-block:: yaml depends: - provider_code: Provider code of the dependee app app_code: App code of the dependee app pattern: The version as is or a regex pattern to match more than one version ``` You can still use APIs for other apps from your application even without listing them under this section. But there is no guarentee that the API will be successfull. For example, the Aalam Invoicer app depends on Aalam Stock app. It should list the Stock app under its `depends` section for successful API transaction. But suppose that the Aaalam invoicer calls the API of a payment service application that is not listed under `depends` section,then there will be no guarentee that the API transaction will be successful.