Skip to content

medic/cht-user-management

Repository files navigation

CHT User Management Tool

Goal

A simple user-facing web application using CHT's API that supports user management needs for CHT projects at scale.

eCHIS Kenya Training Videos

For Developers:

Using this tool with your CHT Project

To use the User Management Tool with your CHT project, you'll need to create a new project configuration folder and follow some deployment steps.

Configuration

  1. Create a new folder in src/config.
  2. Create a config.json file and specify the values as defined below.
  3. Add reference to your configuration folder in src/config/config-factory.ts.
Property Type Description
domains Array Controls the list of instances which the user can login to
domains.friendly string Friendly name for the instance (eg. "Migori")
domains.domain string Hostname for the instance (eg. "migori-echis.health.go.ke")
domains.useHttp boolean Whether to make an insecure connection (http) to the hostname (defaults to false)
contact_types Array One element for each type of user which can be created by the system
contact_types.name string The name of the contact_type as it appears in the app's base_settings.json
contact_types.friendly string Friendly name of the contact type
contact_types.contact_type string The contact_type of the primary contact. As defined in base_settings.json
contact_types.contact_friendly string Friendly name of the primary contact type
contact_types.user_role string[] A list of allowed user roles. If only one is provided, it will be used by default.
contact_types.username_from_place boolean When true, the username is generated from the place's name. When false, the username is generated from the primary contact's name. Default is false.
contact_types.hierarchy Array Defines how this contact_type is connected into the hierarchy. An element with level:1 (parent) is required and additional elements can be provided to support disambiguation. See ConfigProperty.
contact_types.hierarchy.level integer The hierarchy element with level:1 is the parent, level:3 is the great grandparent.
contact_types.replacement_property Property Defines how this contact_type is described when being replaced. The property_name is always replacement. See ConfigProperty.
contact_types.place_properties Array Defines the attributes which are collected and set on the user's created place. See ConfigProperty.
contact_types.contact_properties Array Defines the attributes which are collected and set on the user's primary contact doc. See ConfigProperty.
contact_types.deactivate_users_on_replace boolean Controls what should happen to the defunct contact and user documents when a user is replaced. When false, the contact and user account will be deleted. When true, the contact will be unaltered and the user account will be assigned the role deactivated. This allows for account restoration.
contact_types.hint string Provide a brief hint or description to clarify the expected input for the property.
logoBase64 Image in base64 Logo image for your project

ConfigProperty

The ConfigProperty is a data structure used several times each config.json file. At a high level, a ConfigProperty defines a property on an object.

Property Type Description
friendly_name string Defines how this data will be labeled in CSV files and throughout the user experience.
property_name string Defines how the value will be stored on the object.
type ConfigPropertyType Defines the validation rules, and auto-formatting rules. See ConfigPropertyType.
parameter any See ConfigPropertyType.
required boolean True if the object should not exist without this information.

ConfigPropertyType

The ConfigPropertyType defines a property's validation rules and auto-formatting rules. The optional parameter information alters the behavior of the ConfigPropertyType.

Type Validation Rules Auto Formatting Rules Validator parameter
string Must be defined Removes double whitespaces, leading or trailing whitespaces, and any character which is not alphanumeric or ()\-' None
name Must be defined Same as string + title case + parameter behavior One or more regexes which are removed from the value when matched (eg. "parameter": ["\\sCHU"] will format this CHU into This)
regex Must match the regex captured by parameter Same as string A regex which must be matched to pass validation (eg. "parameter": "^\\d{6}$" will accept only 6 digit numbers)
phone A valid phone number for the specified locality Auto formatting provided by libphonenumber Two letter country code specifying the locality of phone number (eg. "parameter": "KE")
generated None. No user inputs. Uses LiquidJS templates to generate data None Details
select_one Single choice from a list of options Same as string None Dictionary where the keys are the option values and the values are the corresponding labels
select_multiple Multiple choice from a list of options Same as string None Same as select_one
none None None None

The Generated ConfigPropertyType

ContactProperties with type: "generated" use the LiquidJS template engine to populate a property with data. Here is an example of some configuration properties which use "type": "generated":

{
  "place_properties": [
    {
      "friendly_name": "CHP Area Name",
      "property_name": "name",
      "type": "generated",
      "parameter": "{{ contact.name }}'s Area",
      "required": true
    }
  ],
  "contact_properties": [
    {
      "friendly_name": "CHP Name",
      "property_name": "name",
      "type": "name",
      "required": true
    }
  ]
}

The user will be prompted to input the contact's name (CHP Name). The user is not prompted to input the place's name (CHP Area Name) because the place's name will automatically be assigned a value. In this example, if the user puts john as the contact's name, then the place will be named John's Area.

The data that is passed to the template is consistent with the properties defined in your configuration.

Variable Value
place Has the attributes from place_properties.property_name
contact Has the attributes from contact_properties.property_name
lineage Has the attributes from hierarchy.property_name

Deployment

This tool is available via Docker by running docker compose up. Set the Environment Variables.

Development

NodeJs with reloading code

Create an environment file by cp env.example .env. Change INTERFACE to 127.0.0.1 and otherwise see Environment Variables for more info.

If you don't have redis running locally, you can start it with:

docker compose -f docker-compose.redis.yml up -d

Then run:

npm run dev

or

npm run build
npm start

Docker with static code

To build the Docker images and run Docker Compose locally, run:

./docker-local-setup.sh build

If you just need to run the development environment without rebuilding the images run:

./docker-local-setup.sh

Environment Variables

The env.example file has example values. Here's what they mean:

Variable Description Sample
CONFIG_NAME Name of the configuration to use chis-ke
EXTERNAL_PORT Port to use in docker compose when starting the web server 3500
PORT For localhost development environment 3500
COOKIE_PRIVATE_KEY A string used to two-way encryption of main app cookies. Production values need to be a secret. Suggest uuidgen to generate 589a7f23-5bb2-4b77-ac78-f202b9b6d5e3
WORKER_PRIVATE_KEY A string used to two-way encryption sensitive data passed to workers. Recommend to be different from COOKIE_PRIVATE_KEY. Production values need to be a secret. Suggest uuidgen to generate 2b57pd5e-f272-og90-8u97-89a7589a7f23
INTERFACE Interface to bind to. Leave as '0.0.0.0' for prod, suggest '127.0.0.1' for development 127.0.0.1
CHT_DEV_URL_PORT CHT instance when in NODE_ENV===dev. Needs URL and port 192-168-1-26.local-ip.medicmobile.org:10463
CHT_DEV_HTTP 'false' for http 'true' for https false
REDIS_HOST Redis server hostname use 'redis' for docker redis
REDIS_PORT Redis server port 6379
CHT_USER_MANAGEMENT_IMAGE docker image for cht-user-management service (local development), leave empty to use published one cht-user-management:local
CHT_USER_MANAGEMENT_WORKER_IMAGE docker image for cht-user-management service (local development), leave empty to use published one cht-user-management-worker:local

Publishing new docker images

Docker images are hosted on AWS's Elastic Container Registry (ECR). To publish a new version:

  1. Update the version string in the package.json.
  2. Submit a PR and have it merged to main.
  3. Existing CI will push an image to ECR.