generate discovery document at /orvos/v1/rest. refs #1406
authorTom Clegg <tom@clinicalfuture.com>
Tue, 19 Mar 2013 08:06:30 +0000 (01:06 -0700)
committerTom Clegg <tom@clinicalfuture.com>
Tue, 19 Mar 2013 08:06:30 +0000 (01:06 -0700)
app/controllers/application_controller.rb
app/controllers/orvos/v1/schema_controller.rb
config/routes.rb

index d8fdbbca61d5476051d8ebaad812345530efe0f1..3d96706d3b16d9737e7e3e6e8eff3fb36028ca73 100644 (file)
@@ -159,10 +159,11 @@ class ApplicationController < ActionController::Base
       user = nil
       api_client = nil
       api_client_auth = nil
-      if params[:api_token]
+      supplied_token = params[:api_token] || params[:oauth_token]
+      if supplied_token
         api_client_auth = ApiClientAuthorization.
           includes(:api_client, :user).
-          where('api_token=?', params[:api_token]).
+          where('api_token=?', supplied_token).
           first
         if api_client_auth
           session[:user_id] = api_client_auth.user.id
index 8530bf45f85507aeb42ec828bbb0df36d8ec5338..060665e090a5ffdd71290f4d3efeaecebd973bee 100644 (file)
 class Orvos::V1::SchemaController < ApplicationController
   skip_before_filter :find_object_by_uuid
+  skip_before_filter :login_required
+
   def show
-    Rails.application.eager_load!
-    classes = {}
-    ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
-      classes[k] = k.columns.collect do |col|
-        if k.serialized_attributes.has_key? col.name
-          { name: col.name,
-            type: k.serialized_attributes[col.name].object_class.to_s }
-        else
-          { name: col.name,
-            type: col.type }
+    classes = Rails.cache.fetch 'discovery_rest_description' do
+      Rails.application.eager_load!
+      classes = {}
+      ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
+        classes[k] = k.columns.collect do |col|
+          if k.serialized_attributes.has_key? col.name
+            { name: col.name,
+              type: k.serialized_attributes[col.name].object_class.to_s }
+          else
+            { name: col.name,
+              type: col.type }
+          end
         end
       end
+      classes
     end
     render json: classes
   end
