NAV
shell ruby javascript html

Orbita

Summary

Deployment and Server Configuration

Introduction

orbita is a product useful to:

Using orbita you can reduce your time to market and your time to break even

orbita is a product by coders51

This projects is based on microservices and exchange domain events on a event bus.

The actual services are:

General Architecture Details

orbita is a microservice collaboration platform.

Image of Yaktocat

Some info about this kind of architecture:

Quick reference for setup of a production server

To install orbita on an existing server you need the following environment on your production server:

Components are in ruby on rails and elixir, for some component we need:

HTTP API Documentation

The documentation is written in markdown following the API Blueprint Specification

Notifications API

Notification service

Group User Notifications

All these requests requires a JWT token to identify the user

Unread Notifications [/users/{ID}/notifications/unread]

All the unread notifications addressed to the identified user. The JWT_TOKEN is given by the OAuth server and contains encrypted informations about the user.

Retrieve Unread Notifications [GET]

Retrieve all the unread notifications of the user

Mark Notifications As Read [DELETE]

Mark all the unread notifications of the user as read

Unread Notification [/notifications/unread/{ID}]

Unread notification. The JWT_TOKEN is given by the OAuth server and contains encrypted informations about the user.

Mark Notification As Read [DELETE]

Mark single notification as read. The authenticated user must be the sender or the receiver of the notification

Notification [/notifications/{ID}]

Notification. The JWT_TOKEN is given by the OAuth server and contains encrypted informations about the user.

Retrieve Notification [GET]

[NOT IMPLEMENTED YET] Retrieve single notification. The authenticated user must be the sender or the receiver of the notification

Delete Notification [DELETE]

[NOT IMPLEMENTED YET] Delete the single notification.

Enable notifications [POST /users/:user/notifications/by/:media/enabled]

Enables a given notification media (e.g., email or websockets) for a given user.

Disable notifications [POST /users/:user/notifications/by/:media/disabled]

Disables a given notification media (e.g., email or websockets) for a given user.

Read notifications settings for a media [GET /users/:user/notifications/by/:media]

Tells whether notifications on the given :media are enabled for the given :user.

Read notifications settings for all media [GET /users/:user/notifications/by/:media]

Tells whether notifications are enabled/disabled for each media for the given :user.

Group WebSocket

WebSocket Library [/js/app.js]

The library to use to establish the WebSocket connection. See the official documentation on how to use it client side.

Retrieve WebSocket Library [GET]

WebSocket Handshake [/socket/websocket?jwt_token={JWT_TOKEN}]

To establish a WebSocket connection, the client sends a WebSocket handshake request, for which the server returns a WebSocket handshake response. The JWT_TOKEN is given by the OAuth server and contains encrypted informations about the user.

WebSocket Handshake [GET]

How to generate HTML

Using aglio an HTML file can be generate starting from a Blueprint file

> To install, use this code:

$ npm -g install aglio
> HTML Generation

$ aglio -i http-api-mta-notifications.md -o http-api-mta-notifications.html

FORMAT: 1A

Networking API

Networking service. The endpoints on this API expose resources that represent relationships across different users and things.

Group Friend Requests

The friend request resource represents a request to connect from one user to another. A friendship between users can only be created when a friendship request has been accepted. There are five(5) endpoints for this resource..

List of Friend Requests [/friend_requests]

A resource representing all of a user’s friend requests.

Fetch all Friend Requests [GET]

Fetches all friend requests sent and received by a user. The user is identified through the Authorization header provided.

Create a Friend Request [POST]

It expects a to param which should be an oauth_id of a user to whom the request is sent to. An Authorization header is required to identify the user who sent the request. You may only create one (1) friend request between two (2) users.

List of Friend Requests [/friend_requests/{id}]

A resource representing all of a user’s friend requests.

Deletes a Friend Request [DELETE]

An Authorization header is required to identify the user who sent the request.

