Skip to content

Commit

Permalink
Merge pull request #17 from undp/symsoft_notification_updates
Browse files Browse the repository at this point in the history
Updates to Notifications
  • Loading branch information
jtwalker2000 authored Feb 6, 2025
2 parents 9c93627 + 12653c5 commit eb16502
Show file tree
Hide file tree
Showing 43 changed files with 3,615 additions and 3,533 deletions.
56 changes: 52 additions & 4 deletions Phase2/clients/Auth/keycloak.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
var OidcHelper = require('openid-client-helper')
var jwt = require('jsonwebtoken')
const config = require('../Config/config.json')
const keycloak = require('../Config/keycloak.json')
const client = require('../Config/config.json').Client
const axios = require('axios')
const qs = require('qs')
const roleNames = require('../Config/config.json').roleNames

const realmUrl = keycloak['auth-server-url'] + 'realms/' + keycloak['realm']
const adminUrl = keycloak['auth-server-url'] + 'admin/realms/' + keycloak['realm']
Expand All @@ -23,6 +24,12 @@ const clientMetadata = {
post_logout_redirect_uri: clientUrl
}

const serviceUserMetadata = {
grant_type: 'client_credentials',
client_id: keycloak['resource'],
client_secret: keycloak['credentials']['secret']
}

const OidcHelperParams = {
issuerMetadata: issuerMetadata,
clientMetadata: clientMetadata,
Expand Down Expand Up @@ -59,6 +66,23 @@ const _getAuthTokenDecoded = (req) => {
return jwt.decode(userAuthz?.tokenSet?.access_token)
}

const getServiceUserToken = async () => {
let options = {
method: 'POST',
url: issuerMetadata.token_endpoint,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify(serviceUserMetadata)
}

let token = await axios(options)
.then(res => res.data.access_token)
.catch(err => console.error(err))

return token;
};

const getAccessToken = (req) => {
const userAuthz = req ? getAuthorization({ req }) : null;
return userAuthz?.tokenSet?.access_token;
Expand Down Expand Up @@ -137,14 +161,36 @@ const _getUsersByRole = async (role, clientId, adminToken) => {

return users
}
const _getUserById = async (id, adminToken) => {
let options = {
method: 'GET',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + adminToken
},
url: adminUrl + `/users/${id}`
}

let users = await axios(options)
.then(res => res.data)
.catch(err => console.error(err))

return users
}

const getReviewerEmails = async (reviewer_type = 'Registry_reviewer', adminToken) => {
// let clientId = await _getClientId(clientMetadata.client_id, adminToken);
let users = await _getUsersByRole("Registry_reviewer", "8c1d3780-36da-4146-bbd0-9c02c29fa4b9", adminToken)
const getReviewerEmails = async (reviewer_type = roleNames.REVIEWER, serviceUserToken) => {
let clientId = await _getClientId(clientMetadata.client_id, serviceUserToken);
let users = await _getUsersByRole(reviewer_type, clientId, serviceUserToken)

return users?.filter(user => user.email).map(user => user.email)
}

const getSubmitterEmail = async (submitterId, serviceUserToken) => {
let user = await _getUserById(submitterId, serviceUserToken)

return user.email;
}

module.exports = {
authorize,
redirect,
Expand All @@ -155,9 +201,11 @@ module.exports = {
getClient,
getAuthorization,
getAccessToken,
getServiceUserToken,
getClaims,
getWWWAuthenticateHeaderAttributes,
getReviewerEmails,
getSubmitterEmail,
getRoles,
getUserId
}
8 changes: 0 additions & 8 deletions Phase2/clients/Auth/roles.js

This file was deleted.

55 changes: 0 additions & 55 deletions Phase2/clients/Config/README.md

This file was deleted.

30 changes: 23 additions & 7 deletions Phase2/clients/Config/config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"Client" : {
"hostname": "https://clients.regitrust.axyom.co"
"hostname": "https://clients.regitrust.axyom.co/"
},
"MongoDB": {
"hostname": "127.0.0.1",
"PORT": "27017",
"dbName": "GCCN",
"dbName": "DBNAME",
"options": {}
},
"TRAIN": {
Expand All @@ -21,13 +21,29 @@
"trustFramework": "/testFW.zm.regitrust.axyom.co"
},
"Notifications": {
"host": "SMTP HOST",
"host": "SMTP Host",
"port": 25,
"username": "SMTP USERNAME",
"password": "SMTP PASSWORD"
"username": "USER",
"password": "PASSWORD"
},
"reCaptcha": {
"siteKey": "RECAPTCHA SITE KEY",
"secret": "RECAPTCHA SECRET"
"siteKey": "SITEKEY",
"secret": "SECRET"
},
"roleNames": {
"SUBMITTER": "Registry_submitter",
"REVIEWER": "Registry_reviewer",
"ONBOARDING_MANAGER": "Onboarding_manager",
"ADMIN": "Registry_admin"
},
"enrollmentReviewStatuses": {
"PENDING": "pending",
"APPROVED": "approved",
"REJECTED": "rejected"
},
"networkSubmissionStatuses": {
"PENDING": "Submitted",
"APPROVED": "Accepted and Published",
"REJECTED": "Rejected"
}
}
5 changes: 2 additions & 3 deletions Phase2/clients/Config/keycloak.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"realm": "RegiTRUST",
"realmAdminEmail": "REVIEWERS DISTIBUTION GROUP EMAIL",
"auth-server-url": "https://auth.regitrust.axyom.co/",
"auth-server-url": "keycloak-server-url",
"ssl-required": "external",
"resource": "RegiTRUST_Client",
"resource": "keycloak-client",
"verify-token-audience": true,
"credentials": {
"secret": "SECRET"
Expand Down
55 changes: 50 additions & 5 deletions Phase2/clients/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
# GCCNTrustRegistryNetwork
Updated to the phase 2 requirements
- Versioning of the Trust List and Trust Service Providers
= Onboarding Contact Form
- Identity and access updates
# Web Front End
_Last updated: January 2025_

The web front end provides a User Interface for managing the Trust List.

## Functionality Supported
- **Enrollment**: Provides a form to allow prospective TSP represntatives to submit an enrollment request. The onboarding staff at TSPA can review and acknowledge or defer the requests.
- **Network Entry Managment**: Authrized TSP staff can submit Trust List entries with multiple services. The entries can be reviewed, approved and published by TSP Reviewers.
- **Versioning of Trust List**: System provides ability to edit Trust List entries.

## Tech Stack
At the time of this commit Node v.22.5.1 is used.

## Installation and Deployment
Node application deployment for the chosen platform.
In test environment is is running as a systemd service, exposed to internet via an nginx server.

## Folder Structure
```
/c:/[Project Directory]
├── README.md
├── /Config/
└── config.json **Configurations and constants for other services i.e. reCaptcha, email system, etc
└── keycloak.json **Configurations for keycloak
├── /Auth/
└── keycloak.json *Keycloak API implementations
├── /data/
└── formFields/ *Schema for form building (mapped using ./views/forms/includes/formFieldsRenderer.pug)
└── MongoDB/ *Mongo configs and schema definitions
└── submissionFormatting/ *Form submission helpers
└── submissions/
└── TRAIN/ *TRAIN API implementations
├── /notifications/ * Holds logic for sending email notifications and the email templates to use
├── /routes/ * Controller. Holds directories of main paths and thier child endpoints
├── /Views/
```

## Important Notes

### Enrollment
- Enrollment requires reCAPTCHA Configuration and therefore requires a few more steps to set up.

## Contact / Acknowledgments
[**Symsoft Solutions**](https://symsoftsolutions.com). For any queries or support, please contact our team.

### Contributors

- [Abdul Farooqui](https://github.com/abdulFarooqui)
- [John Walker](https://github.com/jtwalker2000)
- [Savita Farooqui](https://github.com/SavitaFarooqui)
4 changes: 2 additions & 2 deletions Phase2/clients/data/TRAIN/trainApiService.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const getTspHistory = async (tspid = '', token) => {
})
.then(res => res.data)
.catch(err => {
console.log(err);
// console.log(err);
return null;
});

Expand All @@ -54,7 +54,7 @@ const getTspDetail = async (tspid, version = null,token) => {
})
.then(res => res.data)
.catch(err => {
console.log(err);
// console.log(err);
return null;
});

Expand Down
27 changes: 19 additions & 8 deletions Phase2/clients/data/submissionFormatting/submissionFormatting.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var SubmissionModel = require('../../data/MongoDB/mongoose').SubmissionModel;

const formatDate = (date) => {
const options = {
year: 'numeric',
Expand Down Expand Up @@ -48,15 +50,27 @@ const mongoToForm = (submission) => {
//Each key and value formatted as labels and values as they will appear on screen
// Object format:
// { Formatted Field Label : Formatted Field Value }
const mongoToReview = (submission, formType = "network") => {
const mongoToReview = async (submission, formType = "network") => {
//Review Information section
const ReviewInfo = submission.ReviewInfo
let ReviewInfo = submission.ReviewInfo
if(!ReviewInfo) {
let localSubmission = await SubmissionModel.findOne({ "TrustServiceProvider.TSPID": submission.TSPID }).select('ReviewInfo')
ReviewInfo = localSubmission.ReviewInfo
}

let SubmitterInfo = submission.Submitter
if(formType !== "enroll"){
if(!SubmitterInfo) {
let localSubmission = await SubmissionModel.findOne({ "TrustServiceProvider.TSPID": submission.TSPID }).select('Submitter')
SubmitterInfo = localSubmission.Submitter
}
}

return Object.assign(jsonToDetailPage(submission, formType), { ReviewInfo })
return Object.assign(jsonToDetailPage(submission, formType), { ReviewInfo, SubmitterInfo })
}

const jsonToDetailPage = (json, formType = "network") => {
const _id = json && json._id ? json._id : null;
const _id = json && json._id ? json._id : json.TSPID ? json.TSPID : null;

switch(formType) {
case "framework":
Expand Down Expand Up @@ -150,10 +164,7 @@ const jsonToDetailPage = (json, formType = "network") => {
let opsAgent = service.OpsAgentInfo

return Object.assign( { "Name:": opsAgent.OpsAgentName.Name }, buildAddressViewFormat(opsAgent.OpsAgentAddress))
})

console.log(json);

})

json = json.SubmitterInfo

Expand Down
Loading

0 comments on commit eb16502

Please sign in to comment.