Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Major New Features

Intermediate Progress for Queries

Researchers can observe their queries making progress from their local node to the hub, out to SHRINE's adapters and into the CRC. Researchers no longer need to take any action to retrieve QUEUED query results from the CRC; SHRINE's adapter now polls the CRC and proactively sends results back to the researcher's local node.

Major Security Enhancements

SHRINE no longer includes shrine-proxy.war which enabled several serious exploits.

SHRINE no longer requires a firewall hole to allow downstream nodes to act as a server for the hub. Downstream nodes no longer need to trust a client they do not control.

SHRINE no longer records the unobfuscated count result received from the CRC.

Network Health Web Page

SHRINE includes a new feature that periodically tests and supplies a simple report of network health.

Simpler Downstream Node Maintenance and Upgrades

Downstream node admins may now stop SHRINE for brief periods of time without missing queries from remote researchers. Those queries accumulate at the hub; the downstream node will be asked to run those queries when the node lets the hub know it is ready.

SHRINE's new internal data structures are versioned so that future upgrades may possibly be backward-compatible even if the contents of those structures changes. Future upgrades of SHRINE may not have to be coordinated across a whole network.

New Back-End Architecture for SHRINE

Most of these changes are enabled by a new back-end architecture for SHRINE based on Message-Oriented Middleware. This opens up many possible future enhancements for SHRINE. 

Minor Changes

Removed shrine-metadata.war, steward.war, shrine-proxy.war, shrine-dashboard.war, and shrine-webclient.zip contents

Functionality in these .war files have been moved to shrine-api.war . (If your site does not support the ACT Aim 3 plugins, you may also remove shrine.war .) The javascript code now draws its configuration from shrine.conf instead of from several locations in javascript files. All javascript code now resides within the .war files that serve the application.

shouldQuerySelf Feature Removed

Find all the references to shouldQuerySelf in shrine.conf files and remove them.

If you really have an Adapter on the same node as the hub, add its adapter to the hub via a curl command or initial configuration - just like any other. (You will very likely have done this for the QEP at the hub already.)

Removed the "includeAggregateResults" setting

Remove the formerly required "includeAggregateResults =  false" from shrine.conf . 

No More Human-Readable node name property

The nodeKey property is used by SHRINE internally instead, and the node structure (stored at the hub) holds a real human-readable name with a good assortment of punctuation and spaces.

Remove the downstreamNodes section from the hub's shrine.conf

Remove the downstreamNodes section from the hub's shrine.conf. It is not used in SHRINE 2.0.0 and causes minor problems in the dashboard.

Database Changes

No need to specify a slick driver

Now the system can select the slick driver based on the shrineDatabaseType property. If the selected slick driver causes problems it is OK to use the old properties - which will override the one chosen via shrineDatabaseType.

Count-based Lockout Feature Removed

Remove adapterLockoutAttemptsThreshold from all shrine.conf files

Remove PRIVILEGED_USER tables and associated constraints and sequences from your database.

Drop the column of actual patient counts from the adapter's COUNT_RESULT table

SHRINE no longer needs to store the actual (and mildly sensitive) actual count of patients from the CRC in its COUNT_RESULT table. In mysql remove it from the shrine_query_history database with

Code Block
languagesql
ALTER TABLE COUNT_RESULT DROP COLUMN ORIGINAL_COUNT;


Drop the column of actual patient counts from the adapter's BREAKDOWN_RESULT table

SHRINE no longer needs to store the actual (and mildly sensitive) actual count of patients from the CRC in its BREAKDOWN_RESULT table. In mysql remove it from the shrine_query_history database with

Code Block
languagesql
ALTER TABLE BREAKDOWN_RESULT DROP COLUMN ORIGINAL_VALUE;

Add a status column for queries at the QEP

Add a status column to qepAuditDB's previousQueries table to support updates in query status with :

MySQL:

Code Block
use qepAuditDB;
alter table `previousQueries` add column `status` VARCHAR(255) NOT NULL DEFAULT 'Before V26';


MS SQL:

Code Block
use qepAuditDB;
alter table "previousQueries" add "status" VARCHAR(MAX) NOT NULL DEFAULT 'Before V26';


ORACLE:

Code Block
use qepAuditDB;
alter table "previousQueries" add  "status" VARCHAR2(256) default 'Before V26' NOT NULL;

Added table QUERY_PROBLEM_DIGESTS

MySQL:

Code Block
languagesql
use qepAuditDB;
create table `QUERY_PROBLEM_DIGESTS` (`NETWORKQUERYID` BIGINT NOT NULL,`CODEC` TEXT NOT NULL,`STAMP` TEXT NOT NULL,`SUMMARY` TEXT NOT NULL,`DESCRIPTION` TEXT NOT NULL,`DETAILS` TEXT NOT NULL,`CHANGEDATE` BIGINT NOT NULL);
create index queryProblemsNetworkIdIndex on QUERY_PROBLEM_DIGESTS(NETWORKQUERYID);


