GSOC 2019: OpenMRS Atlas 3.1

I think we could add subscribe and unsubscribe buttons to info-windows of markers. If you like the idea, I guess we could implement it. I’m not entirely sure if its worth it, but I guess it could be done.

Also the download button is fixed now. I created a PR and merged it as it was a small change.

Following (subscribing to) a marker isn’t really a feature we need and there are many other more useful features to be done (fixing the module, reporting on data, search, etc.), I don’t think we should pursue marker subscriptions. The only reason it came up at all is because we can’t send people emails from a service without including mechanism for them to unsubscribe from all future emails. That would be impolite. :slight_smile:

And you deployed to staging… excellent! Though, at first glance on Safari on my iPhone, it looks like I still get a map without markers as a download image.

1 Like

It seems to work on my android phone, and mozilla on my pc. Does the downloaded image show markers on your Mac?

Also, what should the subscribe and unsubscribe links look like? I’m not very proficient at link designing, :confused:

Using Chrome on my Mac, I see the markers and it appears to work fine, but the download fails if my browser window is too big. It appears to begin failing around dimensions 1140x1000 or 1200x900 pixels. If my window is those dimensions or larger, instead of downloading an openmrs-atlas.png file, it shows the name download followed by “Failed - Network error”. I don’t see any other clues in the console or network fetches.

First, make sure the /login endpoint takes a URL-encoded redirect parameter – i.e., a request to /login?redirect=%2Ffoo should send the user to /foo after they successfully login. To avoid abuse of this feature, only process relative paths and silently ignore a redirect parameter that redirects to other websites (requests like /login?redirect=https%3A%2F%2Fgoogle.com would just send the user back to the atlas after login).

Then, browsing to /unsubscribe would check if the user is authenticated and…

  • If not authenticated, redirect to /login?redirect=%2Funsubscribe
  • If authenticated and already unsubscribed (you’ll need to implement GET /unsubscribed to check this), render the atlas and present a popup like “You have been unsubscribed from any email notifications from Atlas.”
  • If authenticated and not yet unsubscribed, render the atlas and present a dialog saying something like “Unsubscribe from all email notifications from Atlas? YES NO” with NO selected by default. If the user dismisses or selects NO, they’re just at the Atlas main screen. If they select YES, you invoke the API to unsubscribe them and then show the “You have been unsubscribed from any email notifications from Atlas.” popup.

There is no “subscribe” link. We could create a ticket to address later to give unsubscribed users the option to opt back in to notifications if/when they created a new marker (i.e., instead of just reporting the marker was saved, an unsubscribed user would see a message like “You have previously unsubscribed from any emails from Atlas, so you won’t be notified if this marker needs to be updated. Do you want to turn Atlas notifications back on?”).

1 Like

Same here. I think we may have a clue.

I made the requested changes for ATLAS-168. :slight_smile: I also added the tables in the PR to atlas-stg for testing.

Merged!

Are we ready to request others to test atlas-stg? Can anyone log into atlas-stg or is it connected to a staging ldap? If authentication is limited, perhaps we could make a test account (even temporarily) for people to use in testing. I was thinking we could direct them to a feedback link like this. :slight_smile:

I may have messed up the PR a little. Some remnants from the previous version of the plan of the ticket remained in the PR at the time of merging. I didn’t notice them until after it got merged. I’ll clear them up in a few min, and let you know.

Fixed! Sorry about that. I guess we’re ready to request some testing. :slight_smile: A friend of mine could log into atlas-stg, so I think anyone may be able to login.

Awesome! Try hopping into our IRC channel or Slack and see if you can convince a few people to try out atlas-stg.openmrs.org, kick the tires, and give you some feedback. Let 'em know they can turn off fading in the menu and, if they happen to have an old marker on atlas-stg, they should still be able to edit it. Some specific folks (you may not find them on IRC or Slack but they might chime in here or you could try sending them a DM in Talk) who might be interested in trying it out: @ball, @akanter, and @ahabib. Others who I’m sure would be happy to help try it out : @jennifer, @dkayiwa, and @c.antwi.

Be respectful of their time and feel free to throw my name in if it helps (e.g., Burke and I were hoping if you get a chance, you could browse to atlas-stg.openmrs.org, edit an old marker or add a new one, and let us know if you see any issues). Also, make sure they know to test out atlas-stg.openmrs.org (not atlas.openmrs.org). :slight_smile:

FYI – I restored the date_changed values on atlas-stg, so it has faded markers again. For anyone with an existing, faded marker, this will give them the thrill of clicking on the update link and seeing their marker come back to life. :+1:

If you can mange to get 3-5 or more people to test it out without significant issues, we’ll promote it to production and make an announcement to the community that Altas is back, baby!

1 Like

@burke @harsha89 @cintiadr I created a talk post for it and also posted it on IRC. :slight_smile:

While testing continues, I’d like to start working on the Atlas module. According to my understanding, this is how things should work:

  • The module sends a POST request to the server, containing a uuid, which is the module’s id.
  • If this id isn’t found in some “module” table, we will store this id in the table.
  • If there are no errors, the server will indicate it, the module starts running, and the server session is now in “module mode”.
  • Any marker created from within this module mode will also have an auth entry with the module’s id as the token.

Some questions I have are:

  • How do we know that the POST containing the uuid actually comes from a module?
  • If multiple sites were created in module mode in the same openmrs instance, do we update all these sites with the same data?

The atlas module never creates a marker; rather, it is entrusted to send updates during the creation of a marker by a user. Also, the module can only be linked to a single marker, since the purpose of the marker is to represent a single OpenMRS server (i.e., a marker on the atlas for the server it’s running on).

This is based on some dusty recollection, so don’t be surprised if you find discrepancies between my description here and the code.

