X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/8ff3fd06e165a275f53884d1d20287b68c1b32bd..797885e26f85f04123bcba751addcd415ed3db2e:/services/api/app/models/arvados_model.rb diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb index 93d5b9a023..339bc9e23f 100644 --- a/services/api/app/models/arvados_model.rb +++ b/services/api/app/models/arvados_model.rb @@ -8,7 +8,7 @@ require 'record_filters' require 'serializers' require 'request_error' -class ArvadosModel < ActiveRecord::Base +class ArvadosModel < ApplicationRecord self.abstract_class = true include ArvadosModelUpdates @@ -41,6 +41,16 @@ class ArvadosModel < ActiveRecord::Base class_name: 'Link', primary_key: :uuid) + # If async is true at create or update, permission graph + # update is deferred allowing making multiple calls without the performance + # penalty. + attr_accessor :async_permissions_update + + # Ignore listed attributes on mass assignments + def self.protected_attributes + [] + end + class PermissionDeniedError < RequestError def http_status 403 @@ -92,7 +102,11 @@ class ArvadosModel < ActiveRecord::Base # The following permit! is necessary even with # "ActionController::Parameters.permit_all_parameters = true", # because permit_all does not permit nested attributes. + raw_params ||= {} + if raw_params + raw_params = raw_params.to_hash + raw_params.delete_if { |k, _| self.protected_attributes.include? k } serialized_attributes.each do |colname, coder| param = raw_params[colname.to_sym] if param.nil? @@ -103,6 +117,15 @@ class ArvadosModel < ActiveRecord::Base raise ArgumentError.new("#{colname} parameter cannot have non-string hash keys") end end + # Check JSONB columns that aren't listed on serialized_attributes + columns.select{|c| c.type == :jsonb}.collect{|j| j.name}.each do |colname| + if serialized_attributes.include? colname || raw_params[colname.to_sym].nil? + next + end + if has_nonstring_keys?(raw_params[colname.to_sym]) + raise ArgumentError.new("#{colname} parameter cannot have non-string hash keys") + end + end end ActionController::Parameters.new(raw_params).permit! end @@ -352,7 +375,7 @@ class ArvadosModel < ActiveRecord::Base # discover a unique name. It is necessary to handle name choosing at # this level (as opposed to the client) to ensure that record creation # never fails due to a race condition. - err = rn.original_exception + err = rn.cause raise unless err.is_a?(PG::UniqueViolation) # Unfortunately ActiveRecord doesn't abstract out any of the @@ -388,7 +411,7 @@ class ArvadosModel < ActiveRecord::Base end def logged_attributes - attributes.except(*Rails.configuration.unlogged_attributes) + attributes.except(*Rails.configuration.AuditLogs.UnloggedAttributes) end def self.full_text_searchable_columns @@ -399,7 +422,8 @@ class ArvadosModel < ActiveRecord::Base def self.full_text_tsvector parts = full_text_searchable_columns.collect do |column| - cast = serialized_attributes[column] ? '::text' : '' + is_jsonb = self.columns.select{|x|x.name == column}[0].type == :jsonb + cast = (is_jsonb || serialized_attributes[column]) ? '::text' : '' "coalesce(#{column}#{cast},'')" end "to_tsvector('english', substr(#{parts.join(" || ' ' || ")}, 0, 8000))" @@ -444,7 +468,7 @@ class ArvadosModel < ActiveRecord::Base end rescue ActiveRecord::RecordNotFound => e errors.add :owner_uuid, "is not owned by any user: #{e}" - return false + throw(:abort) end if uuid_in_path[x] if x == owner_uuid @@ -452,7 +476,7 @@ class ArvadosModel < ActiveRecord::Base else errors.add :owner_uuid, "has an ownership cycle" end - return false + throw(:abort) end uuid_in_path[x] = true end @@ -557,6 +581,8 @@ class ArvadosModel < ActiveRecord::Base self.owner_uuid ||= current_default_owner if self.respond_to? :owner_uuid= if !anonymous_updater self.modified_by_user_uuid = current_user ? current_user.uuid : nil + end + if !timeless_updater self.modified_at = current_time end self.modified_by_client_uuid = current_api_client ? current_api_client.uuid : nil @@ -658,7 +684,8 @@ class ArvadosModel < ActiveRecord::Base # we'll convert symbols to strings when loading from the # database. (Otherwise, loading and saving an object with existing # symbols in a serialized field will crash.) - self.class.serialized_attributes.each do |colname, attr| + jsonb_cols = self.class.columns.select{|c| c.type == :jsonb}.collect{|j| j.name} + (jsonb_cols + self.class.serialized_attributes.keys).uniq.each do |colname| if self.class.has_symbols? attributes[colname] attributes[colname] = self.class.recursive_stringify attributes[colname] send(colname + '=', @@ -708,7 +735,7 @@ class ArvadosModel < ActiveRecord::Base end def self.uuid_like_pattern - "#{Rails.configuration.uuid_prefix}-#{uuid_prefix}-_______________" + "#{Rails.configuration.ClusterID}-#{uuid_prefix}-_______________" end def self.uuid_regex @@ -787,8 +814,8 @@ class ArvadosModel < ActiveRecord::Base end def is_audit_logging_enabled? - return !(Rails.configuration.max_audit_log_age.to_i == 0 && - Rails.configuration.max_audit_log_delete_batch.to_i > 0) + return !(Rails.configuration.AuditLogs.MaxAge.to_i == 0 && + Rails.configuration.AuditLogs.MaxDeleteBatch.to_i > 0) end def log_start_state