A simple user-facing web application using CHT's API that supports user management needs for CHT projects at scale.
For Developers:
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.
src/config
.config.json
file and specify the values as defined below.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 |
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. |
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 |
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 |
This tool is available via Docker by running docker compose up
. Set the Environment Variables.
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
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
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 |
Docker images are hosted on AWS's Elastic Container Registry (ECR). To publish a new version:
package.json
.main
.