In its first iteration, the module was responsible for creating the marker, but as we improved the Atlas server, we realized that 90% of the marker management (even using the module) could be done through the server’s web interface with a much lighter interaction with the module. Now the module loads the Atlas server web page in an iframe, passing a parameter to let the server know it’s running inside the module.

  • The user authenticates to Atlas server (the usual way) inside the iframe
  • In module mode, the server allows the user either to link an existing marker or create a marker (only one) that is linked to the OpenMRS instance (i.e., the module)
  • When the user either links an existing marker or creates a new one, the module server sends the server a unique token (a uuid). We used to use this as the uuid for the marker (which is why we were hiding them). Now, this token sent from the module would be stored as the auth token. It’s a “secret” that only the module & server know, which is how the server can trust a ping from the module (it’s sent with the auth token… ideally in the body of a POST and not in the URL, which risks exposing the secret).
  • When linking a marker to the module (whether an existing marker or a newly created marker), the user is given the chance to opt-out of sending additional data to the server (e.g., patient/encounter/obs counts, server info, running modules & versions).

Once the module is linked to a marker, all the module does is issue a weekly ping that updates the marker (keeps it from fading) and optionally send the additional data. The current module probably does an HTTP GET with the module’s UUID and an extra secret phrase (SESSION_SECRET). We’d want to switch this to a POST with the module’s UUID (as an auth token) inside the body (not exposed in the URL) and we could get rid of the SESSION_SECRET since it’s not needed.

1 Like

Here’s how I could link the module with the Atlas server. I assume you already have the Atlas server running.

  • Clone the openmrs-module-atlas repo.
  • Go to AtlasConstants.java, and change the value of SERVER_URL to the URL of your local server. You could also change SERVER_PING_URL to redirect pings to your server, but the ping route doesn’t really work.
  • Build the module using mvn clean install, load it into OpenMRS, and open the ‘Manage Atlas Markers’ page to see your module’s iframe connected to your server.

@heliostrike,

Some more thoughts on the API for the module…

When the module first runs, it should auto-generate and save an internal uuid that will serve as its token for the Atlas. This is the secret we don’t want to expose in urls and what we’ll store in the auth table for a module.

Module start with:

POST /module
 {
  token: "module-generated-uuid"
}

and server responds with either:

HTTP 200 OK
[
  { /* linked marker here */ }
]

or, if no marker has been linked:

HTTP 200 OK
[ ]

Then module loads iframe with src /?module=true (while we could pass the linked marker id here, let’s not because the user can change the linked marker while interacting with the iframe). The following behavior applies only to Atlas Server when it’s in this “marker mode.”

If a user isn’t authenticated, the OpenMRS Atlas redirects them to /login.

When the Atlas website finishes loading in module mode and a user is authenticated, it would ask the module (through the iframe) for it’s linked marker and, if one exists, it would set focus to the linked marker (just as if we loaded the atlas website with /?id={id} for that marker).

I believe this code will already show a “This is not me” link on a linked marker and show a “This is me” link on any other markers the authenticated user can edit, which is the behavior we want.

If a marker is linked, then the user shouldn’t see the “Create a marker” option in the menu.

If we haven’t yet linked a marker, the user would see the “Create a marker” option and creating a marker would automatically link it to the module.

Linking a marker to the module should store the module’s token in the auth table for that marker. Likewise, unlinking a marker from the module should remove this auth rule to ensure a module is never linked to more than one marker. In essence, the auth rule represents the link between module & marker.

1 Like

I started working on this issue. I could connect the module to the atlas server using a POST, and save the module-id and marker data on the module page session, but the module page and iframe are running on different sessions. We’ll need the module-id and marker-id in the iframe session to get things running. I’ve been searching for a solution for the last hour but I think I’m stuck. How do we solve this?

Do you have communication between the iframe and parent set up (e.g., using cross-document messaging)?

Glancing at the module source, I see it uses DWR, which was deprecated years ago. Ugh.

1 Like

I’m unfamiliar with cross-document messaging, will have to look it up. Thanks for the lead. :slight_smile:

“Node js sharing sessions across domains” I’ve been googling the wrong thing the whole day!

Yes. The messaging will all happen client side via javascript – e.g., when Atlas finishes loading (within the iframe in “module mode”) it fires an event to notify the parent (module’s web page), which can turn around and provide the info needed.

Unfortunately, the web pages for the module (unless there’s a branch other than master with newer code) appears to be legacy code and may need to be rewritten for newer versions of OpenMRS.

1 Like

Sorry about the late update. I made 2 PRs to make the atlas module work with atlas.

Atlas PR: Created module mode. ‘Module mode’ is stored in the session. When its switched on, the iframe expects the module ID and ‘has_site’ from the parent window, and activates module mode. Here users can attach or detach modules and markers.

Atlas Module PR: Setup cross-window communication. When sending data is enabled, sends POST requests to update markers.

If you’d like to test the atlas module, change the server url here and maybe reduce the POST data interval here to test whether POST is working properly.

While the atlas module PRs are in the oven, I’d like to take up the search for markers ticket. I was curious about how we’d search for markers, do we return markers where the search phrase is a substring of a marker’s name, or where its the prefix of the name, or is there any other criteria we need to consider? What do you think?

I’ve made PRs on most of the new tickets created but I have a few questions about a few of them.

  • ATLAS-206 - Would we want to create a GET to retrieve details about usage of all modules? I think it would help with ATLAS-207.

  • ATLAS-203 - It looks like most of the console.log(error);s are being used to log mysql query errors. What should I do in these cases?

I also updated the module PRs (ATLAS-194, ATLAS-195) to work with each other, and created a PR for searching markers. They are unrefined, but I think the project objectives are almost complete. :slight_smile:

1 Like