Merge branch '1608-api-documentation'
[arvados.git] / apps / workbench / app / controllers / application_controller.rb
index 6535888996304af716e9b12c1ab26b056960b0ff..57ba0cf7a1879413cab628d6e5206fc14d6268c5 100644 (file)
@@ -1,9 +1,10 @@
 class ApplicationController < ActionController::Base
   protect_from_forgery
+  around_filter :thread_clear
   around_filter :thread_with_api_token, :except => [:render_exception, :render_not_found]
   before_filter :find_object_by_uuid, :except => [:index, :render_exception, :render_not_found]
 
-  unless Rails.application.config.consider_all_requests_local
+  begin
     rescue_from Exception,
     :with => :render_exception
     rescue_from ActiveRecord::RecordNotFound,
@@ -12,7 +13,7 @@ class ApplicationController < ActionController::Base
     :with => :render_not_found
     rescue_from ActionController::UnknownController,
     :with => :render_not_found
-    rescue_from ActionController::UnknownAction,
+    rescue_from ::AbstractController::ActionNotFound,
     :with => :render_not_found
   end
 
@@ -32,7 +33,7 @@ class ApplicationController < ActionController::Base
   def render_exception(e)
     logger.error e.inspect
     logger.error e.backtrace.collect { |x| x + "\n" }.join('') if e.backtrace
-    if @object and @object.errors and @object.errors.full_messages
+    if @object.andand.errors.andand.full_messages.andand.any?
       @errors = @object.errors.full_messages
     else
       @errors = [e.inspect]
@@ -51,6 +52,7 @@ class ApplicationController < ActionController::Base
     @objects ||= model_class.all
     respond_to do |f|
       f.json { render json: @objects }
+      f.html { render }
     end
   end
 
@@ -60,30 +62,84 @@ class ApplicationController < ActionController::Base
     end
     respond_to do |f|
       f.json { render json: @object }
-      f.html { render }
+      f.html {
+        if request.method == 'GET'
+          render
+        else
+          redirect_to params[:return_to] || @object
+        end
+      }
+    end
+  end
+
+  def render_content
+    if !@object
+      return render_not_found("object not found")
+    end
+  end
+
+  def new
+    @object = model_class.new
+  end
+
+  def update
+    updates = params[@object.class.to_s.underscore.singularize.to_sym]
+    updates.keys.each do |attr|
+      if @object.send(attr).is_a? Hash and updates[attr].is_a? String
+        updates[attr] = Oj.load updates[attr]
+      end
+    end
+    if @object.update_attributes updates
+      show
+    else
+      self.render_error status: 422
+    end
+  end
+
+  def create
+    @object ||= model_class.new params[model_class.to_s.singularize.to_sym]
+    @object.save!
+    redirect_to(params[:return_to] || @object)
+  end
+
+  def destroy
+    if @object.destroy
+      redirect_to(params[:return_to] || :back)
+    else
+      self.render_error status: 422
     end
   end
 
   def current_user
-    if Thread.current[:orvos_api_token]
-      @current_user ||= User.current
+    if Thread.current[:arvados_api_token]
+      Thread.current[:user] ||= User.current
     else
       logger.error "No API token in Thread"
       return nil
     end
   end
 
-  protected
-    
   def model_class
     controller_name.classify.constantize
   end
 
+  protected
+    
   def find_object_by_uuid
     if params[:id] and params[:id].match /\D/
       params[:uuid] = params.delete :id
     end
-    @object = model_class.where(uuid: params[:uuid]).first
+    if params[:uuid].is_a? String
+      @object = model_class.find(params[:uuid])
+    else
+      @object = model_class.where(uuid: params[:uuid]).first
+    end
+  end
+
+  def thread_clear
+    Thread.current[:arvados_api_token] = nil
+    Thread.current[:user] = nil
+    yield
   end
 
   def thread_with_api_token
@@ -91,11 +147,11 @@ class ApplicationController < ActionController::Base
       try_redirect_to_login = true
       if params[:api_token]
         try_redirect_to_login = false
-        Thread.current[:orvos_api_token] = params[:api_token]
+        Thread.current[:arvados_api_token] = params[:api_token]
         # Before copying the token into session[], do a simple API
         # call to verify its authenticity.
         if verify_api_token
-          session[:orvos_api_token] = params[:api_token]
+          session[:arvados_api_token] = params[:api_token]
           if !request.format.json? and request.method == 'GET'
             # Repeat this request with api_token in the (new) session
             # cookie instead of the query string.  This prevents API
@@ -109,32 +165,39 @@ class ApplicationController < ActionController::Base
           @errors = ['Invalid API token']
           self.render_error status: 401
         end
-      elsif session[:orvos_api_token]
+      elsif session[:arvados_api_token]
         # In this case, the token must have already verified at some
         # point, but it might have been revoked since.  We'll try
         # using it, and catch the exception if it doesn't work.
         try_redirect_to_login = false
-        Thread.current[:orvos_api_token] = session[:orvos_api_token]
+        Thread.current[:arvados_api_token] = session[:arvados_api_token]
         begin
           yield
-        rescue OrvosApiClient::NotLoggedInException
+        rescue ArvadosApiClient::NotLoggedInException
           try_redirect_to_login = true
         end
+      else
+        logger.debug "No token received, session is #{session.inspect}"
       end
       if try_redirect_to_login
         respond_to do |f|
           f.html {
-            redirect_to $orvos_api_client.orvos_login_url(return_to: request.url)
+            if request.method == 'GET'
+              redirect_to $arvados_api_client.arvados_login_url(return_to: request.url)
+            else
+              flash[:error] = "Either you are not logged in, or your session has timed out. I can't automatically log you in and re-attempt this request."
+              redirect_to :back
+            end
           }
           f.json {
-            @errors = ['No API token supplied -- can\'t really do anything.']
+            @errors = ['You do not seem to be logged in. You did not supply an API token with this request, and your session (if any) has timed out.']
             self.render_error status: 422
           }
         end
       end
     ensure
       # Remove token in case this Thread is used for anything else.
-      Thread.current[:orvos_api_token] = nil
+      Thread.current[:arvados_api_token] = nil
     end
   end
 
@@ -142,7 +205,7 @@ class ApplicationController < ActionController::Base
     begin
       Link.where(uuid: 'just-verifying-my-api-token')
       true
-    rescue OrvosApiClient::NotLoggedInException
+    rescue ArvadosApiClient::NotLoggedInException
       false
     end
   end