Accept Friend Request [/friend_requests/{from}/accept]

For accepting a friend request.

Accept a Friend Request [PUT]

Deleting a friend request and creates a friend resource in its place. The user accepting the friend request is identified through the Authorization header. You can only accept a friend request once.

Refuse Friend Request [/friend_requests/{from}/refuse]

For refusing a friend request.

Refuse a Friend Request [DELETE]

The user accepting the friend request is identified through the Authorization header.

All Friends [/friends]

The friend resource represents a friendship between two (2) users. A friendship is only created when a friend request has been accepted by a user.

Fetch all Friends [GET]

Get all friends of a user. The user is identified through the Authorization header provided.

A friend [/friends/{id}]

Delete Friendship [DELETE]

An id param is expected which identifies the current user’s friend. The current user is identified through the Authorization header provided.

All Friends for Services [/private/friends]

Friends resource meant to be accessed by other MTA services.

Fetch all Friends [GET]

Get all friends of a user. The user is identified through the id query parameter. AUTH_CODE is the Base64-encoded, sha256 hash of a secret key shared across services and the url of the endpoint.

Friendship Check for Users [/friends-with/{id}]

Check if Two (2) Users are Connected [GET]

The current user is identified through the Authorization header provided.

Friendship Check for Services [/private/friends-with]

Check if Two (2) Users are Connected [GET]

AUTH_CODE is the Base64-encoded, sha256 hash of a secret key shared across services and the url of the endpoint.

Authentication & Authorization

Introduction

All services share a secret key

