diff --git a/LesionTracker/.meteor/packages b/LesionTracker/.meteor/packages index 42be79925..58bfd688d 100644 --- a/LesionTracker/.meteor/packages +++ b/LesionTracker/.meteor/packages @@ -21,6 +21,7 @@ cornerstone worklist viewerbase dicomweb +accounts-base accounts-password ian:accounts-ui-bootstrap-3 @@ -40,12 +41,10 @@ momentjs:moment clinical:router clinical:extended-api clinical:active-entry -clinical:static-pages clinical:error-pages clinical:theming -clinical:theming-ui clinical:fonts -clinical:glass-ui +clinical:hipaa-audit-log clinical:hipaa-logger anti:gagarin@=0.4.11 check diff --git a/LesionTracker/.meteor/versions b/LesionTracker/.meteor/versions index 71f4529fb..3aae6e1e5 100644 --- a/LesionTracker/.meteor/versions +++ b/LesionTracker/.meteor/versions @@ -4,7 +4,6 @@ anti:gagarin@0.4.11 anti:i18n@0.4.3 arsnebula:reactive-promise@0.9.1 autoupdate@1.2.4 -awatson1978:fonts-helveticas@1.0.4 babel-compiler@5.8.24_1 babel-runtime@0.1.4 base64@1.0.4 @@ -18,19 +17,17 @@ caching-html-compiler@1.0.2 callback-hook@1.0.4 check@1.1.0 clinical:active-entry@1.5.14 -clinical:barcode@3.0.1 +clinical:auto-resizing@0.1.2 clinical:error-pages@0.1.1 clinical:extended-api@2.2.1 clinical:fonts@1.0.0 -clinical:glass-ui@1.3.7 +clinical:hipaa-audit-log@2.4.2 clinical:hipaa-logger@1.0.1 clinical:router@2.0.17 clinical:router-location@2.0.14 clinical:router-middleware-stack@2.0.13 clinical:router-url@2.0.15 -clinical:static-pages@1.0.7 clinical:theming@0.3.1 -clinical:theming-ui@0.2.3 coffeescript@1.0.11 cornerstone@0.0.1 ddp@1.2.2 @@ -78,6 +75,7 @@ mobile-status-bar@1.0.6 momentjs:moment@2.10.6 mongo@1.1.3 mongo-id@1.0.1 +mrt:moment@2.8.1 npm-bcrypt@0.7.8_2 npm-mongo@1.4.39_1 observe-sequence@1.0.7 diff --git a/Packages/active-entry/components/entryPages.less b/Packages/active-entry/components/entryPages.less index 693636aaf..2536871c4 100755 --- a/Packages/active-entry/components/entryPages.less +++ b/Packages/active-entry/components/entryPages.less @@ -4,22 +4,23 @@ // this probably wants to be moved into clinical:glass-ui -input, button, select{ - font-size: 14px; - line-height: 20px; - font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; - font-style: 400; - padding: .75rem 0; - line-height: 1.5rem !important; - border: none; - border-radius: 0; - box-sizing: border-box; - //color: #333333; - outline: none; - padding-left: 3em; +.entryPage { + input, button, select{ + font-size: 14px; + line-height: 20px; + font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: 400; + padding: .75rem 0; + line-height: 1.5rem !important; + border: none; + border-radius: 0; + box-sizing: border-box; + //color: #333333; + outline: none; + padding-left: 3em; + } } - .entryLogo{ //background-color: lightgray; height: 200px; diff --git a/Packages/hipaa-audit-log/.gitignore b/Packages/hipaa-audit-log/.gitignore new file mode 100644 index 000000000..677a6fc26 --- /dev/null +++ b/Packages/hipaa-audit-log/.gitignore @@ -0,0 +1 @@ +.build* diff --git a/Packages/hipaa-audit-log/.travis.yml b/Packages/hipaa-audit-log/.travis.yml new file mode 100644 index 000000000..27cbbc9d8 --- /dev/null +++ b/Packages/hipaa-audit-log/.travis.yml @@ -0,0 +1,13 @@ +language: node_js +node_js: + - "0.10" +#sudo: required + +sudo: required + +env: + global: + - METEOR_ENV=development + +before_install: + - "curl -L http://git.io/ejPSng | /bin/sh" diff --git a/Packages/hipaa-audit-log/History.md b/Packages/hipaa-audit-log/History.md new file mode 100644 index 000000000..f4f3d1ba3 --- /dev/null +++ b/Packages/hipaa-audit-log/History.md @@ -0,0 +1,9 @@ + +#### v2.3.7 + +* Updated to use clinical:router + +#### v2.4.0 + +* clinical:hipaa-loger extracted from package +* HipaaLogger and HipaaLog removed diff --git a/Packages/hipaa-audit-log/README.md b/Packages/hipaa-audit-log/README.md new file mode 100644 index 000000000..19dfad1c7 --- /dev/null +++ b/Packages/hipaa-audit-log/README.md @@ -0,0 +1,71 @@ +clinical:hipaa-audit-log +==================================================== + +HIPAA logging and audit features for Meteor Apps built with Clinical UI. + +![HipaaAuditLogScreenshot](https://raw.githubusercontent.com/awatson1978/clinical-hipaa-audit-log/master/screenshots/auditlog.png) + +==================================================== +#### Installation + +The HIPAA audit log is now split into two packages: one for the logging, and one for the UI. Please see [``clinical:hipaa-logger``](https://github.com/clinical-meteor/hipaa-logger) for the logging portion. + +```` +meteor add clinical:hipaa-audit-log +meteor add clinical:hipaa-logger +```` + +==================================================== +#### URL Routes + +Navigate to the audit log via the default route: + +````js +Router.go('/audit'); +```` + +==================================================== +#### Provided Templates + +Three templates are provided by this package: + +````html +{{>hipaaAuditLog}} +{{>hipaaRibbon}} +{{>hipaaLogPage}} +```` + +==================================================== +#### Styling and Classes + +You can adjust the styling of the audit log through the configuration object. The following example shows how to style the audit log with Bootstrap controls. + +````js + HipaaAuditLog.configure({ + classes: { + input: "form-control squee", + select: "form-control", + ribbon: "" + }, + highlightColor: "#006289" + }); +```` + + +==================================================== +#### StarryNight/Nightwatch API - Provides + +````js +// component API calls +reviewHipaaAuditLogPage() +hipaaLogEntryContains(rowIndex, hipaaEvent) + +// actions +logHipaaEvent(hipaaEvent, timeout) +```` + + +------------------------ +### License + +![MIT License](https://img.shields.io/badge/license-MIT-blue.svg) diff --git a/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.html b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.html new file mode 100644 index 000000000..9ea39789f --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.html @@ -0,0 +1,171 @@ + + + + + + diff --git a/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.js b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.js new file mode 100644 index 000000000..acd458a9b --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.js @@ -0,0 +1,131 @@ +//Hipaa = new Meteor.Collection("hipaa"); + +Session.setDefault("hipaaSearchFilter", ''); +Session.setDefault("hipaaTypeFilter", ''); + +// search window defaults to seven days in the past and one day in the future +Session.setDefault("beginDateFilter", new Date(moment().subtract(7, "days")).toISOString()); +Session.setDefault("endDateFilter", new Date(moment().add(1, "days")).toISOString()); + + + + +Template.hipaaAuditLog.onRendered(function () { + Session.set("ribbonWidth", $('#hipaaRibbon').width()); +}); + +Template.hipaaAuditLog.helpers({ + getHipaaSearchFilter: function () { + return Session.get('hipaaSearchFilter'); + }, + hipaaAudit: function () { + // return HipaaLog.find(); + return HipaaLog.find({ + $or: [ + { + userName: { + $regex: Session.get('hipaaSearchFilter'), + $options: 'i' + } + }, + { + patientName: { + $regex: Session.get('hipaaSearchFilter'), + $options: 'i' + } + } + ], + eventType: { + $regex: Session.get("hipaaTypeFilter"), + $options: 'i' + }, + timestamp: { + $lte: new Date(Session.get('endDateFilter')), + $gte: new Date(Session.get('beginDateFilter')) + } + }, { + sort: { + timestamp: -1 + } + }); + } +}); + +Template.hipaaAuditLog.events({ + "keyup #hipaaSearchFilter": function (event, template) { + Session.set("hipaaSearchFilter", $('#hipaaSearchFilter').val()); + } +}); + + +//================================================================================================== +// HIPAA EVENT RECORD + +Template.hipaaEntry.helpers({ + getHighlightColor: function () { + var hipaaAuditLog = Session.get('HipaaAuditLogConfig'); + if (hipaaAuditLog) { + return "color:" + hipaaAuditLog.highlightColor; + } else { + return null; + } + }, + getUserName: function () { + if (this.userName) { + return this.userName; + } else { + return "---"; + } + }, + getPatientName: function () { + if (this.patientName) { + return this.patientName; + } else { + return "---"; + } + }, + hasPatientInfo: function () { + if (this.patientName) { + return true; + } else { + return false; + } + }, + getErrorMessage: function () { + if (this.message) { + return this.message; + } else { + return "---"; + } + }, + getCollectionName: function () { + if (this.collectionName) { + return this.collectionName; + } else { + return "---"; + } + }, + getRecordId: function () { + if (this.recordId) { + return this.recordId; + } else { + return "---"; + } + }, + entryTimestamp: function () { + return moment(this.timestamp).format("YYYY, MMM DD, hh:mm A"); + }, + entryTime: function () { + return moment(this.timestamp).format("HH:MM A"); + }, + entryDate: function () { + return moment(this.timestamp).format("YYYY, MMM DD"); + }, + logMessageType: function (eventType) { + if (this.eventType === eventType) { + return true; + } else { + return false; + } + } +}); diff --git a/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.less b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.less new file mode 100644 index 000000000..0d902457e --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaAuditLog/hipaaAuditLog.less @@ -0,0 +1,74 @@ +#hipaaAuditLog{ + padding-left: 0px !important; + + li{ + list-style: none; + padding-top: 5px; + padding-left: 20px; + } + .gray{ + color: gray; + } + .lightgray{ + color: #aaaaaa; + } + .iconColumn{ + width: 10%; + } + .messageClumn{ + width: 80%; + } + .fa{ + padding-right: 12px; + padding-left: 4px; + padding-top: 6px; + width: 40px; + //border: 1px solid orange; + } + .fa-recycle{ + padding-top: 8px; + } + .fa-plus-circle{ + padding-left: 6px !important; + } + .fa-circle-o{ + padding-left: 6px !important; + } + .fa-minus-circle{ + padding-left: 6px !important; + } + .fa-database{ + padding-left: 7px !important; + } + .fa-pencil{ + padding-left: 6px !important; + } + .fa-code-fork{ + padding-left: 12px !important; + } + .fa-warning{ + padding-left: 5px !important + } + .fa-rss{ + padding-left: 7px !important; + } + + .hipaaAuditItem{ + border-top: 1px solid lightgray; + padding-bottom: 10px; + } + .hipaaAuditItem:nth-child(1){ + border-top: 0px; + } + + .media-body{ + padding-bottom: 5px; + } + + + #hipaaAuditLog{ + width: 100%; + } + + +} diff --git a/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.html b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.html new file mode 100644 index 000000000..f03f7a5fd --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.html @@ -0,0 +1,12 @@ + diff --git a/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.js b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.js new file mode 100644 index 000000000..3d1e10c70 --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.js @@ -0,0 +1,14 @@ +Router.route("/audit", { + name:"hipaaAuditLogRoute", + template:"hipaaLogPage" +}); + + +Template.hipaaLogPage.helpers({}); + +Template.hipaaLogPage.events({}); + +// We probably don't need this, but the subscription in subscriptions.js doesn't seem to be working? +Template.hipaaLogPage.onCreated(function() { + this.subscribe('HipaaLog'); +}) \ No newline at end of file diff --git a/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.less b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.less new file mode 100644 index 000000000..c33ff8508 --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaLogPage/hipaaLogPage.less @@ -0,0 +1,13 @@ + + +#hipaaLogPage{ + background-color: white; + //padding-top: 80px; + + #hipaaLogTitle{ + left: 30px; + position: absolute; + text-align: left; + } + +} diff --git a/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.html b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.html new file mode 100644 index 000000000..c0a38264a --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.html @@ -0,0 +1,14 @@ + diff --git a/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.js b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.js new file mode 100644 index 000000000..01f38cc6f --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.js @@ -0,0 +1,99 @@ +Template.hipaaRibbon.events({ + 'keyup #hipaaSearchFilter': function () { + Session.set("hipaaSearchFilter", $('#hipaaSearchFilter').val()); + }, + "change #beginDateInput": function (event, template) { + Session.set("beginDateFilter", $('#beginDateInput').val() + "T00:00:00.000Z"); + }, + "change #endDateInput": function (event, template) { + Session.set("endDateFilter", $('#endDateInput').val() + "T00:00:00.000Z"); + }, + + 'click #filterCreatedButton': function () { + Session.set("hipaaTypeFilter", 'create'); + }, + 'click #filterModifiedButton': function () { + Session.set("hipaaTypeFilter", 'modify'); + }, + 'click #filterViewedButton': function () { + Session.set("hipaaTypeFilter", 'viewed'); + }, + 'click #filterAllButton': function () { + Session.set("hipaaTypeFilter", ''); + } +}); + +var ribbonBreakPoint = 760; + + +Meteor.startup(function(){ + $(window).resize(function(evt) { + Session.set("ribbonWidth", $('#hipaaRibbon').width()); + }); +}); + +Template.hipaaRibbon.helpers({ + getSearchFilterStyling: function () { + // spacing between inputs should be 20px each + // if the overall width of the audit log is less than N, show the fullwidth + if(Session.get('ribbonWidth') > ribbonBreakPoint){ + var searchFilterWidth = Session.get('ribbonWidth') - 575; + return "margin-left: 10px; margin-right: 5px; width:" + searchFilterWidth + "px;"; + }else{ + var ribbonWidth = Session.get('ribbonWidth') - 40; + return "width: " + ribbonWidth + "px; margin-left: 10px; margin-right: 10px;"; + } + }, + getDateRangeStyling: function () { + // spacing between inputs should be 20px each + // date range inputs shouldn't be less than 170 px + // if the overall width of the audit log is less than N, dont even show them + if(Session.get('ribbonWidth') > ribbonBreakPoint){ + return "visbility: visible; margin-left: 5px; margin-right: 5px; width: 170px;"; + }else{ + return "display: none; visibility: hidden"; + } + }, + getSelectStyling: function () { + // spacing between inputs should be 20px each + // select input should be the same as daterange + if(Session.get('ribbonWidth') > ribbonBreakPoint){ + return "visbility: visible; margin-left: 5px; margin-right: 5px; width: 170px;"; + }else{ + return "display: none; visibility: hidden"; + } + }, + getRibbonClass: function () { + var hipaaAuditLog = Session.get('HipaaAuditLogConfig'); + if (hipaaAuditLog && hipaaAuditLog.classes) { + return hipaaAuditLog.classes.ribbon; + } else { + return null; + } + }, + getSelectClass: function () { + var hipaaAuditLog = Session.get('HipaaAuditLogConfig'); + if (hipaaAuditLog && hipaaAuditLog.classes) { + return hipaaAuditLog.classes.select; + } else { + return null; + } + }, + getInputClass: function () { + var hipaaAuditLog = Session.get('HipaaAuditLogConfig'); + if (hipaaAuditLog && hipaaAuditLog.classes) { + return hipaaAuditLog.classes.input; + } else { + return null; + } + }, + getHipaaSearchFilter: function () { + return Session.get('hipaaSearchFilter'); + }, + getBeginDate: function () { + return moment(Session.get("beginDateFilter")).format("YYYY-MM-DD"); + }, + getEndDate: function () { + return moment(Session.get("endDateFilter")).format("YYYY-MM-DD"); + } +}); diff --git a/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.less b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.less new file mode 100644 index 000000000..f4beb9abf --- /dev/null +++ b/Packages/hipaa-audit-log/components/hipaaRibbon/hipaaRibbon.less @@ -0,0 +1,35 @@ + +#hipaaRibbon{ + position: static; + width: 100%; + padding-top: 10px; + height: 60px; + //background-color: lightgray; + + input[type="date"]{ + padding-left: 10px; + } + input[type="text"]{ + // padding-left: 10px; + // padding-right: 10px; + } + select{ + display: inline-block; + height: 40px; + // padding-left: 10px; + // padding-right: 10px; + } + + #hipaaSearchFilter{ + color: black; + } + //--------------------------------------- + // Bootstrap users + .form-control{ + display: inline-block !important; + } +} + +// @media only screen and (max-width: 850px) { +// +// } diff --git a/Packages/hipaa-audit-log/components/subscriptions.js b/Packages/hipaa-audit-log/components/subscriptions.js new file mode 100644 index 000000000..af01a3b04 --- /dev/null +++ b/Packages/hipaa-audit-log/components/subscriptions.js @@ -0,0 +1 @@ +Meteor.subscribe('HipaaLog'); diff --git a/Packages/hipaa-audit-log/lib/HipaaAuditLog.js b/Packages/hipaa-audit-log/lib/HipaaAuditLog.js new file mode 100644 index 000000000..c0a1b0f11 --- /dev/null +++ b/Packages/hipaa-audit-log/lib/HipaaAuditLog.js @@ -0,0 +1,19 @@ +HipaaAuditLog = { + configure: function (configObject) { + if (Meteor.isClient) { + Session.set('HipaaAuditLogConfig', configObject); + } + //console.log("HipaaAuditLogConfig.configObject", configObject); + } +} + +if (Meteor.isClient) { + Session.setDefault('HipaaAuditLogConfig', { + classes: { + input: "", + select: "", + ribbon: "" + }, + highlightColor: "" + }); +} diff --git a/Packages/hipaa-audit-log/package.js b/Packages/hipaa-audit-log/package.js new file mode 100644 index 000000000..bb2ebcd4c --- /dev/null +++ b/Packages/hipaa-audit-log/package.js @@ -0,0 +1,59 @@ +Package.describe({ + summary: "HIPAA audit log for ClinicalFramework.", + version: "2.4.2", + git: "http://github.com/clinical-meteor/clinical-hipaa-audit-log.git", + name: "clinical:hipaa-audit-log" +}); + +Package.on_use(function (api) { + api.versionsFrom('1.1.0.3'); + + api.use('meteor-platform'); + + api.use('mrt:moment@2.8.1', 'client'); + api.use('grove:less@0.1.1', 'client'); + + api.use('clinical:router@2.0.17'); + api.use('clinical:fonts@1.0.0', 'client'); + api.use('clinical:auto-resizing@0.1.2', 'client'); + api.use('clinical:hipaa-logger@1.0.0'); + + api.imply('clinical:hipaa-logger'); + + api.addFiles('lib/HipaaAuditLog.js'); + + api.addFiles('server/initialize.js', "server"); + api.addFiles('server/publication.js', "server"); + + api.addFiles('components/hipaaRibbon/hipaaRibbon.html', "client"); + api.addFiles('components/hipaaRibbon/hipaaRibbon.js', "client"); + api.addFiles('components/hipaaRibbon/hipaaRibbon.less', "client"); + + api.addFiles('components/hipaaAuditLog/hipaaAuditLog.html', "client"); + api.addFiles('components/hipaaAuditLog/hipaaAuditLog.js', "client"); + api.addFiles('components/hipaaAuditLog/hipaaAuditLog.less', "client"); + + api.addFiles('components/hipaaLogPage/hipaaLogPage.html', "client"); + api.addFiles('components/hipaaLogPage/hipaaLogPage.js', "client"); + api.addFiles('components/hipaaLogPage/hipaaLogPage.less', "client"); + + api.export('HipaaAuditLog'); +}); + + + +Package.onTest(function (api) { + api.use('tinytest'); + + api.use('meteor-platform'); + api.use('iron:router@1.0.4', 'client'); + api.use('mrt:moment@2.8.1', 'client'); + api.use('grove:less@0.1.1', 'client'); + + api.use('clinical:verification'); + api.use('clinical:fonts@1.0.0'); + api.use('clinical:hipaa-audit-log'); + api.use('clinical:hipaa-logger@1.0.0'); + + api.addFiles('tests/tinytest/audit-log-tests.js'); +}); diff --git a/Packages/hipaa-audit-log/screenshots/auditlog.png b/Packages/hipaa-audit-log/screenshots/auditlog.png new file mode 100644 index 000000000..bcaf96b90 Binary files /dev/null and b/Packages/hipaa-audit-log/screenshots/auditlog.png differ diff --git a/Packages/hipaa-audit-log/server/initialize.js b/Packages/hipaa-audit-log/server/initialize.js new file mode 100644 index 000000000..79efc1691 --- /dev/null +++ b/Packages/hipaa-audit-log/server/initialize.js @@ -0,0 +1,26 @@ +Meteor.methods({ + initializeDemoLog:function (){ + console.log('initializeDemoLog'); + + // hipaaEvent, userId, userName, collectionName, recordId, patientId, patientName, message + HipaaLogger.logEvent("init", Meteor.userId(), "Ada Lovelace"); + + HipaaLogger.logEvent("create", Meteor.userId(), "Ada Lovelace", "Users", Random.id(), Random.id(), "John Doe"); + + HipaaLogger.logEvent("viewed", Meteor.userId(), "Mary Shelley", "Users", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("create", Meteor.userId(), "Florence Nightingale", "Vitals", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("viewed", Meteor.userId(), "Florence Nightingale", "Medications", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("create", Meteor.userId(), "Florence Nightingale", "Medications", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("denied", Meteor.userId(), "Kurt Vonnegut", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("create", Meteor.userId(), "Florence Nightingale", "Vitals", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("viewed", Meteor.userId(), "Florence Nightingale", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("modify", Meteor.userId(), "Florence Nightingale", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("viewed", Meteor.userId(), "Edward Doisy", "Users", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("clone", Meteor.userId(), "Edward Doisy", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("publish", Meteor.userId(), "Edward Doisy", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("unpublish", Meteor.userId(), "Edward Doisy", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("delete", Meteor.userId(), "Ada Lovelace", "MedicationPlans", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("viewed", Meteor.userId(), "Florence Nightingale", "Vitals", Random.id(), Random.id(), "John Doe"); + HipaaLogger.logEvent("create", Meteor.userId(), "Florence Nightingale", "Vitals", Random.id(), Random.id(), "John Doe"); + } +}); diff --git a/Packages/hipaa-audit-log/server/publication.js b/Packages/hipaa-audit-log/server/publication.js new file mode 100644 index 000000000..0209a75aa --- /dev/null +++ b/Packages/hipaa-audit-log/server/publication.js @@ -0,0 +1,4 @@ + +Meteor.publish('HipaaLog', function () { + return HipaaLog.find(); +}); diff --git a/Packages/hipaa-audit-log/tests/gagarin/HipaaAuditLogTests.js b/Packages/hipaa-audit-log/tests/gagarin/HipaaAuditLogTests.js new file mode 100644 index 000000000..46aa26b79 --- /dev/null +++ b/Packages/hipaa-audit-log/tests/gagarin/HipaaAuditLogTests.js @@ -0,0 +1,72 @@ + +describe('clinical:hipaa-audit-log', function () { + var server = meteor(); + var client = browser(server); + + // beforeEach(function () { + // server.execute(function () { + // + // }).then(function (value){ + // + // }); + // }); + // afterEach(function () { + // server.execute(function () { + // + // }); + // }); + + it('HipaaLogger should exist on the client', function () { + return client.execute(function () { + expect(HipaaLogger).to.exist; + }); + }); + + it('HipaaLogger should exist on the server', function () { + return server.execute(function () { + expect(HipaaLogger).to.exist; + }); + }); + + + it("HipaaLogger can log events on the client", function () { + return client.execute(function () { + HipaaLogger.logEvent({ + eventType: "modified", + userId: "janedoe", + userName: "Jane Doe", + collectionName: "Medications", + recordId: "123", + patientId: "123", + patientName: "abc" + }); + return HipaaLog.findOne(); + }).then(function (eventRecord){ + server.wait(500, "", function (){ + expect(eventRecord).to.exist; + expect(eventRecord.userId).to.equal("janedoe"); + expect(eventRecord.userName).to.equal("Jane Doe"); + }); + }); + }); + it("HipaaLogger can log events on the server", function () { + return server.execute(function () { + HipaaLogger.logEvent({ + eventType: "modified", + userId: "janedoe", + userName: "Jane Doe", + collectionName: "Medications", + recordId: "123", + patientId: "123", + patientName: "abc" + }); + + var eventRecord = HipaaLog.findOne(); + + expect(eventRecord).to.exist; + expect(eventRecord.userId).to.equal("janedoe"); + expect(eventRecord.userName).to.equal("Jane Doe"); + }); + }); + +}); diff --git a/Packages/hipaa-audit-log/tests/nightwatch/commands/components/hipaaLogEntryContains.js b/Packages/hipaa-audit-log/tests/nightwatch/commands/components/hipaaLogEntryContains.js new file mode 100644 index 000000000..5e09b2916 --- /dev/null +++ b/Packages/hipaa-audit-log/tests/nightwatch/commands/components/hipaaLogEntryContains.js @@ -0,0 +1,20 @@ + + + +exports.command = function(rowIndex, hipaaEvent) { + this + .verify.elementPresent("#hipaaAuditLog .hipaaAuditItem:nth-child(" + rowIndex + ")") + + if(hipaaEvent.type === "create"){ + this + .verify.elementPresent("#hipaaAuditLog .hipaaAuditItem:nth-child(" + rowIndex + ") .userName", hipaaEvent.userName) + .verify.elementPresent("#hipaaAuditLog .hipaaAuditItem:nth-child(" + rowIndex + ") .recordId", hipaaEvent.recordId) + .verify.elementPresent("#hipaaAuditLog .hipaaAuditItem:nth-child(" + rowIndex + ") .collectionName", hipaaEvent.collectionName) + + if(hipaaEvent.patientName){ + this.verify.elementPresent("#hipaaAuditLog .hipaaAuditItem:nth-child(" + rowIndex + ") .patientName", hipaaEvent.patientName) + } + } + + return this; +}; diff --git a/Packages/hipaa-audit-log/tests/nightwatch/commands/components/reviewHipaaAuditLogPage.js b/Packages/hipaa-audit-log/tests/nightwatch/commands/components/reviewHipaaAuditLogPage.js new file mode 100644 index 000000000..3dabb092a --- /dev/null +++ b/Packages/hipaa-audit-log/tests/nightwatch/commands/components/reviewHipaaAuditLogPage.js @@ -0,0 +1,9 @@ + + +exports.command = function() { + this + .verify.elementPresent("#hipaaLogPage") + .verify.elementPresent("#hipaaAuditLog") + + return this; +}; diff --git a/Packages/hipaa-audit-log/tests/nightwatch/commands/methods/logHipaaEvent.js b/Packages/hipaa-audit-log/tests/nightwatch/commands/methods/logHipaaEvent.js new file mode 100644 index 000000000..8e4b44e1b --- /dev/null +++ b/Packages/hipaa-audit-log/tests/nightwatch/commands/methods/logHipaaEvent.js @@ -0,0 +1,41 @@ + + + + +// syncrhonous version; doesn't work well +/*exports.command = function(hipaaEvent, timeout) { + var client = this; + this + .execute(function(data){ + return HipaaLogger.logEventObject(data); + }, [hipaaEvent], function(result){ + console.log("result.value", result.value); + client.assert.ok(result.value); + }).pause(1000) + return this; +};*/ + + + + +// async version calls method on the server +exports.command = function(hipaaEvent, timeout) { + var client = this; + if (!timeout) { + timeout = 5000; + } + + this + .timeoutsAsyncScript(timeout) + .executeAsync(function(data, meteorCallback){ + //return HipaaLogger.logEventObject(data); + Meteor.call('logHipaaEvent', data, function(meteorError, meteorResult){ + var response = (meteorError ? { error: meteorError } : { result: meteorResult }); + meteorCallback(response); + }) + }, [hipaaEvent], function(result){ + console.log("result.value", result.value); + client.assert.ok(result.value); + }).pause(1000) + return this; +}; diff --git a/Packages/hipaa-audit-log/tests/tinytest/audit-log-tests.js b/Packages/hipaa-audit-log/tests/tinytest/audit-log-tests.js new file mode 100644 index 000000000..459385929 --- /dev/null +++ b/Packages/hipaa-audit-log/tests/tinytest/audit-log-tests.js @@ -0,0 +1,25 @@ +describe('clinical:hipaa-audit-log', function () { + + describe('user interface', function () { + it.client('displays an audit log', function () { + + }); + it.client('has a search button', function () { + + }); + it.client('has filter buttons', function () { + + }); + }); + + describe('server functionality', function () { + it.client('logs hipaa events to a HIPAA collection', function () { + + }); + + it.client('doesnt allow users to delete or modify events', function () { + + }); + + }); +}); diff --git a/Packages/worklist/components/worklist.js b/Packages/worklist/components/worklist.js index 1f717c387..be47cf775 100644 --- a/Packages/worklist/components/worklist.js +++ b/Packages/worklist/components/worklist.js @@ -55,6 +55,21 @@ getStudyMetadata = function(studyInstanceUid, doneCallback) { // Finally, we fire the doneCallback with this study meta data doneCallback(study); + + // Temporary: Testing out the Clinical Meteor HIPAA Audit log + if (Meteor.user()) { + log.info('Adding access to HIPAA Log'); + var hipaaEvent = { + eventType: "access", + userId: Meteor.userId(), + userName: Meteor.user().profile.fullName, + collectionName: "Studies", + recordId: studyInstanceUid, + patientId: null, + patientName: null + }; + HipaaLogger.logEvent(hipaaEvent); + } }); };