X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/eb7227693e8847a65798afa7f7e8a4ffe8a199a4..bf7687829f5222375441cf75c7d82d82a4f508c4:/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 fc96cf5768..33e107e369 100644 --- a/apps/workbench/app/models/arvados_base.rb +++ b/apps/workbench/app/models/arvados_base.rb @@ -1,12 +1,21 @@ 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 + 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,21 +30,28 @@ class ArvadosBase < ActiveRecord::Base end end - def initialize(*args) - super(*args) + 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 @@ -43,7 +59,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 @@ -58,7 +74,6 @@ class ArvadosBase < ActiveRecord::Base @columns << column(k, :text) serialize k, coldef[:type].constantize end - attr_accessible k @attribute_info[k] = coldef end end @@ -79,14 +94,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 @@ -115,6 +135,27 @@ 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={}, create_params={} + x = super(permit_attribute_params(raw_params)) + x.create_params = create_params + x + end + + def update_attributes raw_params={} + super(self.class.permit_attribute_params(raw_params)) + end + def save obdata = {} self.class.columns.each do |col| @@ -125,9 +166,10 @@ 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) + postdata.merge!(@create_params) if @create_params + resp = arvados_api_client.api(self.class, '', postdata) end return false if !resp[:etag] || !resp[:uuid] @@ -135,12 +177,10 @@ class ArvadosBase < ActiveRecord::Base @etag = resp[:etag] @kind = resp[:kind] - # these attrs can be modified by "save" -- we should update our copies - %w(uuid owner_uuid created_at updated_at - modified_at modified_by_user_uuid modified_by_client_uuid - ).each do |attr| + # attributes can be modified during "save" -- we should update our copies + resp.keys.each do |attr| if self.respond_to? "#{attr}=".to_sym - self.send(attr + '=', resp[attr.to_sym]) + self.send(attr.to_s + '=', resp[attr.to_sym]) end end @@ -156,7 +196,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 @@ -183,13 +223,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, @@ -197,7 +237,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 @@ -209,7 +249,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 + '=') @@ -246,25 +286,37 @@ class ArvadosBase < ActiveRecord::Base } end + def class_for_display + self.class.to_s + end + def self.creatable? current_user end + def self.goes_in_folders? + 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 @@ -283,13 +335,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')]) @@ -301,10 +353,18 @@ class ArvadosBase < ActiveRecord::Base (name if self.respond_to? :name) || uuid end + def content_summary + self.class_for_display + end + def selection_label friendly_link_name end + def owner + ArvadosBase.find(owner_uuid) rescue nil + end + protected def forget_uuid!