Scenario 1 - Authentication/Authorization between services

  1. Service A calls Service B (example: http://foo.orbita.com/api/v1/users)

  2. Service A takes Service B URL (http://foo.orbita.com/api/v1/users) and encrypt it with SHA-256 using the shared key, encode it in base64 and put the resulting token in an header (example: Authorization: X-C51 xxxxxxxxxxxx).

  3. Service B receives the call, checks if the header is present and do the same process of point 2. Than Service B checks if both token are equal and only in this case it responds with the requested resource.

If you want to try it in your shell, given $URL as the URL of the resource that needs authentication and given $SECRET the shared key: shell $ curl -vvv $URL -H 'Accept: application/json' -H "Authorization: X-C51 `echo -n $URL | openssl dgst -sha256 -hex -hmac $SECRET | cut -d ' ' -f 2`"

Scenario 2 - Authentication/Authorization between apps and services

Login Process

  1. Application A calls orbita-oauth requesting a standard OAuth 2.0 login process.
  2. orbita-oauth responds back with a access token (in jwt format) containing this data:
          {
            user: {
              id: 'xxxxxxxxxxx',
              email: 'xxxxxxxxxxx',
              expiration_date: 'xxxxxxxxxxx',
              date: 'xxxxxxxxxxx'
            }
          }

and a refresh_token.

  1. If Application A is an internal Orbita app it creates a cookie to share both tokens with orbita-components.
  2. If Application A find that a cookie is already present it simply calls orbita-oauth to verify if the token is still valid. If the token is not valid Application A uses the refresh_token to request to orbita-oauth another valid token.

Resource Request Process

  1. Application A calls Service B (example: http://foo.orbita.com/api/v1/users) and include the jwt token in the header Authorization: Bearer xxxxxxxxxxxxxx
  2. Service B calls orbita-oauth and check if the token is valid. If it’s valid it responds with the requested resource

General Considerations

In general keep in mind that:

Orbita Components API

Setup

  1. Add to your html file next scripts:
    • <script src="<%= Rails.application.secrets.cdn_url %>/orbita_components.js"></script>
    • <script src="https://cdn.polyfill.io/v2/polyfill.js?features=Intl.~locale.en"></script>
    • <script src="https://cdn.polyfill.io/v2/polyfill.js?features=Intl.~locale.it"></script>
  2. Add styles:
    • <link href="<%= Rails.application.secrets.cdn_url %>/orbita_components.css" rel="stylesheet">

API

example: orbitaComponents.showFlashMessage('lorem ipsum', 'info', 2500)

Example:

<div id="orbita_toolbar_wrapper">
</div>

<div id="orbita_body">
</div>

<div id="orbita_footer">
</div>
orbitaComponents.init({
  toolbar: {
    wrapperId: 'orbita_toolbar_wrapper', links: [
      {
        url: 'https://foo.com',
        it: 'Foo IT',
        en: 'Foo EN'
      },{
        url: 'http://boo.com',
        it: 'Boo IT',
        en: 'Boo EN'
      }],
      logoImage: "<%=asset_url('white_logo.png') %>",
      logoWidth: "165px",
      logoHeight: "36px"
  },
  footer: {wrapperId: 'orbita_footer'}
});
orbitaComponents.init({
  toolbar: {
    wrapperId: 'orbita_toolbar_wrapper', links: [
      {
        url: 'https://foo.com',
        it: 'Foo IT',
        en: 'Foo EN'
      },{
        url: 'http://boo.com',
        it: 'Boo IT',
        en: 'Boo EN'
      }, {
        url: '/settings',
        it: 'Settings',
        en: 'Settings',
        authorization: function(currentUser){ return currentUser }
      }],
      logoImage: "<%=asset_url('white_logo.png') %>",
      logoWidth: "165px",
      logoHeight: "36px"
  }
});

Example with Friend Button

 <div>
   <p>Alex Err with id 2</p>
   <div id="button_connect"></div>
 </div>
 <script type="text/javascript" charset="utf-8">
   orbitaComponents.renderFriendshipButton({wrapperId: 'button_connect', userId: 2});
</script>
orbitaComponents.init({
  toolbar: {
    userMenu: {
      links: [
        {
          url: 'http://www.facebook.com',
          it: 'Faccebooke',
          en: 'Facebook'
        }
      ]
    }
  }
})

Verify JWT Token

Metadata

Every domain event will have the same metadata * id (UUID): an UUID generated by the service that emitted the event * type (string): the type of the event * source (string): the name of the service that emitted the event * emitted_at (datetime): the time at which the event is emitted * correlation_id (string): an id that can be used to create relationship between events (ex. If I group friendship events using the correlation_id I will expect to see groups of events like [FriendshipRequested, FriendshipAccepted] or [FriendshipRequested, FriendshipRefused]) * payload (object): event specific data

Domain Events

FriendshipRequested

Emitted on channel orbita-networking

Emitted from the orbita-networking service when a user requests friendship from another user * from (UUID): the OAUTH id of the user that requested the friendship * to (UUID): the OAUTH id of the target user

Example: javascript { "id": "95494570-BA22-488E-AF9A-E272589ACEA2", "type": "FriendshipRequested", "source": "networking", "emitted_at": "2015-09-17T13:55:02.930Z", "correlation_id": "80F2564A-0B14-4731-BF6A-B7D3CAA61E48", "payload": { "from": "C3B499C8-7F7F-45D0-82D7-75BFFF7417FD", "to": "5B5A541F-2E16-4DAA-9AA5-710EDF09E6E4" } }

FriendshipAccepted

Emitted on channel orbita-networking

Emitted from the orbita-networking service when a friendship request has been accepted by a user. * from (UUID): the OAUTH id of the user that requested the friendship * to (UUID): the OAUTH id of the target user * request_id : the id of the friend request

FriendshipRefused

Emitted on channel orbita-networking

Emitted from the orbita-networking service when a friendship request has been refused by a user. * from (UUID): the OAUTH id of the user that requested the friendship * to (UUID): the OAUTH id of the target user * request_id : the id of the friend request

UserCreated

Emitted on channel orbita-oauth

Example: “`javascript

{ "id”: “95494570-BA22-488E-AF9A-E272589ACEA2”, “type”: “UserCreated”, “source”: “orbita-oauth”, “emitted_at”: “2015-09-17T13:55:02.930Z”, “payload”: { user: { id: 1, email: ‘example@mail.com’, first_name: 'first’, last_name: 'last’ } } } “`

UserUpdated

Emitted on channel orbita-oauth

Example: ”`javascript

{ “id”: “95494570-BA22-488E-AF9A-E272589ACEA2”, “type”: “UserUpdated”, “source”: “orbita-oauth”, “emitted_at”: “2015-09-17T13:55:02.930Z”, “payload”: { user: { id: 1, email: 'example@mail.com’, first_name: 'first’, last_name: 'last’ } } } “`

User language changed

Emitted on channel orbita-oauth

Example: ”`javascript

{ “id”: “95494570-BA22-488E-AF9A-E272589ACEA2”, “type”: “UserLanguageChanged”, “source”: “orbita-oauth”, “emitted_at”: “2015-09-17T13:55:02.930Z”, “payload”: { “user_id”: 1, “from”: “en”, “to”: “it” } } “`

UserDeleted

Emitted on channel orbita-oauth

Example: javascript { "id": "95494570-BA22-488E-AF9A-E272589ACEA2", "type": "UserDeleted", "source": "orbita-oauth", "emitted_at": "2015-09-17T13:55:02.930Z", "payload": { "user_id": 1, } }

UserLogout

Example: javascript { "id": "95494570-BA22-488E-AF9A-E272589ACEA2", "type": "UserDeleted", "source": "orbita-oauth", "emitted_at": "2015-09-17T13:55:02.930Z", "payload": { "user_id": 1, } }

  1. Oauth service must be run on 5100
  2. JWT-Test app must be run on 3000
  3. Network app must be run on 4001
  4. Components must be run (webpack) on 8080

Mta-Oauth create apps

Example:

  Redirect uri: "http://portal.mysite-staging.com/users/auth/oauth51/callback",
  Uid: "dc58bccd82602fa1c86bdff342e3c627d44dd642dabf2e9b645ea0e501291d14",
  Secret: "a19c7a77185df47182dbe241a9e02614465da2dfe8f06d7fe888645465312001"

Then go to your application (jwt_test, developers) and add this secret and id to secret.yml

How to create new application and use all orbita services

Create new rails app

How to compose your secret.yml file

Login section

For login, you can use oauth provider, and implement it in your application. Let’s do it: * Add to devise.rb:

config.omniauth :oauth51, Rails.application.secrets.oauth['client_id'],   Rails.application.secrets.oauth['client_secret'], scope: 'public accounts points', client_options: {site: Rails.application.secrets.oauth['app_url']}

  class OmniauthCallbacksController < Devise::OmniauthCallbacksController

    COOKIES_KEY = :_jwt_token
    COOKIES_REFRESH_KEY = :_refresh_token

    def oauth51
      o51_authentication_token = request.env["omniauth.auth"].credentials.token
      o51_refresh_token = request.env["omniauth.auth"].credentials.refresh_token

      ### We need set token to cookies, then all apps can use it for login user.
      set_auth_cookies(o51_authentication_token, o51_refresh_token)
      client = Oauth51Client::Client.new(o51_authentication_token, Rails.application.secrets.oauth['app_url'])
      client.me # returns info about user
      User.create_from_o51(client.me)
    end

    private

    def set_auth_cookies(jwt_token, refresh_token)
      cookies[COOKIES_KEY] = {
        value: jwt_token,
        expires: 7.days.from_now,
        domain: :all
      }
      cookies[COOKIES_REFRESH_KEY] = {
        value: refresh_token,
        expires: 7.days.from_now,
        domain: :all
      }
    end
  end
  module JwtLogin
    extend ActiveSupport::Concern

  COOKIES_KEY = :_jwt_token
  COOKIES_REFRESH_KEY = :_refresh_token

  def login_with_jwt(tries=0)
    return delete_cookies if tries > 1
    jwt_token = cookies[COOKIES_KEY]
    url = Rails.application.secrets.oauth['app_url'] + "/api/v1/users/me"
    begin
      user_info = RestClient.get(url, {'Authorization' => "Bearer #{jwt_token}"})
    rescue => e
      if e.to_s.match(/401/)
        return unless cookies[COOKIES_REFRESH_KEY]
        refresh_token(cookies[COOKIES_REFRESH_KEY])
        login_with_jwt(tries + 1)
      end
      return nil
    end
    User.create_from_jwt_token(JSON.parse(user_info))
  end

  def refresh_token(token)
    params = {
      grant_type: "refresh_token",
      client_id: Rails.application.secrets.oauth["client_id"],
      client_secret: Rails.application.secrets.oauth["client_secret"],
      refresh_token: token
    }
    begin
      token_data = RestClient.post(Rails.application.secrets.oauth["app_url"] + '/oauth/token', params)
    rescue => e
      return nil
    end
    update_tokens(JSON.parse(token_data))
  end

  def update_tokens(tokens)
    cookies[COOKIES_KEY] = {
      value: tokens["access_token"],
      expires: 7.days.from_now,
      domain: :all
    }
    cookies[COOKIES_REFRESH_KEY] = {
      value: tokens["refresh_token"],
      expires: 7.days.from_now,
      domain: :all
    }
  end

  def delete_cookies
    cookies.delete(COOKIES_KEY, domain: :all)
    cookies.delete(COOKIES_REFRESH_KEY, domain: :all)
  end
end

Now Our application can login by token, and go to all applications as logined user.

Next step - add some components to our application. Lets add toolbar with notifications: * Add to config/secrets.yml cdn url: cdn_url: http://cdn.mysite-staging.com * Add to your layout next code:

<head>
  <script src="<%= Rails.application.secrets.cdn_url %>/orbita_components.js"></script>
  <script src="https://cdn.polyfill.io/v2/polyfill.js?features=Intl.~locale.en"></script>
  <script src="https://cdn.polyfill.io/v2/polyfill.js?features=Intl.~locale.it"></script>
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
  <link href="<%= Rails.application.secrets.cdn_url %>/orbita_components.css" rel="stylesheet">
</header>
<body>
<div id="orbita_toolbar_wrapper">
</div>

<div id="orbita_body">
  Here you can add your code..........
</div>

<div id="orbita_footer">
</div>
  <script type="text/javascript" charset="utf-8">
    var store = orbitaComponents.configureStoreFunction(window.Reducers);
    //You can use store in your own redux application if you use react, or ignore it.
    orbitaComponents.renderToolbar({wrapperId: 'orbita_toolbar_wrapper', store: store, links: [{
      url: 'https://www.mysite.com/inventory/users/sign_in',
      it: 'Inventario',
      en: 'Inventory'
    },{
      url: 'http://www.mysite.com',
      it: 'Magazine',
      en: 'Magazine'
    }]});
    orbitaComponents.renderFooter({wrapperId: 'orbita_footer', store: store});
  </script>
</body>

It’s all, enjoy!

How to Store User Data in Orbita Bucket Service

We can store additional Orbita-specific user data in the Orbita Bucket service. To do this, we will need to send a request to Orbita Oauth which exposes the http://connect.getorbita.io/api/v1/users/1/bucket endpoint. It works for the following methods:

  1. POST - replaces the user data stored in the bucket with the data passed along with the request. It expects a JSON-format body with a data property like {"data": {"foo": "bar"}}. Making a POST request to http://connect.getorbita.io/api/v1/users/1/bucket with the above payload, will create a record with the following details {user_id: 1, data: {foo: "bar"}}.

  2. PUT - merges the data payload with the data already stored for a specific user. If no previous user data exists, a new record will be created for that user. It expects a JSON-format body with a data property like {"data": {"foo": "bar"}}. If a user {user_id: 1, {foo: "bar"}} exists, and we do a PUT request to http://connect.getorbita.io/api/v1/users/1/bucket with payload of {"data": {"bar": "baz"}, the updated record will be {user_id: 1, {foo: "bar", bar: "baz"}} where data property is merged with the data property of the payload.

  3. GET - this gets a user record given a user id. Just send a GET request to http://connect.getorbita.io/api/v1/users/1/bucket.

  4. DELETE - deletes a user record given a user id. Just send a DELETE request to http://connect.getorbita.io/api/v1/users/1/bucket

When making the requests, keep in mind that an access token is required. You will need to get an access token from oauth or oauth-staging. Below are some sample access tokens I use for testing that have expiration times set in the far future.

How to Setup a New Orbita Instance

Configuration

We will need to edit the config.exs file found in the root directory of the orbita repo. A get_configs/1 function is expected for the instance you want to setup. The get_configs/1 function should return a keyword list with certain options. If you want to generate configs for a "foo" instance, we define the following get_configs/1 function:

  def get_configs("foo") do
    [apps: @apps, # a list of apps you want to generate configs for. refer to @apps to see all available options
     ports: %{
       "networking" => "4030",
       "notifications" => "4130",
       "cookietrack" => "9040"}, # a mapping of ports for certain apps
     domain: "foo.com", # the parent domain for the services
     namespace: "foo", # the namespace we use to refer to this instance. typically the same as the argument expected by  the function
     server: "deploy@orbita.lan.coders51.com", # the server we will deploy to
     env: "production"] # either "staging" or "production" environment
  end

Generation of Configurations

From the command line, go to the root of the orbita directory. From there, we run the following:

$ ./gen_configs -n foo

The above command generates capistrano, nginx, supervisor, unicorn, thin, secrets.yml and vm.args configs for each of the apps depending on the templates that exist for them. You can check the templates available for each app under ./templates directory in the orbita repo.

First Deployment of Each Service/App

Before deploying, go to the repo of either Networking, Notifications or Oauth and then run the ff: shell $ bundle exec cap foo_production setup:amqp

The above command creates the rabbitmq vhost for the instance and a corresponding user with admin-like privileges. This is an important step so that the services can actually communicate with each other and is required so that you can deploy multiple orbita instances on one server.

All services except Dashboard and Components/CDN are deployed this way:

Make sure you are in the root directory of the service we want to deploy. shell $ git commit -am "foo_production deploy configs" $ bundle exec cap foo_production deploy:initial # if env is "staging" then it should be foo_staging

Note that we deploy:initial. This is different from the capistrano deploy task we will use in succeeding deploys since it includes some setup tasks such as uploading of nginx and supervisor configs.

For Dashboard, we do the ff:

Before deploying, you will need to add the necessary configs for your deployment to config/environment.js. Commit and push that to the remote host before running the below commands.

$ ./setup_deploy foo_dashboard_production deploy@server.com  # the first arg is the name of the dashboard app which is the namespace + dashboard + env
$ ember deploy foo_dashboard_production

For Components/CDN, we do:

$ git commit -am "foo_production deploy configs"
$ bundle exec cap foo_production copy:initial

Important Notes

Staging Deploy

For every application just run cap staging deploy

Staging Remote URLs

Vagrant Provisioning

  1. Install Ansible and Vagrant
  2. Clone this repository and go to its root directory
  3. ansible-galaxy install -r requirements.yml try sudo if the command fails with permission error.
  4. vagrant up - This will take a long time as it will provision your vagrant machine with all the dependencies of Orbita’s services.
  5. vagrant ssh - Logs into your Orbita dev machine
  6. orbita-components folder is shared between the local machine and the vagrant vm with rsync. The folder is synced only when vagrant vm is initialized. If you want a live rsync (necessary if you develop orbita-components) you need to execute also vagrant rsync-auto
  7. Run ./setup.sh to initialize all the repositories (orbita-networking, orbita-notifications, and so on)
  8. foreman start - Start all services

Provisioning Staging Server

  1. Install Ansible in your dev machine
  2. Set staging host in /etc/ansible/hosts by adding the following to that file: ruby [staging] deploy@orbita.lan.coders51.com
  3. Git clone the https://git.coders51.com/coders51/orbita repository
  4. From the root of that repository, run ansible-playbook provision/staging.yml
  5. If you encounter any bugs, report them by creating an issue at https://git.coders51.com/coders51/orbita/issues

Deploying Orbita Services

Deploying Services Except Dashboard

$ bundle exec cap foo_production deploy

$ bundle exec cap foo_production deploy

Deploying Dashboard

$ ember deploy foo_dashboard_production

$ ember deploy foo_dashboard_production

Dev Machine Setup

  1. Install Ansible and Vagrant
  2. Go this repo’s root directory
  3. ansible-galaxy install -r requirements.yml try sudo if the command file with permission error.
  4. vagrant up - This will take a long time as it will provision your vagrant machine with all the dependencies of Orbita’s services.
  5. vagrant ssh - Logs into your Orbita dev machine
  6. Run ./setup.sh to initialize all the repositories (orbita-networking, orbita-notifications, and so on)
  7. foreman start - Start all services

How to receive orbita notification

All the orbita notifications are sent through the exchange orbita_exchange of type topic. There are two main routing key in orbita one for receive notification and one for send command. To receive notification you should create a new queue with routing key of type #.evt.# see this exampel in ruby using bunny (There are a lot of client in other languages):

connection = Bunny.new(amqp_opts)
connection.start
channel = connection.create_channel
orbita_exchange = channel.topic('orbita_exchange')
queue = channel.queue('my_app_queue', durable: true, auto_delete: false)
queue.bind(exchange, routing_key: '#.evt.#')

The first part of routing key is reserved for future use but the second part, after evt, should be specialized to receive only event from oauth, or from my_app. For example if you want receive all event from connect you should bind your queue in this way:

connection = Bunny.new(amqp_opts)
connection.start
channel = connection.create_channel
orbita_exchange = channel.topic('orbita_exchange')
queue = channel.queue('my_app_queue', durable: true, auto_delete: false)
queue.bind(exchange, routing_key: '#.evt.oauth.#')

How to send orbita command

Sending a command is very similar to receive an event. The application should publish a message on ‘orbita_exchange’ with the appropiate routing key. The routing key is composed by a first part that should be fixed 0.0.cmd. and a second part that identify the type of the message. For example you could send a generic notification tha cna be dispatched via WS and mobile sending a message of this type:

message = {
  "id": "2cb56d59-ed41-4aad-9a7d-765fa89daa4b",
  "type": "GenericNotification",
  "source": "my_app",
  "emitted_at": "2016-09-22T16:24:13Z",
  "payload": {
    "from": 23,
    "to": 23,
    "link": "#",
    "text": "This is a generic notification"
  }
}

with routing key eqaul to 0.0.cmd.notification. Publishing this message on orbita_exchange will bring up a notification on the bar of the user with id 23.

Format of the message

The format of the events and the commands is very similar:

{
  "id": "a75fbf6e-4c36-48fb-9051-33a2f9600e9a",
  "emited_at": "2016-09-22T16:08:15Z",
  "type": "GenericNotification",
  "source": "my_app",
  "payload": ...
}

Warning: sometime some messages can contain other fields but it’s cant be used directly by other aplication because can be removed or changed. In general only this fields should be considered always present and every fileds related to particular message should be put in the payload.

Import users in OAuth

It’s possible import users from other applications in Orbita OAuth. There are a rake task that can be used to import data in OAuth from csv file. The task is bundle exec rake orbita:oauth:import_users. The format of the csv file is similar to table of the user: