Merge branch '9623-reuse-containers'
[arvados.git] / services / api / app / models / arvados_model.rb
index 8ae3e43fecdd5dd371e41ec9d0d5ecc9b4d8deca..7d1c30cdaf63b418086a265c5129a103d168cb67 100644 (file)
@@ -1,10 +1,12 @@
 require 'has_uuid'
+require 'record_filters'
 
 class ArvadosModel < ActiveRecord::Base
   self.abstract_class = true
 
   include CurrentApiClient      # current_user, current_api_client, etc.
   include DbCurrentTime
+  extend RecordFilters
 
   attr_protected :created_at
   attr_protected :modified_by_user_uuid
@@ -40,7 +42,13 @@ class ArvadosModel < ActiveRecord::Base
 
   class AlreadyLockedError < StandardError
     def http_status
-      403
+      422
+    end
+  end
+
+  class InvalidStateTransitionError < StandardError
+    def http_status
+      422
     end
   end
 
@@ -199,6 +207,7 @@ class ArvadosModel < ActiveRecord::Base
     # authorized users themselves) is an object's owner_uuid, that
     # object is readable.
     owner_uuids = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
+    owner_uuids.uniq!
 
     sql_conds = []
     sql_table = kwargs.fetch(:table_name, table_name)
@@ -251,8 +260,29 @@ class ArvadosModel < ActiveRecord::Base
     "to_tsvector('english', ' ' || #{parts.join(" || ' ' || ")})"
   end
 
+  def self.apply_filters query, filters
+    ft = record_filters filters, self
+    if not ft[:cond_out].any?
+      return query
+    end
+    query.where('(' + ft[:cond_out].join(') AND (') + ')',
+                          *ft[:param_out])
+  end
+
   protected
 
+  def self.deep_sort_hash(x)
+    if x.is_a? Hash
+      x.sort.collect do |k, v|
+        [k, deep_sort_hash(v)]
+      end.to_h
+    elsif x.is_a? Array
+      x.collect { |v| deep_sort_hash(v) }
+    else
+      x
+    end
+  end
+
   def ensure_ownership_path_leads_to_user
     if new_record? or owner_uuid_changed?
       uuid_in_path = {owner_uuid => true, uuid => true}