# Some sensitive files
/config/api.clinicalfuture.com.*
/config/database.yml
+/config/initializers/omniauth.rb
# asset cache
/public/assets/
gem 'acts_as_api'
gem 'passenger', :group => :production
+
+gem 'omniauth', '1.1.1'
+gem 'omniauth-oauth2', '1.1.1'
erubis (2.7.0)
execjs (1.4.0)
multi_json (~> 1.0)
+ faraday (0.8.4)
+ multipart-post (~> 1.1)
fastthread (1.0.7)
+ hashie (1.2.0)
highline (1.6.15)
hike (1.2.1)
+ httpauth (0.2.0)
i18n (0.6.1)
jquery-rails (2.1.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.7.6)
+ jwt (0.1.5)
+ multi_json (>= 1.0)
libv8 (3.11.8.13)
mail (2.3.3)
i18n (>= 0.4.0)
treetop (~> 1.4.8)
mime-types (1.19)
multi_json (1.2.0)
+ multipart-post (1.1.5)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-sftp (2.0.5)
net-ssh (2.6.3)
net-ssh-gateway (1.1.0)
net-ssh (>= 1.99.1)
+ oauth2 (0.8.0)
+ faraday (~> 0.8)
+ httpauth (~> 0.1)
+ jwt (~> 0.1.4)
+ multi_json (~> 1.0)
+ rack (~> 1.2)
+ omniauth (1.1.1)
+ hashie (~> 1.2)
+ rack
+ omniauth-oauth2 (1.1.1)
+ oauth2 (~> 0.8.0)
+ omniauth (~> 1.0)
passenger (3.0.19)
daemon_controller (>= 1.0.0)
fastthread (>= 1.0.1)
coffee-rails (~> 3.1.1)
jquery-rails
json
+ omniauth (= 1.1.1)
+ omniauth-oauth2 (= 1.1.1)
passenger
pg
rails (= 3.1.10)
.contain-align-left {
text-align: left;
}
+
+body {
+ margin: 0;
+}
+body > div {
+ margin: 2px;
+}
+div#footer {
+ font-family: Verdana,Arial,sans-serif;
+ font-size: 12px;
+ margin-top: 24px;
+ border-top: 1px solid #ccc;
+}
+div#footer, div#footer a {
+ color: #777;
+}
+div#header {
+ margin: 0;
+ padding: .5em 1em;
+ background: #000;
+ font-weight: bold;
+ font-size: 18px;
+ font-family: Verdana,Arial,sans-serif;
+ vertical-align: middle;
+ color: #ddd;
+}
+div#header > div {
+ display: inline-block;
+ font-size: 12px;
+ line-height: 18px;
+}
+div#header > .apptitle {
+ font-size: 18px;
+}
+div#header a.logout {
+ color: #fff;
+ font-weight: normal;
+}
+div#header button {
+ font-size: 12px;
+}
+div#header span.beta {
+ opacity: 0.5;
+}
+div#header span.beta > span {
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #fff;
+ font-size: 0.8em;
+}
+img.clinicalfuture-logo {
+ width: 221px;
+ height: 44px;
+}
+#intropage {
+ font-family: Verdana,Arial,sans-serif;
+}
+#errorpage {
+ font-family: Verdana,Arial,sans-serif;
+}
+
+div.full-page-tab-set > ul > li {
+ font-size: 14px;
+}
+.titlebanner p {
+ font-size: 16px;
+}
+p {
+ font-size: 12px;
+}
+.small-text {
+ font-size: 12px;
+}
+.autoui-icon-float-left {
+ float: left;
+ margin-right: .3em;
+}
+.autoui-pad {
+ padding: 0 1em;
+}
+table.datatablesme {
+ border: 0;
+ border-collapse: collapse;
+ width: 100%;
+}
+.loadinggif {
+ background: #fff url(/images/ajax-loader-16-fff-aad.gif) no-repeat;
+}
+.clientprogressgif {
+ /* warning: depends on 24px outer container. */
+ position: absolute;
+ left: 4px;
+ top: 4px;
+ width: 16px;
+ height: 16px;
+}
+.counttable {
+ width: 100%;
+ display: table;
+ border-collapse: collapse;
+ margin-bottom: 0.5em;
+}
+.counttable > div {
+ display: table-row;
+}
+.counttable > div > div {
+ display: table-cell;
+ text-align: center;
+ background: #ccf;
+ padding: 0 2px;
+ font-size: 0.8em;
+}
+.counttable > div > div.counter {
+ font-size: 2em;
+ padding: 4px 2px 0 2px;
+}
+table.admin_table {
+ border-collapse: collapse;
+}
+table.admin_table tbody tr {
+ height: 2.5em;
+}
+table.admin_table th,table.admin_table td {
+ text-align: left;
+ border: 1px solid #bbb;
+ padding: 3px;
+}
+table.admin_table tbody tr:hover {
+ background: #ff8;
+}
+table.admin_table tbody tr:hover td {
+ background: transparent;
+}
+
+div.helptopics {
+ position: fixed;
+}
+div.helptopics ul {
+ padding: 0;
+ margin-left: 1em;
+ list-style-type: none;
+}
+div.helptopics ul li {
+ margin: 0 0 1em 0;
+}
+div.helpcontent li {
+ margin-bottom: .5em;
+}
+
+div.preview {
+ color: red;
+ font-weight: bold;
+ text-align: center;
+}
+
+.sudo-warning {
+ padding: 4px 10px;
+ background: #ffdd00;
+ color: red;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px
+}
+
+div#header a.sudo-logout {
+ color: #000;
+ font-weight: bold;
+}
+
before_filter :find_object_by_uuid, :except => :index
before_filter :authenticate_api_token
+ before_filter :set_remote_ip
+ before_filter :login_required
+
+ before_filter :catch_redirect_hint
+
+ def catch_redirect_hint
+ if !current_user
+ if params.has_key?('redirect_to') then
+ session[:redirect_to] = params[:redirect_to]
+ end
+ end
+ end
+
+ # Authentication
+ def login_required
+ if !current_user
+ respond_to do |format|
+ format.html {
+ redirect_to '/auth/joshid'
+ }
+ format.json {
+ render :json => { 'error' => 'Not logged in' }.to_json
+ }
+ end
+ end
+ end
+
+ def current_user
+ return nil unless session[:user_id]
+ @current_user ||= User.find(session[:user_id]) rescue nil
+ end
+ # /Authentication
+
+ before_filter :set_remote_ip
+ before_filter :login_required
+
+ # Authentication
+ def login_required
+ if !current_user
+ respond_to do |format|
+ format.html {
+ redirect_to '/auth/joshid'
+ }
+ format.json {
+ render :json => { 'error' => 'Not logged in' }.to_json
+ }
+ end
+ end
+ end
+
+ def current_user
+ return nil unless session[:user_id]
+ @current_user ||= User.find(session[:user_id]) rescue nil
+ end
+ # /Authentication
+
+ before_filter :set_remote_ip
+ before_filter :login_required
+
+ # Authentication
+ def login_required
+ if !current_user
+ respond_to do |format|
+ format.html {
+ redirect_to '/auth/joshid'
+ }
+ format.json {
+ render :json => { 'error' => 'Not logged in' }.to_json
+ }
+ end
+ end
+ end
+
+ def current_user
+ return nil unless session[:user_id]
+ @current_user ||= User.find(session[:user_id]) rescue nil
+ end
+ # /Authentication
+
unless Rails.application.config.consider_all_requests_local
rescue_from Exception,
:with => :render_error
render_error(Exception.new("Invalid API token"))
end
end
+
+private
+ def set_remote_ip
+ # Caveat: this is highly dependent on the proxy setup. YMMV.
+ if request.headers.has_key?('HTTP_X_REAL_IP') then
+ # We're behind a reverse proxy
+ @remote_ip = request.headers['HTTP_X_REAL_IP']
+ else
+ # Hopefully, we are not!
+ @remote_ip = request.env['REMOTE_ADDR']
+ end
+ end
+
end
class CollectionsController < ApplicationController
+ skip_before_filter :authenticate_api_token
def index
@objects = model_class.order("created_at desc")
end
class NodesController < ApplicationController
+ skip_before_filter :authenticate_api_token
def index
@objects = model_class.order("created_at desc")
end
class PipelineInvocationsController < ApplicationController
+ skip_before_filter :authenticate_api_token
def index
@objects = model_class.order("created_at desc")
end
--- /dev/null
+class StaticController < ApplicationController
+
+ skip_before_filter :uncamelcase_params_hash_keys
+ skip_before_filter :find_object_by_uuid
+ skip_before_filter :authenticate_api_token
+ skip_before_filter :login_required, :only => :home
+
+ def home
+ render 'intro'
+ end
+
+end
--- /dev/null
+class UserSessionsController < ApplicationController
+ before_filter :login_required, :only => [ :destroy ]
+
+ skip_before_filter :uncamelcase_params_hash_keys
+ skip_before_filter :find_object_by_uuid
+ skip_before_filter :authenticate_api_token
+
+ respond_to :html
+
+ # omniauth callback method
+ def create
+ omniauth = env['omniauth.auth']
+ #logger.debug "+++ #{omniauth}"
+
+ identity_url_ok = (omniauth['info']['identity_url'].length > 0) rescue false
+ unless identity_url_ok
+ # Whoa. This should never happen.
+
+ @title = "UserSessionsController.create: omniauth object missing/invalid"
+ @body = "omniauth.pretty_inspect():\n\n#{omniauth.pretty_inspect()}"
+
+ view_context.fatal_error(@title,@body)
+ return redirect_to openid_login_error_url
+ end
+
+ user = User.find_by_identity_url(omniauth['info']['identity_url'])
+ if not user
+ # New user registration
+ user = User.create!(:email => omniauth['info']['email'],
+ :first_name => omniauth['info']['first_name'],
+ :last_name => omniauth['info']['last_name'],
+ :identity_url => omniauth['info']['identity_url'])
+ else
+ user.email = omniauth['info']['email']
+ user.first_name = omniauth['info']['first_name']
+ user.last_name = omniauth['info']['last_name']
+ user.save
+ end
+
+ omniauth.delete('extra')
+
+ session[:user_id] = user.id
+
+ @redirect_to = root_path
+ if session.has_key?('redirect_to') then
+ @redirect_to = session[:redirect_to]
+ session.delete(:redirect_to)
+ end
+ redirect_to @redirect_to
+ end
+
+ # Omniauth failure callback
+ def failure
+ flash[:notice] = params[:message]
+ end
+
+ # logout - Clear our rack session BUT essentially redirect to the provider
+ # to clean up the Devise session from there too !
+ def logout
+ session[:user_id] = nil
+
+ flash[:notice] = 'You have logged off'
+ redirect_to "#{CUSTOM_PROVIDER_URL}/users/sign_out?redirect_uri=#{root_url}"
+ end
+
+ # login - Just bounce to /auth/joshid. The only purpose of this function is
+ # to save the redirect_to parameter (if it exists; see the application
+ # controller). /auth/joshid bypasses the application controller.
+ def login
+ redirect_to "/auth/joshid"
+ end
+end
module ApplicationHelper
+
+ def current_user
+ controller.current_user
+ end
+
end
--- /dev/null
+class User < ActiveRecord::Base
+
+ def full_name
+ "#{first_name} #{last_name}"
+ end
+
+end
<%= csrf_meta_tags %>
</head>
<body>
+<div id="header">
+ <div class="apptitle">ORVOS <span class="beta"><span>BETA</span></span></div>
+ <div style="float:right">
+ <% if current_user %>
+ <%= current_user.full_name %>
+ <% if current_user.is_admin %>
+ •
+ <a class="logout" href="/admin/users">Admin</a>
+ <% end %>
+ •
+ <a class="logout" href="/logout">Log out</a>
+ <% else %>
+ <a class="logout" href="/auth/joshid">Log in</a>
+ <% end %>
+
+ <% if current_user and session[:real_uid] and session[:switch_back_to] and User.find(session[:real_uid].to_i).verify_userswitch_cookie(session[:switch_back_to]) %>
+ •
+ <span class="sudo-warning">Logged in as <b><%= current_user.full_name %></b>. <%= link_to "Back to #{User.find(session[:real_uid]).full_name}", switch_to_user_path(session[:real_uid]), :method => :post, :class => 'sudo-logout' %></span>
+ <% end %>
+ </div>
+</div>
+
<%= yield %>
+<div style="clear:both"></div>
+
+<% if current_user or session['invite_code'] %>
+<div id="footer">
+ <div style="float:right">Questions → <a href="mailto:orvos@clinicalfuture.com">orvos@clinicalfuture.com</a></div>
+ <div style="clear:both"></div>
+</div>
+<% end %>
+
</body>
</html>
--- /dev/null
+<% content_for :js do %>
+$(function(){
+ $('button.login').button().click(function(){window.location=$(this).attr('href')});
+});
+<% end %>
+<div id="intropage">
+ <img class="clinicalfuture-logo" src="/images/logo.png" style="display:block; margin:2em auto"/>
+ <div style="width:30em; margin:2em auto 0 auto">
+ <h1>Welcome</h1>
+ <h4>Clinical Future ORVOS</h4>
+
+ <% if !current_user and session['invite_code'] %>
+
+ <p>Clinical Future Orvos lets you manage and process human genomes and exomes. You can start using the private beta
+ now with your Google account.</p>
+ <p style="float:right;margin-top:1em">
+ <button class="login" href="/auth/joshid">Log in and get started</button>
+ </p>
+
+ <% else %>
+
+ <p>Clinical Future ORVOS is transforming how researchers and
+ clinical geneticists use whole genome sequences. </p>
+ <p>If you’re interested in learning more, we’d love to hear
+ from you —
+ contact <a href="mailto:orvos@clinicalfuture.com">orvos@clinicalfuture.com</a>.</p>
+
+ <% if !current_user %>
+ <p style="float:right;margin-top:1em">
+ <a href="/auth/joshid">Log in here.</a>
+ </p>
+ <% end %>
+
+ <% end %>
+
+ <div style="clear:both;height:8em"></div>
+ </div>
+</div>
--- /dev/null
+<h1>Fail</h1>
+
+<%= notice %>
+
+<br/>
+<a href="/auth/joshid">Retry Login</a>
# Load the rails application
require File.expand_path('../application', __FILE__)
+require 'josh_id'
# Initialize the rails application
Server::Application.initialize!
end
end
+ # omniauth
+ match '/auth/:provider/callback', :to => 'user_sessions#create'
+ match '/auth/failure', :to => 'user_sessions#failure'
+
+ # Custom logout
+ match '/login', :to => 'user_sessions#login'
+ match '/logout', :to => 'user_sessions#logout'
+
# Send unroutable requests to an arbitrary controller
# (ends up at ApplicationController#render_not_found)
match '*a', :to => 'orvos/v1/metadata#render_not_found'
+
+ root :to => 'static#home'
end
--- /dev/null
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users do |t|
+ t.string :uuid
+ t.string :created_by_client
+ t.string :created_by_user
+ t.datetime :created_at
+ t.string :modified_by_client
+ t.string :modified_by_user
+ t.datetime :modified_at
+ t.string :email
+ t.string :first_name
+ t.string :last_name
+ t.string :identity_url
+ t.boolean :is_admin
+ t.text :prefs
+
+ t.timestamps
+ end
+ end
+end
add_index "specimens", ["uuid"], :name => "index_specimens_on_uuid", :unique => true
+ create_table "users", :force => true do |t|
+ t.string "uuid"
+ t.string "created_by_client"
+ t.string "created_by_user"
+ t.datetime "created_at"
+ t.string "modified_by_client"
+ t.string "modified_by_user"
+ t.datetime "modified_at"
+ t.string "email"
+ t.string "first_name"
+ t.string "last_name"
+ t.string "identity_url"
+ t.boolean "is_admin"
+ t.text "prefs"
+ t.datetime "updated_at"
+ end
+
end
--- /dev/null
+require 'omniauth-oauth2'
+module OmniAuth
+ module Strategies
+ class JoshId < OmniAuth::Strategies::OAuth2
+
+ CUSTOM_PROVIDER_URL = 'http://auth.clinicalfuture.com'
+ #CUSTOM_PROVIDER_URL = 'http://auth.clinicalfuture.com:3001'
+
+ option :client_options, {
+ :site => CUSTOM_PROVIDER_URL,
+ :authorize_url => "#{CUSTOM_PROVIDER_URL}/auth/josh_id/authorize",
+ :access_token_url => "#{CUSTOM_PROVIDER_URL}/auth/josh_id/access_token"
+ }
+
+ uid { raw_info['id'] }
+
+ info do
+ {
+ :first_name => raw_info['info']['first_name'],
+ :last_name => raw_info['info']['last_name'],
+ :email => raw_info['info']['email'],
+ :identity_url => raw_info['info']['identity_url'],
+ }
+ end
+
+ extra do
+ {
+ 'raw_info' => raw_info
+ }
+ end
+
+ def raw_info
+ @raw_info ||= access_token.get("/auth/josh_id/user.json?oauth_token=#{access_token.token}").parsed
+ end
+ end
+ end
+end
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>Ruby on Rails: Welcome aboard</title>
- <style type="text/css" media="screen">
- body {
- margin: 0;
- margin-bottom: 25px;
- padding: 0;
- background-color: #f0f0f0;
- font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
- font-size: 13px;
- color: #333;
- }
-
- h1 {
- font-size: 28px;
- color: #000;
- }
-
- a {color: #03c}
- a:hover {
- background-color: #03c;
- color: white;
- text-decoration: none;
- }
-
-
- #page {
- background-color: #f0f0f0;
- width: 750px;
- margin: 0;
- margin-left: auto;
- margin-right: auto;
- }
-
- #content {
- float: left;
- background-color: white;
- border: 3px solid #aaa;
- border-top: none;
- padding: 25px;
- width: 500px;
- }
-
- #sidebar {
- float: right;
- width: 175px;
- }
-
- #footer {
- clear: both;
- }
-
- #header, #about, #getting-started {
- padding-left: 75px;
- padding-right: 30px;
- }
-
-
- #header {
- background-image: url("/assets/rails.png");
- background-repeat: no-repeat;
- background-position: top left;
- height: 64px;
- }
- #header h1, #header h2 {margin: 0}
- #header h2 {
- color: #888;
- font-weight: normal;
- font-size: 16px;
- }
-
-
- #about h3 {
- margin: 0;
- margin-bottom: 10px;
- font-size: 14px;
- }
-
- #about-content {
- background-color: #ffd;
- border: 1px solid #fc0;
- margin-left: -55px;
- margin-right: -10px;
- }
- #about-content table {
- margin-top: 10px;
- margin-bottom: 10px;
- font-size: 11px;
- border-collapse: collapse;
- }
- #about-content td {
- padding: 10px;
- padding-top: 3px;
- padding-bottom: 3px;
- }
- #about-content td.name {color: #555}
- #about-content td.value {color: #000}
-
- #about-content ul {
- padding: 0;
- list-style-type: none;
- }
-
- #about-content.failure {
- background-color: #fcc;
- border: 1px solid #f00;
- }
- #about-content.failure p {
- margin: 0;
- padding: 10px;
- }
-
-
- #getting-started {
- border-top: 1px solid #ccc;
- margin-top: 25px;
- padding-top: 15px;
- }
- #getting-started h1 {
- margin: 0;
- font-size: 20px;
- }
- #getting-started h2 {
- margin: 0;
- font-size: 14px;
- font-weight: normal;
- color: #333;
- margin-bottom: 25px;
- }
- #getting-started ol {
- margin-left: 0;
- padding-left: 0;
- }
- #getting-started li {
- font-size: 18px;
- color: #888;
- margin-bottom: 25px;
- }
- #getting-started li h2 {
- margin: 0;
- font-weight: normal;
- font-size: 18px;
- color: #333;
- }
- #getting-started li p {
- color: #555;
- font-size: 13px;
- }
-
-
- #sidebar ul {
- margin-left: 0;
- padding-left: 0;
- }
- #sidebar ul h3 {
- margin-top: 25px;
- font-size: 16px;
- padding-bottom: 10px;
- border-bottom: 1px solid #ccc;
- }
- #sidebar li {
- list-style-type: none;
- }
- #sidebar ul.links li {
- margin-bottom: 5px;
- }
-
- .filename {
- font-style: italic;
- }
- </style>
- <script type="text/javascript">
- function about() {
- info = document.getElementById('about-content');
- if (window.XMLHttpRequest)
- { xhr = new XMLHttpRequest(); }
- else
- { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
- xhr.open("GET","rails/info/properties",false);
- xhr.send("");
- info.innerHTML = xhr.responseText;
- info.style.display = 'block'
- }
- </script>
- </head>
- <body>
- <div id="page">
- <div id="sidebar">
- <ul id="sidebar-items">
- <li>
- <h3>Browse the documentation</h3>
- <ul class="links">
- <li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
- <li><a href="http://api.rubyonrails.org/">Rails API</a></li>
- <li><a href="http://www.ruby-doc.org/core/">Ruby core</a></li>
- <li><a href="http://www.ruby-doc.org/stdlib/">Ruby standard library</a></li>
- </ul>
- </li>
- </ul>
- </div>
-
- <div id="content">
- <div id="header">
- <h1>Welcome aboard</h1>
- <h2>You’re riding Ruby on Rails!</h2>
- </div>
-
- <div id="about">
- <h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3>
- <div id="about-content" style="display: none"></div>
- </div>
-
- <div id="getting-started">
- <h1>Getting started</h1>
- <h2>Here’s how to get rolling:</h2>
-
- <ol>
- <li>
- <h2>Use <code>rails generate</code> to create your models and controllers</h2>
- <p>To see all available options, run it without parameters.</p>
- </li>
-
- <li>
- <h2>Set up a default route and remove <span class="filename">public/index.html</span></h2>
- <p>Routes are set up in <span class="filename">config/routes.rb</span>.</p>
- </li>
-
- <li>
- <h2>Create your database</h2>
- <p>Run <code>rake db:create</code> to create your database. If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p>
- </li>
- </ol>
- </div>
- </div>
-
- <div id="footer"> </div>
- </div>
- </body>
-</html>
--- /dev/null
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
+
+one:
+ uuid: MyString
+ created_by_client: MyString
+ created_by_user: MyString
+ created_at: 2013-01-21 21:00:42
+ modified_by_client: MyString
+ modified_by_user: MyString
+ modified_at: 2013-01-21 21:00:42
+ email: MyString
+ first_name: MyString
+ last_name: MyString
+ identity_url: MyString
+ is_admin: false
+ prefs: MyText
+
+two:
+ uuid: MyString
+ created_by_client: MyString
+ created_by_user: MyString
+ created_at: 2013-01-21 21:00:42
+ modified_by_client: MyString
+ modified_by_user: MyString
+ modified_at: 2013-01-21 21:00:42
+ email: MyString
+ first_name: MyString
+ last_name: MyString
+ identity_url: MyString
+ is_admin: false
+ prefs: MyText
--- /dev/null
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end