3112: report issue works for no user and inactive user cases.
[arvados.git] / apps / workbench / app / models / arvados_base.rb
index 47a9d6d02eed085f134f7ec31fd7b4fc575d55d1..1dac43fa61a7ffbd2c100b3f932b4568f174ee73 100644 (file)
@@ -1,6 +1,7 @@
 class ArvadosBase < ActiveRecord::Base
   self.abstract_class = true
   attr_accessor :attribute_sortkey
+  attr_accessor :create_params
 
   def self.arvados_api_client
     ArvadosApiClient.new_or_current
@@ -29,33 +30,33 @@ class ArvadosBase < ActiveRecord::Base
       end
   end
 
-  def initialize raw_params={}
-    begin
-      super self.class.permit_attribute_params(raw_params)
-    rescue Exception => e
-      logger.debug raw_params
-      logger.debug self.class.permit_attribute_params(raw_params).inspect
-      logger.debug self.class.attribute_info.inspect
-      raise e
-    end
+  def initialize raw_params={}, create_params={}
+    super self.class.permit_attribute_params(raw_params)
+    @create_params = create_params
     @attribute_sortkey ||= {
       'id' => nil,
-      'uuid' => '000',
-      'owner_uuid' => '001',
-      'created_at' => '002',
-      'modified_at' => '003',
-      'modified_by_user_uuid' => '004',
-      'modified_by_client_uuid' => '005',
-      'name' => '050',
-      'tail_uuid' => '100',
-      'head_uuid' => '101',
-      'info' => 'zzz-000',
-      'updated_at' => 'zzz-999'
+      'name' => '000',
+      'owner_uuid' => '002',
+      'event_type' => '100',
+      'link_class' => '100',
+      'group_class' => '100',
+      'tail_uuid' => '101',
+      'head_uuid' => '102',
+      'object_uuid' => '102',
+      'summary' => '104',
+      'description' => '104',
+      'properties' => '150',
+      'info' => '150',
+      'created_at' => '200',
+      'modified_at' => '201',
+      'modified_by_user_uuid' => '202',
+      'modified_by_client_uuid' => '203',
+      'uuid' => '999',
     }
   end
 
   def self.columns
-    return @columns unless @columns.nil?
+    return @columns if @columns.andand.any?
     @columns = []
     @attribute_info ||= {}
     schema = arvados_api_client.discovery[:schemas][self.to_s.to_sym]
@@ -93,6 +94,11 @@ class ArvadosBase < ActiveRecord::Base
       raise 'argument to find() must be a uuid string. Acceptable formats: warehouse locator or string with format xxxxx-xxxxx-xxxxxxxxxxxxxxx'
     end
 
+    if self == ArvadosBase
+      # Determine type from uuid and defer to the appropriate subclass.
+      return resource_class_for_uuid(uuid).find(uuid, opts)
+    end
+
     # Only do one lookup on the API side per {class, uuid, workbench
     # request} unless {cache: false} is given via opts.
     cache_key = "request_#{Thread.current.object_id}_#{self.to_s}_#{uuid}"
@@ -105,6 +111,10 @@ class ArvadosBase < ActiveRecord::Base
     new.private_reload(hash)
   end
 
+  def self.find?(*args)
+    find(*args) rescue nil
+  end
+
   def self.order(*args)
     ArvadosResourceList.new(self).order(*args)
   end
@@ -121,6 +131,10 @@ class ArvadosBase < ActiveRecord::Base
     ArvadosResourceList.new(self).limit(*args)
   end
 
+  def self.select(*args)
+    ArvadosResourceList.new(self).select(*args)
+  end
+
   def self.eager(*args)
     ArvadosResourceList.new(self).eager(*args)
   end
@@ -133,12 +147,17 @@ class ArvadosBase < ActiveRecord::Base
     # strong_parameters does not provide security in Workbench: anyone
     # who can get this far can just as well do a call directly to our
     # database (Arvados) with the same credentials we use.
+    #
+    # The following permit! is necessary even with
+    # "ActionController::Parameters.permit_all_parameters = true",
+    # because permit_all does not permit nested attributes.
     ActionController::Parameters.new(raw_params).permit!
   end
 
-  def self.create raw_params={}
-    logger.error permit_attribute_params(raw_params).inspect
-    super(permit_attribute_params(raw_params))
+  def self.create raw_params={}, create_params={}
+    x = super(permit_attribute_params(raw_params))
+    x.create_params = create_params
+    x
   end
 
   def update_attributes raw_params={}
@@ -157,6 +176,7 @@ class ArvadosBase < ActiveRecord::Base
       obdata.delete :uuid
       resp = arvados_api_client.api(self.class, '/' + uuid, postdata)
     else
+      postdata.merge!(@create_params) if @create_params
       resp = arvados_api_client.api(self.class, '', postdata)
     end
     return false if !resp[:etag] || !resp[:uuid]
@@ -262,8 +282,9 @@ class ArvadosBase < ActiveRecord::Base
     uuid
   end
 
-  def dup
-    super.forget_uuid!
+  def initialize_copy orig
+    super
+    forget_uuid!
   end
 
   def attributes_for_display
@@ -274,25 +295,41 @@ class ArvadosBase < ActiveRecord::Base
     }
   end
 
+  def class_for_display
+    self.class.to_s.underscore.humanize
+  end
+
+  def self.class_for_display
+    self.to_s.underscore.humanize
+  end
+
   def self.creatable?
     current_user
   end
 
+  def self.goes_in_projects?
+    false
+  end
+
   def editable?
     (current_user and current_user.is_active and
      (current_user.is_admin or
-      current_user.uuid == self.owner_uuid))
+      current_user.uuid == self.owner_uuid or
+      new_record? or
+      (writable_by.include? current_user.uuid rescue false)))
   end
 
-  def attribute_editable?(attr)
+  def attribute_editable?(attr, ever=nil)
     if "created_at modified_at modified_by_user_uuid modified_by_client_uuid updated_at".index(attr.to_s)
       false
     elsif not (current_user.andand.is_active)
       false
-    elsif "uuid owner_uuid".index(attr.to_s) or current_user.is_admin
+    elsif attr == 'uuid'
       current_user.is_admin
+    elsif ever
+      true
     else
-      current_user.uuid == self.owner_uuid or current_user.uuid == self.uuid
+      editable?
     end
   end
 
@@ -325,14 +362,47 @@ class ArvadosBase < ActiveRecord::Base
     resource_class
   end
 
+  def resource_param_name
+    self.class.to_s.underscore
+  end
+
   def friendly_link_name
-    (name if self.respond_to? :name) || uuid
+    (name if self.respond_to? :name) || default_name
+  end
+
+  def content_summary
+    self.class_for_display
   end
 
   def selection_label
     friendly_link_name
   end
 
+  def self.default_name
+    self.to_s.underscore.humanize
+  end
+
+  def controller
+    (self.class.to_s.pluralize + 'Controller').constantize
+  end
+
+  def controller_name
+    self.class.to_s.tableize
+  end
+
+  # Placeholder for name when name is missing or empty
+  def default_name
+    if self.respond_to? :name
+      "New #{class_for_display.downcase}"
+    else
+      uuid
+    end
+  end
+
+  def owner
+    ArvadosBase.find(owner_uuid) rescue nil
+  end
+
   protected
 
   def forget_uuid!