MS SQL:

Code Block
languagesql
use qepAuditDB;
create table "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID" BIGINT NOT NULL,"CODEC" VARCHAR(MAX) NOT NULL,"STAMP" VARCHAR(MAX) NOT NULL,"SUMMARY" VARCHAR(MAX) NOT NULL,"DESCRIPTION" VARCHAR(MAX) NOT NULL,"DETAILS" VARCHAR(MAX) NOT NULL,"CHANGEDATE" BIGINT NOT NULL);
create index "queryProblemsNetworkIdIndex" on "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID");


ORACLE:

Code Block
languagesql
use qepAuditDB;
create table "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID" NUMBER(19) NOT NULL,"CODEC" VARCHAR(256) NOT NULL,"STAMP" VARCHAR(256) NOT NULL,"SUMMARY" CLOB NOT NULL,"DESCRIPTION" CLOB NOT NULL,"DETAILS" CLOB NOT NULL,"CHANGEDATE" NUMBER(19) NOT NULL);
create index "queryProblemsNetworkIdIndex" on "QUERY_PROBLEM_DIGESTS" ("NETWORKQUERYID");


Added table RESULTS_OBSERVED

MySQL:

Code Block
languagesql
use qepAuditDB;
create table `RESULTS_OBSERVED` (`NETWORKQUERYID` BIGINT NOT NULL,`CHECKSUM` BIGINT NOT NULL,`OBSERVEDTIME` BIGINT NOT NULL);
create index resultsObservedQueryIdIndex on RESULTS_OBSERVED(NETWORKQUERYID);
create index resultsObservedChecksumIndex on RESULTS_OBSERVED(CHECKSUM);


MS SQL:

Code Block
languagesql
use qepAuditDB;
create table `RESULTS_OBSERVED` (`NETWORKQUERYID` BIGINT NOT NULL,`CHECKSUM` BIGINT NOT NULL,`OBSERVEDTIME` BIGINT NOT NULL);
create index "resultsObservedQueryIdIndex" on "RESULTS_OBSERVED" ("NETWORKQUERYID");
create index "resultsObservedChecksumIndex" on "RESULTS_OBSERVED" ("CHECKSUM");


ORACLE:

Code Block
languagesql
use qepAuditDB;
create table "RESULTS_OBSERVED" ("NETWORKQUERYID" NUMBER(19) NOT NULL,"CHECKSUM" NUMBER(19) NOT NULL,"OBSERVEDTIME" NUMBER(19) NOT NULL);
create index "resultsObservedQueryIdIndex" on "RESULTS_OBSERVED" ("NETWORKQUERYID");
create index "resultsObservedChecksumIndex" on "RESULTS_OBSERVED" ("CHECKSUM");


Added table CONNECTIVITY_TEST_RESULTS to the hub's qepAuditDB

MySQL:

Code Block
languagesql
use qepAuditDB;create table `CONNECTIVITY_TEST_RESULTS` (
`NETWORKQUERYID` BIGINT NOT NULL,
`CHANGE_DATE` BIGINT NOT NULL
);

create index CONNECTIVITY_TEST_RESULTS_NETWORKQUERYID_INDEX on CONNECTIVITY_TEST_RESULTS (NETWORKQUERYID);
create index CONNECTIVITY_TEST_RESULTS_CHANGE_DATE_INDEX on CONNECTIVITY_TEST_RESULTS (CHANGE_DATE);


MS SQL:

Code Block
languagesql
use qepAuditDB;
create table "CONNECTIVITY_TEST_RESULTS" (
"NETWORKQUERYID" BIGINT NOT NULL,
"CHANGE_DATE" BIGINT NOT NULL
);

create index "CONNECTIVITY_TEST_RESULTS_NETWORKQUERYID_INDEX" on CONNECTIVITY_TEST_RESULTS ("NETWORKQUERYID");
create index "CONNECTIVITY_TEST_RESULTS_CHANGE_DATE_INDEX" on CONNECTIVITY_TEST_RESULTS ("CHANGE_DATE");


ORACLE:

Code Block
languagesql
use qepAuditDB;
create table "CONNECTIVITY_TEST_RESULTS" (
"NETWORKQUERYID"  NUMBER(19) NOT NULL,
"CHANGE_DATE"  NUMBER(19) NOT NULL
);

create index "CONNECTIVITY_TEST_RESULTS_NETWORKQUERYID_INDEX" on CONNECTIVITY_TEST_RESULTS ("NETWORKQUERYID");
create index "CONNECTIVITY_TEST_RESULTS_CHANGE_DATE_INDEX" on CONNECTIVITY_TEST_RESULTS ("CHANGE_DATE");


