X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/c19ef999c3b938e6d3cdc3746fab5bad8aba3403..84decc8949fc51ec2eaf906fc2c4cbbb3df807dd:/apps/workbench/app/models/arvados_base.rb diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb index a4ec7ab265..7d8603782e 100644 --- a/apps/workbench/app/models/arvados_base.rb +++ b/apps/workbench/app/models/arvados_base.rb @@ -2,11 +2,19 @@ class ArvadosBase < ActiveRecord::Base self.abstract_class = true attr_accessor :attribute_sortkey + def self.arvados_api_client + ArvadosApiClient.new_or_current + end + + def arvados_api_client + ArvadosApiClient.new_or_current + end + def self.uuid_infix_object_kind @@uuid_infix_object_kind ||= begin infix_kind = {} - $arvados_api_client.discovery[:schemas].each do |name, schema| + arvados_api_client.discovery[:schemas].each do |name, schema| if schema[:uuidPrefix] infix_kind[schema[:uuidPrefix]] = 'arvados#' + name.to_s.camelcase(:lower) @@ -21,8 +29,8 @@ class ArvadosBase < ActiveRecord::Base end end - def initialize(*args) - super(*args) + def initialize raw_params={} + super self.class.permit_attribute_params(raw_params) @attribute_sortkey ||= { 'id' => nil, 'name' => '000', @@ -49,7 +57,7 @@ class ArvadosBase < ActiveRecord::Base return @columns unless @columns.nil? @columns = [] @attribute_info ||= {} - schema = $arvados_api_client.discovery[:schemas][self.to_s.to_sym] + schema = arvados_api_client.discovery[:schemas][self.to_s.to_sym] return @columns if schema.nil? schema[:properties].each do |k, coldef| case k @@ -64,7 +72,6 @@ class ArvadosBase < ActiveRecord::Base @columns << column(k, :text) serialize k, coldef[:type].constantize end - attr_accessible k @attribute_info[k] = coldef end end @@ -85,14 +92,19 @@ 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}" if opts[:cache] == false - Rails.cache.write cache_key, $arvados_api_client.api(self, '/' + uuid) + Rails.cache.write cache_key, arvados_api_client.api(self, '/' + uuid) end hash = Rails.cache.fetch cache_key do - $arvados_api_client.api(self, '/' + uuid) + arvados_api_client.api(self, '/' + uuid) end new.private_reload(hash) end @@ -121,6 +133,25 @@ class ArvadosBase < ActiveRecord::Base ArvadosResourceList.new(self).all(*args) end + def self.permit_attribute_params raw_params + # 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={} + super(permit_attribute_params(raw_params)) + end + + def update_attributes raw_params={} + super(self.class.permit_attribute_params(raw_params)) + end + def save obdata = {} self.class.columns.each do |col| @@ -131,9 +162,9 @@ class ArvadosBase < ActiveRecord::Base if etag postdata['_method'] = 'PUT' obdata.delete :uuid - resp = $arvados_api_client.api(self.class, '/' + uuid, postdata) + resp = arvados_api_client.api(self.class, '/' + uuid, postdata) else - resp = $arvados_api_client.api(self.class, '', postdata) + resp = arvados_api_client.api(self.class, '', postdata) end return false if !resp[:etag] || !resp[:uuid] @@ -160,7 +191,7 @@ class ArvadosBase < ActiveRecord::Base def destroy if etag || uuid postdata = { '_method' => 'DELETE' } - resp = $arvados_api_client.api(self.class, '/' + uuid, postdata) + resp = arvados_api_client.api(self.class, '/' + uuid, postdata) resp[:etag] && resp[:uuid] && resp else true @@ -187,13 +218,13 @@ class ArvadosBase < ActiveRecord::Base ok end end - @links = $arvados_api_client.api Link, '', { _method: 'GET', where: o, eager: true } - @links = $arvados_api_client.unpack_api_response(@links) + @links = arvados_api_client.api Link, '', { _method: 'GET', where: o, eager: true } + @links = arvados_api_client.unpack_api_response(@links) end def all_links return @all_links if @all_links - res = $arvados_api_client.api Link, '', { + res = arvados_api_client.api Link, '', { _method: 'GET', where: { tail_kind: self.kind, @@ -201,7 +232,7 @@ class ArvadosBase < ActiveRecord::Base }, eager: true } - @all_links = $arvados_api_client.unpack_api_response(res) + @all_links = arvados_api_client.unpack_api_response(res) end def reload @@ -213,7 +244,7 @@ class ArvadosBase < ActiveRecord::Base if uuid_or_hash.is_a? Hash hash = uuid_or_hash else - hash = $arvados_api_client.api(self.class, '/' + uuid_or_hash) + hash = arvados_api_client.api(self.class, '/' + uuid_or_hash) end hash.each do |k,v| if self.respond_to?(k.to_s + '=') @@ -261,7 +292,9 @@ class ArvadosBase < ActiveRecord::Base 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) @@ -269,10 +302,10 @@ class ArvadosBase < ActiveRecord::Base 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 else - current_user.uuid == self.owner_uuid or current_user.uuid == self.uuid + editable? end end @@ -291,13 +324,13 @@ class ArvadosBase < ActiveRecord::Base end resource_class = nil uuid.match /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/ do |re| - resource_class ||= $arvados_api_client. + resource_class ||= arvados_api_client. kind_class(self.uuid_infix_object_kind[re[1]]) end if opts[:referring_object] and opts[:referring_attr] and opts[:referring_attr].match /_uuid$/ - resource_class ||= $arvados_api_client. + resource_class ||= arvados_api_client. kind_class(opts[:referring_object]. attributes[opts[:referring_attr]. sub(/_uuid$/, '_kind')]) @@ -317,6 +350,10 @@ class ArvadosBase < ActiveRecord::Base friendly_link_name end + def owner + ArvadosBase.find(owner_uuid) rescue nil + end + protected def forget_uuid!