+
+  def discovery_rest_description
+    discovery = Rails.cache.fetch 'discovery_rest_description' do
+      Rails.application.eager_load!
+      discovery = {
+        kind: "discovery#restDescription",
+        discoveryVersion: "v1",
+        id: "orvos:v1",
+        name: "orvos",
+        version: "v1",
+        revision: "20130226",
+        title: "Orvos API",
+        description: "The API to interact with Orvos.",
+        documentationLink: "https://redmine.clinicalfuture.com/projects/orvos/",
+        protocol: "rest",
+        baseUrl: root_url + "/orvos/v1/",
+        basePath: "/orvos/v1/",
+        rootUrl: root_url,
+        servicePath: "orvos/v1/",
+        batchPath: "batch",
+        parameters: {
+          alt: {
+            type: "string",
+            description: "Data format for the response.",
+            default: "json",
+            enum: [
+                   "json"
+                  ],
+            enumDescriptions: [
+                               "Responses with Content-Type of application/json"
+                              ],
+            location: "query"
+          },
+          fields: {
+            type: "string",
+            description: "Selector specifying which fields to include in a partial response.",
+            location: "query"
+          },
+          key: {
+            type: "string",
+            description: "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
+            location: "query"
+          },
+          oauth_token: {
+            type: "string",
+            description: "OAuth 2.0 token for the current user.",
+            location: "query"
+          }
+        },
+        auth: {
+          oauth2: {
+            scopes: {
+              "https://api.clinicalfuture.com/auth/orvos" => {
+                description: "View and manage objects"
+              },
+              "https://api.clinicalfuture.com/auth/orvos.readonly" => {
+                description: "View objects"
+              }
+            }
+          }
+        },
+        schemas: {},
+        resources: {}
+      }
+      
+      ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
+        object_properties = {}
+        k.columns.
+          select { |col| col.name != 'id' }.
+          collect do |col|
+          if k.serialized_attributes.has_key? col.name
+            object_properties[col.name] = {
+              type: k.serialized_attributes[col.name].object_class.to_s
+            }
+          else
+            object_properties[col.name] = {
+              type: col.type
+            }
+          end
+        end
+        discovery[:schemas][k.to_s + 'List'] = {
+          id: k.to_s,
+          description: k.to_s,
+          type: "object",
+          properties: {
+            kind: {
+              type: "string",
+              description: "Object type. Always orvos##{k.to_s.camelcase(:lower)}List.",
+              default: "orvos##{k.to_s.camelcase(:lower)}List"
+            },
+            etag: {
+              type: "string",
+              description: "List version."
+            },
+            items: {
+              type: "array",
+              description: "The list of #{k.to_s.pluralize}."
+            },
+            next_link: {
+              type: "string",
+              description: "A link to the next page of #{k.to_s.pluralize}."
+            },
+            next_page_token: {
+              type: "string",
+              description: "The page token for the next page of #{k.to_s.pluralize}."
+            },
+            selfLink: {
+              type: "string",
+              description: "A link back to this list."
+            }
+          }
+        }
+        discovery[:schemas][k.to_s] = {
+          id: k.to_s,
+          description: k.to_s,
+          type: "object",
+          properties: {
+            uuid: {
+              type: "string",
+              description: "Object ID."
+            },
+            etag: {
+              type: "string",
+              description: "Object version."
+            }
+          }.merge(object_properties)
+        }
+        discovery[:resources][k.to_s.underscore.pluralize] = {
+          methods: {
+            get: {
+              id: "orvos.#{k.to_s.underscore.pluralize}.get",
+              path: "#{k.to_s.underscore.pluralize}/{uuid}",
+              httpMethod: "GET",
+              description: "Gets a #{k.to_s}'s metadata by ID.",
+              parameters: {
+                uuid: {
+                  type: "string",
+                  description: "The ID for the #{k.to_s} in question.",
+                  required: true,
+                  location: "path"
+                }
+              },
+              parameterOrder: [
+                               "uuid"
+                              ],
+              response: {
+                "$ref" => k.to_s
+              },
+              scopes: [
+                       "https://api.clinicalfuture.com/auth/orvos",
+                       "https://api.clinicalfuture.com/auth/orvos.readonly"
+                      ]
+            },
+            list: {
+              id: "orvos.#{k.to_s.underscore.pluralize}.list",
+              path: k.to_s.underscore.pluralize,
+              httpMethod: "GET",
+              description: "List #{k.to_s.underscore.pluralize}.",
+              parameters: {
+                limit: {
+                  type: "integer",
+                  description: "Maximum number of #{k.to_s.underscore.pluralize} to return.",
+                  default: "100",
+                  format: "int32",
+                  minimum: "0",
+                  location: "query"
+                },
+                pageToken: {
+                  type: "string",
+                  description: "Page token.",
+                  location: "query"
+                },
+                q: {
+                  type: "string",
+                  description: "Query string for searching #{k.to_s.underscore.pluralize}.",
+                  location: "query"
+                }
+              },
+              response: {
+                "$ref" => "#{k.to_s.pluralize}List"
+              },
+              scopes: [
+                       "https://api.clinicalfuture.com/auth/orvos",
+                       "https://api.clinicalfuture.com/auth/orvos.readonly"
+                      ]
+            }
+          }
+        }
+      end
+      discovery
+    end
+    render json: discovery
+  end
 end
index 2b254aceb8f4b35680de8e27d155ac91af8fa050..c55c518036383a62078f6a5d91f062a0d4a57c2e 100644 (file)
@@ -72,6 +72,7 @@ Server::Application.routes.draw do
   namespace :orvos do
     namespace :v1 do
       match '/schema' => 'schema#show'
+      match '/rest' => 'schema#discovery_rest_description'
       match '/nodes/:uuid/ping' => 'nodes#ping', :as => :ping_node
       match '/links/from/:tail_uuid' => 'links#index', :as => :orvos_v1_links_from
       match '/users/current' => 'users#current'