From 09971b7166fe2beee636cc0591b61d953217547d Mon Sep 17 00:00:00 2001 From: jonathanbataire Date: Mon, 13 Jan 2025 17:45:17 +0300 Subject: [PATCH 01/11] v1 --- src/config/chis-ug/config.json | 110 ++++++++++++++++++++++++------ src/lib/cht-session.ts | 6 +- src/liquid/app/config_upload.html | 67 ++++++++++++++++++ src/liquid/app/form_switch.html | 3 + src/liquid/app/nav.html | 8 ++- src/routes/app.ts | 45 +++++++++++- src/server.ts | 4 ++ 7 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 src/liquid/app/config_upload.html diff --git a/src/config/chis-ug/config.json b/src/config/chis-ug/config.json index 0dd1e1a7..f5dd055d 100644 --- a/src/config/chis-ug/config.json +++ b/src/config/chis-ug/config.json @@ -16,7 +16,94 @@ ], "contact_types": [ { - "name": "health_center", + "name": "c40-parish", + "friendly": "Parish", + "contact_type": "person", + "user_role": ["chew"], + "username_from_place": true, + "deactivate_users_on_replace": true, + "hierarchy": [ + { + "friendly_name": "Health Facility", + "property_name": "HEALTHFACILITY", + "contact_type": "c30-district_hospital", + "type": "name", + "required": true, + "parameter": ["\\sH[ /]*F\\s"], + "level": 1 + } + ], + "replacement_property": { + "friendly_name": "Outgoing CHEW", + "property_name": "REPLACEMENT", + "type": "name", + "required": true + }, + "place_properties": [ + { + "friendly_name": "Parish Name", + "property_name": "name", + "type": "name", + "required": true, + "unique": "parent" + }, + { + "friendly_name": "Sub District", + "property_name": "sub_district", + "parameter": ["\\ssub\\s", "\\sdistrict\\s"], + "type": "name", + "required": false + }, + { + "friendly_name": "County", + "property_name": "county", + "type": "name", + "parameter": ["\\scounty\\s"], + "required": true + }, + { + "friendly_name": "Sub County", + "property_name": "sub_county", + "type": "name", + "parameter": ["\\ssub\\s", "\\scounty\\s"], + "required": true + } + ], + "contact_properties": [ + { + "friendly_name": "CHEW Name", + "property_name": "name", + "type": "name", + "required": true + }, + { + "friendly_name": "Phone Number", + "property_name": "phone", + "type": "phone", + "parameter": "UG", + "required": true, + "unique": "all" + }, + { + "friendly_name": "Date of Birth", + "property_name": "date_of_birth", + "type": "dob", + "required": true + }, + { + "friendly_name": "Sex", + "property_name": "sex", + "type": "select_one", + "parameter": { + "male": "Male", + "female": "Female" + }, + "required": true + } + ] + }, + { + "name": "c50-health_center", "friendly": "VHT Area", "contact_type": "person", "user_role": ["vht"], @@ -24,9 +111,9 @@ "deactivate_users_on_replace": true, "hierarchy": [ { - "friendly_name": "Health Center", - "property_name": "HEALTHCENTER", - "contact_type": "district_hospital", + "friendly_name": "Parish", + "property_name": "PARISH", + "contact_type": "c40-parish", "type": "name", "required": true, "parameter": ["\\sH[ /]*C\\s"], @@ -49,14 +136,6 @@ "required": true, "unique": "parent" }, - - { - "friendly_name": "District", - "property_name": "district", - "type": "name", - "parameter": ["\\sdistrict\\s"], - "required": true - }, { "friendly_name": "Sub District", "property_name": "sub_district", @@ -78,13 +157,6 @@ "parameter": ["\\ssub\\s", "\\scounty\\s"], "required": true }, - { - "friendly_name": "Parish", - "property_name": "parish", - "parameter": ["\\sparish\\s"], - "type": "name", - "required": true - }, { "friendly_name": "Village", "property_name": "village", diff --git a/src/lib/cht-session.ts b/src/lib/cht-session.ts index ae98e694..e542cbe5 100644 --- a/src/lib/cht-session.ts +++ b/src/lib/cht-session.ts @@ -29,6 +29,7 @@ export default class ChtSession { public readonly axiosInstance: AxiosInstance; public readonly sessionToken: string; public readonly chtCoreVersion: string; + public readonly isAdmin: boolean; private constructor(creationDetails: SessionCreationDetails) { this.authInfo = creationDetails.authInfo; @@ -36,6 +37,7 @@ export default class ChtSession { this.facilityIds = creationDetails.facilityIds; this.sessionToken = creationDetails.sessionToken; this.chtCoreVersion = creationDetails.chtCoreVersion; + this.isAdmin = this.facilityIds.includes(ADMIN_FACILITY_ID); this.axiosInstance = axios.create({ baseURL: ChtSession.createUrl(creationDetails.authInfo, ''), @@ -47,10 +49,6 @@ export default class ChtSession { } } - public get isAdmin(): boolean { - return this.facilityIds.includes(ADMIN_FACILITY_ID); - } - public static async create(authInfo: AuthenticationInfo, username : string, password: string): Promise { const sessionToken = await ChtSession.createSessionToken(authInfo, username, password); diff --git a/src/liquid/app/config_upload.html b/src/liquid/app/config_upload.html new file mode 100644 index 00000000..7d61e8ea --- /dev/null +++ b/src/liquid/app/config_upload.html @@ -0,0 +1,67 @@ +
+
+
+ + {% if errors %} +
+ {{errors.message}} +
+ {% endif %} + +
+ +

+
+
+ +
+
+ Cancel +
+
+
+ +
+ +
+
+ This action will override the current configuration. + For more infomation on how to create a configuration file see + documentation +
+
+ + +
+
+
\ No newline at end of file diff --git a/src/liquid/app/form_switch.html b/src/liquid/app/form_switch.html index bb7d5a0c..e2f13094 100644 --- a/src/liquid/app/form_switch.html +++ b/src/liquid/app/form_switch.html @@ -6,6 +6,7 @@ {% elsif op == "merge" %} Merge Two {% elsif op == "delete" %} Delete a {% elsif op == "edit" %} Edit + {% elsif op == "config" %} Upload Configuration file {% else %} New {% endif %} {% endcapture %} @@ -40,6 +41,8 @@ {% include "place/bulk_create_form.html" %} {% elsif op == "move" or op == "merge" or op == "delete" %} {% include "place/manage_hierarchy_form.html" %} + {% elsif op == "config" %} + {% include "app/config_upload.html" %} {% else %} {% include "place/create_form.html" %} {% endif %} diff --git a/src/liquid/app/nav.html b/src/liquid/app/nav.html index 802e88d4..76e1bcbc 100644 --- a/src/liquid/app/nav.html +++ b/src/liquid/app/nav.html @@ -77,7 +77,13 @@
- +
From 25dea7386ea0dd638b9504afc061fdbd55c5ddd4 Mon Sep 17 00:00:00 2001 From: jonathanbataire Date: Tue, 14 Jan 2025 11:47:56 +0300 Subject: [PATCH 06/11] clean up --- src/server.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index f16025f2..c19ad36f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -73,7 +73,8 @@ const build = (opts: FastifyServerOptions): FastifyInstance => { const chtSession = Auth.createCookieSession(cookieToken); if (!chtSession?.isAdmin && req.routeOptions.url === '/app/config') { reply.status(401).send({ error: 'unauthorized' }); - throw new Error('Unauthorized access to config. User must be admin'); + console.error('Unauthorized access to config. User must be admin'); + return; } req.chtSession = chtSession; req.sessionCache = SessionCache.getForSession(chtSession); From abbd43f6ca22e9fda8e1e36b5b290acbd8e0fb52 Mon Sep 17 00:00:00 2001 From: jonathanbataire Date: Thu, 20 Feb 2025 16:37:18 +0300 Subject: [PATCH 07/11] /config api --- src/config/index.ts | 4 +- src/lib/authentication.ts | 13 ++++++ src/liquid/app/config_upload.html | 67 ------------------------------- src/liquid/app/form_switch.html | 3 -- src/liquid/app/nav.html | 6 --- src/routes/api.ts | 37 +++++++++++++++++ src/routes/app.ts | 45 +-------------------- src/server.ts | 44 +++++++++++++++----- 8 files changed, 88 insertions(+), 131 deletions(-) delete mode 100644 src/liquid/app/config_upload.html create mode 100644 src/routes/api.ts diff --git a/src/config/index.ts b/src/config/index.ts index e17fb556..e8009a52 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -83,7 +83,7 @@ export class Config { public static async getContactType(name: string) : Promise { const {config} = await init(); - const contactMatch = config.contact_types.find(c => c?.name === name); + const contactMatch = config.contact_types.find(c => c.name === name); if (!contactMatch) { throw new Error(`unrecognized contact type: "${name}"`); } @@ -93,7 +93,7 @@ export class Config { public static getParentProperty(contactType: ContactType): HierarchyConstraint { const parentMatch = contactType.hierarchy.find(c => c.level === 1); if (!parentMatch) { - throw new Error(`hierarchy at level 1 is required: "${contactType?.name}"`); + throw new Error(`hierarchy at level 1 is required: "${contactType.name}"`); } return parentMatch; diff --git a/src/lib/authentication.ts b/src/lib/authentication.ts index c32c770a..aab5cbdc 100644 --- a/src/lib/authentication.ts +++ b/src/lib/authentication.ts @@ -1,6 +1,7 @@ import process from 'process'; import jwt from 'jsonwebtoken'; import ChtSession from './cht-session'; +import { Config } from '../config'; const LOGIN_EXPIRES_AFTER_MS = 4 * 24 * 60 * 60 * 1000; const QUEUE_SESSION_EXPIRATION = '96h'; @@ -57,4 +58,16 @@ export default class Auth { const { data } = jwt.verify(token, signingKey) as any; return ChtSession.createFromDataString(data); } + + public static async apiAuth (username: string, password: string, domain: string) { + const authInfo = await Config.getAuthenticationInfo(domain); + try { + const chtSession = await ChtSession.create(authInfo, username, password); + return chtSession; + } catch (e: any) { + console.error(`Login error: ${e}`); + return {}; + } + } + } diff --git a/src/liquid/app/config_upload.html b/src/liquid/app/config_upload.html deleted file mode 100644 index b94b8218..00000000 --- a/src/liquid/app/config_upload.html +++ /dev/null @@ -1,67 +0,0 @@ -
-
-
- - {% if errors %} -
- {{errors.message}} -
- {% endif %} - -
- -

-
-
- -
-
- Cancel -
-
-
- -
- -
-
- This action will override the current configuration. - For more infomation on how to create a configuration file see - documentation -
-
- - -
-
-
\ No newline at end of file diff --git a/src/liquid/app/form_switch.html b/src/liquid/app/form_switch.html index e2f13094..bb7d5a0c 100644 --- a/src/liquid/app/form_switch.html +++ b/src/liquid/app/form_switch.html @@ -6,7 +6,6 @@ {% elsif op == "merge" %} Merge Two {% elsif op == "delete" %} Delete a {% elsif op == "edit" %} Edit - {% elsif op == "config" %} Upload Configuration file {% else %} New {% endif %} {% endcapture %} @@ -41,8 +40,6 @@ {% include "place/bulk_create_form.html" %} {% elsif op == "move" or op == "merge" or op == "delete" %} {% include "place/manage_hierarchy_form.html" %} - {% elsif op == "config" %} - {% include "app/config_upload.html" %} {% else %} {% include "place/create_form.html" %} {% endif %} diff --git a/src/liquid/app/nav.html b/src/liquid/app/nav.html index 64771de6..56fb73ac 100644 --- a/src/liquid/app/nav.html +++ b/src/liquid/app/nav.html @@ -78,12 +78,6 @@