--- /dev/null
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
--- /dev/null
+// Place all the styles related to the ApiClientAuthorizations controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
--- /dev/null
+class ApiClientAuthorizationsController < ApplicationController
+end
--- /dev/null
+module ApiClientAuthorizationsHelper
+end
--- /dev/null
+class ApiClientAuthorization < ArvadosBase
+ def attribute_editable?(attr)
+ ['expires_at', 'default_owner'].index attr
+ end
+end
%w(uuid owner created_at
modified_at modified_by_user modified_by_client
).each do |attr|
- self.send(attr + '=', resp[attr.to_sym])
+ if self.respond_to? "#{attr}=".to_sym
+ self.send(attr + '=', resp[attr.to_sym])
+ end
end
self
[false, 'Keys', authorized_keys_path],
[false, 'VMs', virtual_machines_path],
[false, 'Repos', repositories_path],
+ [false, 'Tokens', api_client_authorizations_path],
[false, 'Jobs', jobs_path]
].each do |admin_only, name, path| %>
<% if !admin_only or (current_user and current_user.is_admin) %>
ArvadosWorkbench::Application.routes.draw do
+ resources :api_client_authorizations
resources :repositories
resources :virtual_machines
resources :authorized_keys
--- /dev/null
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
+
+# This model initially had no columns defined. If you add columns to the
+# model remove the '{}' from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+one: {}
+# column: value
+#
+two: {}
+# column: value
--- /dev/null
+require 'test_helper'
+
+class ApiClientAuthorizationsControllerTest < ActionController::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
--- /dev/null
+require 'test_helper'
+
+class ApiClientAuthorizationTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
--- /dev/null
+require 'test_helper'
+
+class ApiClientAuthorizationsHelperTest < ActionView::TestCase
+end
+++ /dev/null
-class ApiClientAuthorizationsController < ApplicationController
- def index
- if Thread.current[:api_client_trusted]
- @objects = model_class.
- joins(:user, :api_client).
- where('user_id=?', current_user.id)
- else
- @objects = model_class.where('1=0')
- end
- end
-end
if supplied_token
api_client_auth = ApiClientAuthorization.
includes(:api_client, :user).
- where('api_token=?', supplied_token).
+ where('api_token=? and (expires_at is null or expires_at > now())', supplied_token).
first
if api_client_auth
session[:user_id] = api_client_auth.user.id
find session[:api_client_authorization_id]
end
end
- Thread.current[:api_client_trusted] = session[:api_client_trusted]
Thread.current[:api_client_ip_address] = remote_ip
Thread.current[:api_client_authorization] = api_client_auth
Thread.current[:api_client_uuid] = api_client && api_client.uuid
Thread.current[:api_client] = api_client
Thread.current[:user] = user
+ if api_client_auth
+ api_client_auth.last_used_at = Time.now
+ api_client_auth.last_used_by_ip_address = remote_ip
+ api_client_auth.save validate: false
+ end
yield
ensure
- Thread.current[:api_client_trusted] = nil
Thread.current[:api_client_ip_address] = nil
Thread.current[:api_client_authorization] = nil
Thread.current[:api_client_uuid] = nil
--- /dev/null
+class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
+ before_filter :current_api_client_is_trusted
+
+ protected
+
+ def find_objects_for_index
+ # Here we are deliberately less helpful about searching for client
+ # authorizations. Rather than use the generic index/where/order
+ # featuers, we look up tokens belonging to the current user and
+ # filter by exact match on api_token (which we expect in the form
+ # of a where[uuid] parameter to make things easier for API client
+ # libraries).
+ @objects = model_class.
+ includes(:user, :api_client).
+ where('user_id=? and (? or api_token=?)', current_user.id, !@where['uuid'], @where['uuid']).
+ order('created_at desc')
+ end
+
+ def find_object_by_uuid
+ # Again, to make things easier for the client and our own routing,
+ # here we look for the api_token key in a "uuid" (POST) or "id"
+ # (GET) parameter.
+ @object = model_class.where('api_token=?', params[:uuid] || params[:id]).first
+ end
+
+ def current_api_client_is_trusted
+ # Most API clients cannot manipulate tokens. This entire section
+ # of the API is just hidden by default. In the case of a trusted
+ # installation of Workbench, the site administrator will set the
+ # api_client.is_trusted flag so users can use Workbench to
+ # generate API tokens for other applications.
+ unless Thread.current[:api_client].andand.is_trusted
+ render :json => { errors: ['Forbidden: this API client cannot manipulate other clients\' access tokens.'] }.to_json, status: 403
+ end
+ end
+end
--- /dev/null
+tom@shuttle.4812:1371491492
\ No newline at end of file
--- /dev/null
+class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
+ before_filter :current_api_client_is_trusted
+
+ protected
+
+ def find_objects_for_index
+ # Here we are deliberately less helpful about searching for client
+ # authorizations. Rather than use the generic index/where/order
+ # featuers, we look up tokens belonging to the current user and
+ # filter by exact match on api_token (which we expect in the form
+ # of a where[uuid] parameter to make things easier for API client
+ # libraries).
+ @objects = model_class.
+ includes(:user, :api_client).
+ where('user_id=? and (? or api_token=?)', current_user.id, !@where['uuid'], @where['uuid']).
+ order('created_at desc')
+ end
+
+ def find_object_by_uuid
+ # Again, to make things easier for the client and our own routing,
+ # here we look for the api_token key in a "uuid" (POST) or "id"
+ # (GET) parameter.
+ @object = model_class.where('api_token=?', params[:uuid] || params[:id]).first
+ end
+
+ def current_api_client_is_trusted
+ unless Thread.current[:api_client].andand.is_trusted
+ render :json => { errors: ['Forbidden: this API client cannot manipulate other clients\' access tokens.'] }.to_json, status: 403
+ end
+ end
+end
api_accessible :superuser, :extend => :common do |t|
t.add :name
t.add :url_prefix
+ t.add :is_trusted
end
end
-class ApiClientAuthorization < ActiveRecord::Base
+class ApiClientAuthorization < ArvadosModel
+ include KindAndEtag
+ include CommonApiTemplate
+
belongs_to :api_client
belongs_to :user
after_initialize :assign_random_api_token
+ api_accessible :superuser, :extend => :common do |t|
+ t.add :owner
+ t.add :user_id
+ t.add :api_client_id
+ t.add :api_token
+ t.add :created_by_ip_address
+ t.add :default_owner
+ t.add :expires_at
+ t.add :last_used_at
+ t.add :last_used_by_ip_address
+ end
+
def assign_random_api_token
self.api_token ||= rand(2**256).to_s(36)
end
+
+ def owner
+ self.user.andand.uuid
+ end
+ def owner_was
+ self.user_id_changed? ? User.find(self.user_id_was).andand.uuid : self.user.andand.uuid
+ end
+ def owner_changed?
+ self.user_id_changed?
+ end
+
+ def uuid
+ self.api_token
+ end
+ def uuid=(x) end
+ def uuid_was
+ self.api_token_was
+ end
+ def uuid_changed?
+ self.api_token_changed?
+ end
+
+ def modified_by_client
+ nil
+ end
+ def modified_by_client=(x) end
+
+ def modified_by_user
+ nil
+ end
+ def modified_by_user=(x) end
+
+ def modified_at
+ nil
+ end
+ def modified_at=(x) end
end
resources :groups
resources :logs
resources :users
+ resources :api_clients
+ resources :api_client_authorizations
resources :jobs
resources :job_tasks
resources :keep_disks
--- /dev/null
+class AddIsTrustedToApiClients < ActiveRecord::Migration
+ def change
+ add_column :api_clients, :is_trusted, :boolean, :default => false
+ end
+end
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130612042554) do
+ActiveRecord::Schema.define(:version => 20130617150007) do
create_table "api_client_authorizations", :force => true do |t|
t.string "api_token", :null => false
t.string "url_prefix"
t.datetime "created_at"
t.datetime "updated_at"
+ t.boolean "is_trusted", :default => false
end
add_index "api_clients", ["created_at"], :name => "index_api_clients_on_created_at"
Thread.current[:api_client_ip_address]
end
- # Is the current client permitted to perform ALL actions on behalf
- # of the authenticated user?
- def current_api_client_trusted
- Thread.current[:api_client_trusted]
- end
-
def system_user_uuid
[Server::Application.config.uuid_prefix,
User.uuid_prefix,