Remove the qep user from the PM cell, and corresponding bits from shrine.conf

SHRINE now accesses the DSA's database directly from inside shrine-api.war. It no longer needs a special qep user. Delete that user from the PM cell, and remove this (previously required) section from shrine.conf:

Code Block
languagejs
    //shrine-steward config
    shrineSteward {
      qepUserName = "qep"
      qepPassword = "changeit"
      stewardBaseUrl = "https://shrine-node1:6443"
    }

New Features / Enhancements

New Database Schema for Hub

SHRINE is storing all the data needed for network health at the hub, using a new schema, with a focus on json and on version compatibility. The new schema is in shrine-setup.zip, shrine-setup/hub/sql , with a .ddl for each database brand we test.

Install the shrine-api.war servlet

We moved a lot of functionality into this new servlet. Delete steward.war, shrine-dashboard.war, shrine-metadata.war, and shrine-proxy.war. Also delete the unpacked shrine-webclient (which used to be unzipped). If your site is not running the ACT Aim 3 plugins then your site no longer needs shrine.war. 

Update the shrine.conf URL for messaging to use the shrine-api.war servlet

Code Block
languagejs
  messagequeue {
    blockingq {
      serverUrl = "https://shrine-dev1.catalyst:6443/shrine-api/mom"
    }
  }

Set properties needed on the Hub for running a connectivity test and sending emails when there are failures 

Code Block
languagebash
themerdark
networkhealth {
   email {
      networkName = "ACT Network"
      networkSignature = "ACT Network Operations Team"
      grantDescription = "Funded by the NIH National Center for Advancing Translational Sciences through its Clinical and Translational Science Awards Program, grant number UL1 TR001857."
      helpContactName = "ACT JIRA Help Desk"
      helpContactEmail = "actnetwork@pitt.edu",
   }
   webpage {
      networkName = "ACT Network"
      webpageNote = "This is a note" //Optional alert message to display at the bottom of the network health webpage
      alertMessage = "This is an alert message" //Optional alert message to display at the top of the network health webpage
   }
   connectivityTest {
      queryId = "123456789" //The query Id of a previously run query that will be used to create a new query for the connectivity test
      interval = "24 hours" //How often to run the connectivity test
      timeLimit = "10 minutes" //How long to wait for the query to finish running. If a node does not return results, it will be marked as having an error.
      delay = "5 seconds" //The initial delay for starting the connectivity test
   }
}


The URL for the network health status webpage is available on the hub at  https://shrine-dev1.catalyst:6443/shrine-api/networkhealth/webpage/index.html


Adapter controls CRC time limit to run a query

The shrine.adapter.crcRunQueryTimeLimit property in shrine.conf (default of 30 seconds) controls the time limit given to the CRC to either complete or queue the query. 


Added a data service at the hub to gather and serve SHRINE's shared data structures

The hub now supports a shared data service. To reach the service (and get the config data needed to receive query results and queries) downstream nodes need to add the hub's base URL to their shrine.conf

Code Block
languagejs
shrine {
  hub {
    client {
      serverUrl = "https://shrine-hub:6443"
    }
  }
}


Part of the new data service allows a node to look up information about itself

Each node can ask the hub about itself and the hub. To ask about itself it needs a shared key with the hub. Add that to shrine.conf

Code Block
languagejs
shrine {
  nodeKey = "urlPathFriendlyNodeName"
}


The hub needs some initial information about the network, the hub node, and (optionally) other nodes

To supply that data service at start, the hub's shrine.conf needs some initial filling for those data structures. This information is only used if the hub does not have an initial configuration in its database.

Code Block
languagejs
shrine {
  hub {

  //This configuration is only used if no network is found in the hub's database
  //It is loaded into the database when the hub starts if no network is found.
  //To update the network or nodes, use the appropriate curl commands, not this config section.
  //In ifNoNetwork - nodes are added only if the node key does not already exist in the hub's database.
    ifNoNetwork {
      network {
        name = "Shrine Dev Test Network" //Name of your network
        hubQueueName = "hub" //queue used to send messages to the hub, different from the queue used to send messages to a QEP and an adapter colocated with the hub
        adminEmail = "yourname@example.com" //email address for the hub admin to send network health test failures
      }
      //Nodes in this network
      //In ifNoNetwork - nodes are added only if the node key does not already exist in the hub's database.
      nodes = [
        {
          name = "Shrine Dev1" //human-readable name for this node
          key = "shrineDev1" //machine-friendly key used to identify this node. Never change this.
          userDomainName = "shrine-dev1.catalyst" //domain name for users from this node.
          queueName = "shrineDev1" //queue used to send messages to the qep and adapter at this node. This field is optional, defautls to the key if not specified
         sendQueries = "false" //true to send queries to an adapter at this node. An optional field, true by default.
         adminEmail = "yourname@example.com" //email address for the node admin to send network health test failures
        },
        {
          name = "shrine-dev2"
          key = "shrineDev2"
          userDomainName = "shrine-dev2.catalyst"
		  adminEmail = "yourname@example.com"
        }
      ]
    }
  }
}


