API & Data Model Design Discussion: Free-form data

As part of the OpenMRS ID Platform Improvements project, I propose that we allow applications to store “free-form” data on user objects in OpenMRS ID.

The idea is that external, future applications should be able to store user-related data in the Dashboard without requiring us to implement schema changes. For example, OpenMRS Atlas could, using the REST API, store information about the clinic or implementation a person belongs to. That data could be used by the Dashboard, the wiki, or any other application to build a more comprehensive profile out of that person’s OpenMRS ID.

Technically, I think this can be done by used Mixed attributes in Mongoose, which is a schema-less type that stores any object. The user schema could be something like this:

username: <String>
firstName: <String>
lastName: <String>
locked: <Boolean>
externalInformation: <Mixed>

So, in my example, Atlas might store data in user.externalInformation.atlas, which in turn might be an array of Atlas locations associated with the user. The point is that we don’t have to care what it is, if it’s valid JSON/BSON we can store it!

Here are a couple SO questions about doing the same thing:

If we do this at the schema-level, then the REST API just needs a sensible way to represent information contained in externalInformation as REST resources.

@plypy: you know way more about Mongoose than I do :slight_smile: Do you think my proposal is something that’d be feasible?

1 Like

Well, that’s definitely technically feasible, by this approach. However I think we should be extremely careful on this externalInformation. It will be somehow hard to maintain.

Here are a few my concerns,

  • We must authorize the requests, that’s for sure, perhaps we can use something like API key.
  • We shall carefully isolate each admin users’ data, so we don’t have to worry name conflicts.
  • Each user can only write and read his own data. (Perhaps he can read others?)
  • Once data is isolated, how shall we share the data across applications.

Yep, that’s why OAuth will be an important requirement for this. Since OAuth ensures the identity of the user and application making the API request, we can allow restricted access to private data. And probably the default should be to hide free-form data from other users—though we ought to have a way to make some data shared with other users (maybe a JSON schema that can mark a resource as shared?)

What if we tried something like this:

Each 3rd-party app using OpenMRS ID has its own “namespace” within extra. For example, an app named “Atlas” making requests for the user “elliott” might be able to store its own data at /users/elliott/extra/atlas. Since Atlas would be already registered as an application via the OAuth module, request controllers can explicitly allow write access to /users/<username>/extra/atlas for any authorized API requests coming from Atlas.

Probably the best practice here would be to use OAuth scopes. An application would ask for permission to read and/or write profile data, as well as data from other applications. This would look very similar to other OAuth-based APIs like GitHub’s or Twitter’s: the user consent dialog would include what that that application could read and write.

1 Like

I can get behind this…I owe OpenMRS years of work lol…been lacking

Awesome. Take a look at the REST API spec we wrote toward the end of GSoC last year. It doesn’t have endpoints set up for this free-form data but if you want to work on the currently-nonexistent API it’s a good place to start :wink:

Feel free to comment or make additions…since this work is now outside of the 2014 GSoC project we probably should set up a wiki page for it