portal-backend.env
file and remove redundant configuration and defaults.You'll only have to do this once per development environment.
--pull=always
. Check with docker version -f '{{.Client.Version}}'
.--add-host host.docker.internal:host-gateway
. Check with docker version -f '{{.Server.Version}}'
.If you can already pull the following image, you won't need to follow these steps:
docker pull ghcr.io/modusintegration/wso2is-populate:latest
Otherwise follow the steps
Follow the instructions here: https://github.com/modusintegration/mmd-dev#vpn-access
Follow the instructions here: https://github.com/modusintegration/mmd-dev#iac-configuration-file-access
These commands will share environment variables through your shell. Be sure to run them all from the same shell instance (normally you can just use the same terminal window).
Create docker network so our containers can talk to each other
docker network create --driver=bridge portal-net
Run WSO2
docker run \
-p 9443:9443 \
--name=wso2 \
--network=portal-net \
--rm \
--detach \
--volume=$PWD/integration_test/shared/manifests/wso2/identity.xml:/home/wso2carbon/wso2is-km-5.7.0/repository/conf/identity/identity.xml \
wso2/wso2is-km:5.7.0
You'll need to wait a few minutes until you see the following log line in the WSO2 container:
[2021-05-13 11:39:58,203] INFO {org.wso2.carbon.identity.authenticator.x509Certificate.internal.X509CertificateServiceComponent} - X509 Certificate Servlet activated successfully..
You can watch for this with
docker logs -f wso2
The logs are busy, but don't worry, you won't miss the important line, it'll be the last one
printed before the logging goes quiet at the end of the start-up sequence. Once you've seen the
line of interest, kill the logs with <ctrl-c>
.
Populate WSO2
AUTH_SERVER_CLIENTKEY="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c30)"
AUTH_SERVER_CLIENTSECRET="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c30)"
You will likely need to wait a few moments for WSO2 to come up. Once it's stopped running, do the following:
docker run \
--rm \
--env WSO2_HOST="https://wso2:9443" \
--env AUTH_SERVER_CLIENTKEY="$AUTH_SERVER_CLIENTKEY" \
--env AUTH_SERVER_CLIENTSECRET="$AUTH_SERVER_CLIENTSECRET" \
--network=portal-net \
--pull=always \
ghcr.io/modusintegration/wso2is-populate:latest
Check OAuth
curl -k -X POST 'https://localhost:9443/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "client_id=$AUTH_SERVER_CLIENTKEY" \
--data-urlencode "client_secret=$AUTH_SERVER_CLIENTSECRET" \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=openid' \
--data-urlencode 'username=portaladmin' \
--data-urlencode 'password=mcvV2KYw9eKPqNagjGy6'
The result should be json something like:
{
"access_token": "eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJwb3J0YWxhZG1pbkBjYXJib24uc3VwZXIiLCJhdWQiOiJYUFJUOFMyaHdwd0kyR2cwc3BoanMzRF9qXzdhNDUiLCJuYmYiOjE2MjQ4ODk2MjQsImF6cCI6IlhQUlQ4UzJod3B3STJHZzBzcGhqczNEX2pfN2E0NSIsInNjb3BlIjoib3BlbmlkIiwiaXNzIjoiaHR0cHM6XC9cL2xvY2FsaG9zdDo5NDQzXC9vYXV0aDJcL3Rva2VuIiwiZ3JvdXBzIjpbIm5kY191cGRhdGUiLCJBcHBsaWNhdGlvblwvcG9ydGFsb2F1dGgiLCJJbnRlcm5hbFwvZXZlcnlvbmUiXSwiZXhwIjoxNjI0ODkzMjI0LCJpYXQiOjE2MjQ4ODk2MjQsImp0aSI6IjFiY2Q4Zjc0LWZjMDAtNGY5NS1hMzU5LTIxMTg0YzUyM2QzMCJ9.VELD7hblmAjAvYkRZpxhxZOGT-nnOeeJDBl8KPWD7NE1UT0QMQMwbNZ1X3Lp0NMsLJYnr10jFf9OuVDJWl6zWtWuHoXt-xp78AndIEFXMomd_DCKyGhSVm6PEKZb74yUcjmzen58bvPXyPEuV7m6DmoVgx8wThj5O_3DLMR2P4lynkhlTYrPXS1HdQsFlP5f3MhpJjPPrFjGLRKd9xJNUDZKBWBWcgYJao7QR2WsVn1f_R8itcFt6lth7X3a80kyUgypISmixydj9k0vTm1l5pvJlpWOcAKe239H_6cnGmiT2aGWA5USZUw7OVBLpkxKSH4QXMkYFNhs9xg394TVhA",
"refresh_token": "26ff0499-5ca0-3c2a-8238-8233acbd7f8e",
"scope": "openid",
"id_token": "eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoibXotOXZ6NkZBQVpFWWFrQ1otWGU5dyIsImF1ZCI6IlhQUlQ4UzJod3B3STJHZzBzcGhqczNEX2pfN2E0NSIsInN1YiI6Im5kY191cGRhdGUsQXBwbGljYXRpb25cL3BvcnRhbG9hdXRoLEludGVybmFsXC9ldmVyeW9uZSIsIm5iZiI6MTYyNDg4OTYyNCwiYXpwIjoiWFBSVDhTMmh3cHdJMkdnMHNwaGpzM0Rfal83YTQ1IiwiYW1yIjpbInBhc3N3b3JkIl0sImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC90b2tlbiIsImdyb3VwcyI6WyJuZGNfdXBkYXRlIiwiQXBwbGljYXRpb25cL3BvcnRhbG9hdXRoIiwiSW50ZXJuYWxcL2V2ZXJ5b25lIl0sImV4cCI6MTYyNDg5MzIyNCwiaWF0IjoxNjI0ODg5NjI0fQ.F1ZpZ9b6vE3F8HOElDy_PHHUVT53SSuRnJ-8pK-eImbr-DOeuzDDA-qs-iVJnOuJac9fBXGhsdOzXJOViyICuc5S0-QwmPIO6GSGk1oHUpEf42O0jpOKIK_cRmn3iOA87ULplsSOe4mWpk3COdcwqmR6XhmApVOhiOqBOOkJXeiFWQSpp62xwgF0SH18PzgI0j3iBm0c4FbqqxM3v4nP6bkm71WlFijLCu5kgQxDwi44JtPhbwrmFQryl71OG3g2ON0_Eqsfe80cgNfAAWzFIV8QIrGHTStbNf6DaobNZcnRCswMzKLklHKkF92mp3gi6EPVU14vfihpwTvDlfRU4w",
"token_type": "Bearer",
"expires_in": 3600
}
Run portal backend:
# Before running this command, make sure you are accessing the correct Kubernetes cluster,
# i.e. you're using the correct KUBECONFIG file.
CLUSTER_CENTRALLEDGER_DB_PW="$(kubectl get secret -n mojaloop mojaloop-centralledger-mysql -o json | jq '.data."mysql-password" | @base64d' -r)"
docker run \
--rm \
--env-file=portal-backend.env \
--network=portal-net \
-p 3002:3002 \
--name=portal-backend \
-e AUTH_SERVER_CLIENTKEY="$AUTH_SERVER_CLIENTKEY" \
-e AUTH_SERVER_CLIENTSECRET="$AUTH_SERVER_CLIENTSECRET" \
-e DB_PASSWORD="$CLUSTER_CENTRALLEDGER_DB_PW" \
--pull=always \
--detach \
--add-host=host.docker.internal:host-gateway \
mojaloop/finance-portal-backend-service
Test login:
curl --location --request POST 'localhost:3002/login' \
--header 'Content-Type: application/json' \
--data-raw '{
"username": "portaladmin",
"password": "mcvV2KYw9eKPqNagjGy6"
}'
The result should look like:
{"expiresIn":3600}
Port-forward the settlement service, central ledger admin service, and the database:
# Before running this command, make sure you are accessing the correct Kubernetes cluster,
# i.e. you're using the correct KUBECONFIG file.
kubectl port-forward -n mojaloop --address=0.0.0.0 deploy/mojaloop-centralsettlement-service 3007
kubectl port-forward -n mojaloop --address=0.0.0.0 sts/mojaloop-centralledger-mysql 3306
kubectl port-forward -n mojaloop --address=0.0.0.0 deploy/mojaloop-centralledger-service 4001:3001
If this proves unreliable, you might like to wrap it in a loop:
while true; do kubectl port-forward -n mojaloop --address 0.0.0.0 deploy/mojaloop-centralledger-service 4001:3001; done
while true; do kubectl port-forward -n mojaloop --address=0.0.0.0 deploy/mojaloop-centralsettlement-service 3007; done
while true; do kubectl port-forward -n mojaloop --address=0.0.0.0 sts/mojaloop-centralledger-mysql 3306; done
The script in ./scripts/port-forward.sh
might be useful, but will not handle failure of a
port-forward well.
Bring up the v2 fp-ui and required proxy to test. From this repo:
yarn install
yarn build
yarn start
Access the finance portal at http://localhost:3000/. Use portaladmin/mcvV2KYw9eKPqNagjGy6
to log
in. This may take a few seconds each time you run yarn start
.
vX.Y.Z
. See previous
releases for
examples.helm repo add portal https://raw.githubusercontent.com/mojaloop/finance-portal-v2-ui/repo
helm search repo portal/finance-portal-v2-ui
Now, in Chart.yaml
or requirements.yaml
:
dependencies:
- name: finance-portal-v2-ui
version: v1.0.0 # replace as necessary
repository: https://raw.githubusercontent.com/mojaloop/finance-portal-v2-ui/repo
condition: finance-portal-v2-ui.enabled
package.json
.vX.Y.Z
. See previous
releases for
examples.The new image will be available at ghcr.io/mojaloop/finance-portal-v2-ui.
To use the image, you'll need to follow these steps:
read:packages
scope: https://github.com/settings/tokens/new?scopes=read:packages,write:packages# use your token here
TOKEN=""
# your GH user name here
USER=""
docker login ghcr.io -u "$USER" -p "$TOKEN"
docker pull ghcr.io/mojaloop/finance-portal-v2-ui
To deploy an image from a private repo in a private Kubernetes cluster:
Important: this uses your personal access token. You should most likely not use this token in a shared cluster.
jq '.auths = (.auths | with_entries(select(.key == "ghcr.io")))' ~/.docker/config.json > config.json
The project aims to use the BEM naming convention.
The project uses TypeScript. Utility command yarn lint
can help identifing wrong and missing types.
Versioning is done via yarn version
. Usually a patch version change is enough; if a new page/module is added, instead, a minor change is required.
The UI is configured to expect its backend APIs to be served from the same endpoint as the main bundle. This means that...
You start the front end with yarn start
and you must have the backend service(s) running on localhost:3002.
See /webpack.config.js for proxy details. You can tweak these for local development if you need to run multiple backend services
You need a kubernetes ingress which maps the relevant backend services to the correct paths. An ingress which does this is provided in the Mojaloop finance portal HELM chart:
To test the built image you should deploy and run it in a kubernetes cluster via the mojaloop finance portal HELM chart. Backing services will need to be present for backend API requests to succeed.
Before merging any PR, make sure that:
yarn version
should be used for this purpose.yarn prettier
should be used for this purpose.yarn lint
should be used for this purpose.In the project directory, you can run:
yarn start
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
yarn test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
yarn build
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
yarn eject
- DON'T DO THISNote: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
yarn prettier
Runs prettier on the project source files.
yarn lint
Runs ESLint on the project source files.
yarn serve
Serves the production build on port 8080.
The command docker build -t settlement-manager-ui .
creates a docker image with the name settlement-manager-ui
.
The command docker run --rm -p 8080:8080 settlement-manager-ui
runs the docker image binding the port 8080.
The command make build
creates a docker image with the name settlement-manager-ui
. Exposes the UI on port 8080.
The command make run
runs the docker image binding the port 8080.