Create, Update, Delete Data on T7 CDA using JavaScript/React

This document shows you how to write data to your local T7 using the web browser. These instructions are also available on GitHub.

Important

This is a living document and are subject to change.  Last updated:  

Introduction 

In order to manipulate data in the database in some fashion you need to be authorized.
Unlike READ (GET) requests that are read-only, changing or altering data requires you to login.

As a means of allowing districts to start altering data in their databases a series of programs were created in tomcat (CDA runs in Tomcat) to handle the login process.

These programs (WAR files) get installed on your T7 by G6.

They (G6) also need to alter your Tomcat settings and Apache settings to enable this.

To get CWMSLogin working just to be able to get an API key, you could follow the steps outlined in the cwms-python docs (Setting up CDA writes and cwms-python on T7s). This API key is ONLY used for backend processes.

 IT SHOULD NOT be placed in your client-side javascript. ⚠ This exposes it to anyone that can get to the page and would give them the same permissions in the database as the user that creates the key.

You can NOT write to the national CDA instance. I.e. https://cwms-data.usace.army.mil/cwms-data.

This is a largely read only instance. If you did find some way to write to it dataguard would overwrite it. Data is pushed from district T7s, currently, to the national database and the above mentioned URL gives you that data, publicly.

A local CDA instance will need to be placed in your Tomcat web-apps.
The process for that is outlined here:
Install CDA for district T7

Getting Started

  1. If you do not have any of the login setup completed:

    1. You can submit a "CWMS Helpdesk" ticket
      1. In Service Now search for "CWMS" and select the CWMS ticket
      2. Target the WEB team with it set as NOT critical.
        1. This will go directly to Mark and his team.
        2. In the description specify "CDA Auth enabled for T7. Apache reverse proxy for CDA auth in JS. Setup 404 redirects for "/path" for react client-side routing. Where "/path" is the path you wish to deploy your react distribution files to. If this is root you would say "/" ONLY if you do not have a site already. Eventually you would have this updated to root as you have all your pages migrated."
  2. Once G6 has confirmed this working with you try the following:

    1. Navigate to:
      1. https://wm.ds.<3letter>.usace.army.mil:8243/<3letter>-data/CWMSLogin/login - where <3letter> would be swt for example
      2. Click accept and login.
        1. ⚠ If you get an error about no permissions, you will need to be granted permissions via the serveradmin.exe utility in CWMS ⚠
      3. Once logged in you should see the permissions you currently have
    2. Attempt the reverse proxy AFTER you login to the tomcat port above
      1. https://wm.ds.<3letter>.usace.army.mil:8243/CWMSLogin/login - where <3letter> would be swt for example
        1. You should see the same message you saw above.
        2. If you get any other errors, please screenshot and send them to the G6 rep working with you (Probably Mark Carron)

Writing code 

Now that you have everything setup, you are ready to access and write to Oracle on your T7 via CDA.

The general idea/workflow is as follows:

  1. User navigates to your page
  2. Javascript does a polling request (every 5-10 seconds) to the auth endpoint to see if it gets a 401 Unauthorized error
  3. If authorized, changes button to say "Submit"
    1. Clicking this button fires POST requests you define in your code
  4. If NOT authorized, button says the text "Login"
      1. Clicking this button would direct the user to :8243/CWMSLogin/login?OriginalLocation=URL/You/Came/From
      2. Once the user clicks accept a "JSESSIONIDSSO" token is placed in the users cookies, this gets passed to the server on each request as a form of verifying who you are. Clearing your cookies can reset the login. It will also timeout after some time. (This is why you must poll)
  1. GET data could be populated for view (logged in or not)
  2. If the user is logged in you could also enable input boxes for example
  3. User clicks submit, various input boxes on the page get data pulled from them
  4. Data is sent via cwmsjs or fetch/vanillajs to T7 CDA. CWMSjs can be used with vanilla js or react.
  5. User gets feedback from the push requests on if data was written or if they are not authorized again (could become unauthorized in between polling auth checks)

In order to return you back after step 2bb includes a OriginalLocation, you could get clever as I do in the example and use javascript to provide this.
This makes it work on your COOP too!

Code Examples

  • I have prepared a few very basic code examples in both vanilla javascript and react (groundwork/etc capable) that show you how you could handle this.
    • ⚠ If you run into issues with either please report them to so they can fix / correct for all.

Javascript

  • MVS Example for writing timeseries HERE - No CWMSJS, pure JS with fetch

React

  • Writing CLOB data using CWMSjs HERE - CWMSjs saves you from having to write/create the URL yourselves.

CWMSjs

CWMSjs is a wrapper around CDA It is written in typescript and resides in NPM

  • This makes it so you can just npm i cwmsjs and start using it. It offers many examples for READ, but since it is public the authorization page is a little... generic.

  • Additional CWMSjs docs here: - Examples directory : here - Authorization example JS / React: here

T7 Deployment

In order to use this javascript with your local CDA instance on your T7 the source will need to live in tomcat or in apache/httpd.

If you place the client-side source (React/JS/Html/css) in tomcat you will not need the reverse proxy.

Also you can run this command if using React/Groundwork/etc npm run build This will trigger a script you have setup in the scripts block of your package.json to create distribution files dist in the same directory as the package.json. It will be grayed out because it is not in the version control (it's in the .gitignore).

Once you run the build command you can copy the contents of ./dist to wherever you would like the site to live. Side note: the current process for the DEV of our PUBLIC site has a similar script in package.json of your WM public site to copy to a S3 bucket using github / AWS secrets.

Here is a script i have in my package.json that builds and deploys me internal site react distribution files to our T7 using a putty profile I created with a keypair in it named CWPT7

My full script block in package.json:

"scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "clean-remote": "plink -batch -load CWPT7 \"cd /wm/swt/wm_web/var/apache2/2.4/htdocs/assets/ && rm *.js && rm *.css\"",
    "deploy": "npm run build && npm run clean-remote && pscp -batch -r ./dist/assets/* CWPT7:/wm/swt/wm_web/var/apache2/2.4/htdocs/assets/ && pscp -batch -r ./dist/index.html CWPT7:/wm/swt/wm_web/var/apache2/2.4/htdocs/",
    "deploy-all": "npm run build && npm run clean-remote && pscp -batch -r ./dist/* CWPT7:/wm/swt/wm_web/var/apache2/2.4/htdocs/",
    "preview": "vite preview"
  },

Take notice that i have a deploy-all and deploy script. I run the deploy-all when I want EVERY file to get uploaded (including images). So that the process is faster my regular deploy command pushes only the important stuff (CSS/JS/HTML files).

The full command to trigger these scripts you can define in the scripts tag are:
npm run deploy

npm run deploy-all

⚠ Gotchas ⁉

  • Users MUST npm run build and push their dist files to their T7 web directory in order for the authentication to work.
    • This is because localhost:5173 is a different port/host than httpd/tomcat
  • If you attempt to go to the reverse proxy first (before the :8243/CWMSLogin/login tomcat) you will get a 400 error message. This is due to the process failing to pass the certs up stream. We are looking into it. For now send your users to tomcat to authenticate.
    • Then redirect back to httpd. The reverse proxy shares the certs.
  • When the T7 go away the login process will change slightly, but the code to POST will be the same.
    • The endpoints will change some. I.e. no more CWMSLogin/login
    • Majority of your code stays the same!

-- Charles Graham