Add and reconfigure nodes and some aspects of the network via web api commands to the hub

Use a curl command add a node to the hub:

Code Block
languagebash
curl -u username:password -w "\n %{response_code}\n" -k -X PUT "https://shrine-dev1.catalyst:6443/shrine-api/hub/createNode/samHospital?nodeName=Mr%2E%20Sam%20Tsoi%27s%20Hospital&userDomain=tsoi%27net&adminEmail=email@example.com"


Use a curl command to modify a node (and stop sending it queries):

Code Block
languagebash
curl -u username:password -w "\n %{response_code}" -k -X PUT https://shrine-dev1.catalyst:6443/shrine-api/hub/modifyNode/shrine-dev2?sendQueries=false

curl -u username:password -w "\n %{response_code}" -k -X PUT "https://shrine-dev1.catalyst:6443/shrine-api/hub/modifyNode/shrine-dev2?nodeName=Mr%2E%20Sam%20Tsoi%27s%20Hospital&sendQueries=true"


Use a curl command to modify the network: 

Code Block
languagebash
curl -u username:password -w "\n %{response_code}" -k -X PUT "https://shrine-dev1.catalyst:6443/shrine-api/hub/modifyNetwork?networkName=SHRINE%20Dev%20Network"

Configure the webclient in shrine.conf

Code Block
languagetext
 webclient {
    domain = "i2b2demo"
	name  = "SHRINE"
	siteAdminEmail = "email@foo"
    usernameLabel = "User Name"
    passwordLabel = "User Password"
	defaultNumberOfOntologyChildren = 10000  // the number of children to show when an ontology folder is expanded.
    queryFlaggingInstructions = "Enter instructions for flagging queries here"
	flaggingPlaceholderText = "Enter placeholder text for the query flagging text input field"
	flaggingIconInstructions = "Enter text for when user mouses over the flagging information icon in the header of the Query History here"
  }

The webclient has hard coded default values for the usernameLabel, passwordLabel and defaultNumberOfOntologyChildren fields if they are not configured, usernameLabel defaults to "SHRINE User", passwordLabel defaults to "SHRINE Password" and defaultNumberOfOntologyChildren defaults to 10000.

Redirect the old SHRINE webclient URL

The URL to the SHRINE webclient has changed from https://shrine-node-url:6443/shrine-webclient/ to https://shrine-node-url:6443/shrine-api/shrine-webclient/ 

To redirect the old URL and preserve existing bookmarks and history in browsers, specific a URL rewrite in Tomcat.

1. Add rewrite valve to conf/server.xml inside the Host configuration section:
<Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

2. Create a file name rewrite.config in conf/Catalina/localhost with the following contents:
RewriteRule ^/shrine-webclient /shrine-api/shrine-webclient
 

Move externalStewardBaseUrl to ${shrineHubBaseUrl}/shrine-api/shrine-steward

Code Block
languagejs
shrine {
...
  steward {
...  
    emailDataSteward {
...
      externalStewardBaseUrl = ${shrineHubBaseUrl}/shrine-api/shrine-steward
...

Other Notes

Be sure to replace all references to the i2b2demo with your own user's domain

SHRINE identifies users via username:domain . If you use the default i2b2demo domain then SHRINE cannot identify where your researcher's queries are coming from. If you are running queries as a default user:domain then you will very likely see queries that you did not run, and others will be able to see your queries, too. 

Configuration in i2b2_config_data.js

If the REST API is located on a different domain, then use the shrineUrl setting in i2b2_config_data.js.  

Code Block
languagetext
titlei2b2_config_data.js
  {
 	shrineUrl: "http://someotherdomain:6443/shrine-api/"  
  }

In most instances the REST API will be on the same domain as the webclient and no configuration in i2b2_config_data.js is needed.  However for backwards compatibility, the i2b2_config_data.js file must still exist as an empty object

Code Block
languagetext
titlei2b2_config_data.js
  {  
  }

Supported Browsers

The Webclient supports Firefox, Chrome and Safari.  For optimal user experience, we recommend Firefox version 66 or greater, Chrome version 74 or greater and Safari 12 or greater.  We no longer support Internet Explorer or Microsoft Edge.  If a user attempts to reach the Webclient with Explorer or Edge they will be presented with instructions and links to use a different browser.