This gem is a collection of resources to help build Rails applications on AI Bridge.
Installation¶
To install the harbinger-rails-extensions
gem add the following to your Gemfile:
gem 'harbinger-rails-extensions', source: 'http://gem.analytical.info:9292'
Single Sign-on¶
Page Filtering¶
The gem provides methods for authentication/authorization filtering requests using the SDK and filtering specific page content within views. Filtering pages can be done using the authenticate_and_authorize
method. It takes as the first argument an Array
of clinical role names. Each item in that Array
can be its own array that represents a group of clinical roles that are all required. The second argument is an entity manager. Here are some examples:
# Only ai-staff, it-staff, and radiologist roles can access this page
authenticate_and_authorize(["ai-staff","it-staff","radiologist"],@entity_manager)
# Only ai-staff or someone in both the radiologist and supervisor roles can access this page
authenticate_and_authorize(["ai-staff",["supervisor","radiologist"]],@entity_manager)
Best Practice - Typically you'll create your own methods that use
authenticate_and_authorize
as yourbefore_filter
. This demonstrated in the backend Rails tutorial.
You need to create a route and controller/controller method to handle the redirect of authenticate_and_authorize
when the user does not have the required role(s). Here is an example route:
get 'unauthorized' => "unauthorized#index"
Hiding page components by role¶
In addition to redirecting an unauthorized user, it is possible to show different fragments of a page dependent on employee-clinical role mappings. Here is an example of a block helper that hides components of a view unless the logged in user is authorized to see them:
<% authorized(["radiologist","ai-staff"],@entity_manager) do %>
<h1>You will only see this heading when the logged in user is a radiologist or ai-staff</h1>
<% end %>
Note - The
authorized
block helper is using a concat-based method to add the contents of the block to the page. Do not put an=
in theerb
tag, similar to the each expression.
You can also use the authorize_all
which requires that the logged in user have all of the clinical roles in the list.
In addition to the block helpers, there are other helpers that return booleans. They have the same names as the block helpers with a ?
suffix (e.g. authorized?(["radiologist"])
). These methods reflect the behaviors found on Java::HarbingerSdk::Employee
instances: authorizedForAny
, authorizedForAll
. These methods can be found in the SDK API documentation.
Logout button¶
Apps should always give the user a way to log out. This is done with a link that has the href
set to the value returned by the SDK method Java::HarbingerSdk::SSO.logoutUrl()
:
<a href="<%= Java::HarbingerSdk::SSO.logoutUrl() %>">Logout</a>
Usage Logging¶
To log application usage statistics, add the following line to the application controller:
after_filter :log_usage_data
This library will take care of capturing information from the request and sending it to be logged. Application usage data is viewable in the Service Tools application.
Messaging¶
Application Generated¶
When building an application you may find that you not only need real-time clinical data, but you also want to alert others in your application of an action taken by a user. To send a message to the messaging bus you can use Harbinger::Rails::Extensions::Messaging.send_application_message
. It takes three arguments:
- Your application name (the canonical / approved short name of the application)
- A routing key
- The payload or body of the message. This can be any string.
Here is an example for an application exampleapp
inside a model that defines a employee_id
, rad_exam_id
, and attributes
:
def send_amqp_message
Harbinger::Rails::Extensions::Messaging.send_application_message("railsdevelopertutorial","#{self.employee_id}.#{self.rad_exam_id}",self.attributes.to_json)
end
Consuming messages server-side¶
HarbingerJS provides a way to consume messages in real-time by the client (browser), but there are some situations where you may want to consume messages server-side. Handling this as a background task will require a cron script. The script will make a request to a URL which can consume and process messages stored in a queue. This is an example controller request to build a queue and consume messages from the audit
exchange:
dev BackgroundTasks < ApplicationController
before_filter :cron_authentication
def process_queue
conn = Bunny.new(Harbinger::Rails::Extensions::Messaging.bus_credentials)
conn.start
channel = conn.create_channel
exchange = Bunny::Exchange.new(channel,:topic, "audit", :durable => true)
# prepend the name of your queue with your application name
# making your queue durable will ensure messages will survive a server restart
queue = Bunny::Queue.new(channel,"application-name-queue",:durable => true)
queue.bind(exchange,routing_key: "rad_exams.#")
while (queue.message_count > 0) do
message = queue.pop
# ... Process the given message
# A message is an Array where
# [0] is information about the message,
# [1] is information about the transport, and
# [2] is the message payload
end
conn.close
render :nothing
end
end
HarbingerJS¶
Setup¶
HarbingerJS uses serverside information to setup proper routing of resource/AJAX calls and the location of cometd
(the HTTP push messaging system). Add a call to harbingerjs_setup()
to your application view to set up this information so it is available for HarbingerJS. This call must come before the requirement of the HarbingerJS libraries. If you are including HarbingerJS as part of the asset pipeline's application.js
you will need to place the harbingerjs_setup()
call before a call to javascript_include_tag "application"
. Here is the head of a typical application layout:
<head>
<title>My Application</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= harbingerjs_setup %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
<!-- ... anything else you might have -->
</head>