X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/76e20e694fbe708e17e57a2e0b1c36aca6e8d7d0..fb95d0d2d09c9537f5bdc503e51cf4f091d02c46:/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 ae0e490c6e..79237b80e3 100644 --- a/services/api/app/models/arvados_model.rb +++ b/services/api/app/models/arvados_model.rb @@ -1,4 +1,5 @@ -require 'assign_uuid' +require 'has_uuid' + class ArvadosModel < ActiveRecord::Base self.abstract_class = true @@ -14,7 +15,6 @@ class ArvadosModel < ActiveRecord::Base before_save :ensure_ownership_path_leads_to_user before_destroy :ensure_owner_uuid_is_permitted before_destroy :ensure_permission_to_destroy - before_create :update_modified_by_fields before_update :maybe_update_modified_by_fields after_create :log_create @@ -27,7 +27,7 @@ class ArvadosModel < ActiveRecord::Base # Note: This only returns permission links. It does not account for # permissions obtained via user.is_admin or # user.uuid==object.owner_uuid. - has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'" + has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'", dependent: :destroy class PermissionDeniedError < StandardError def http_status @@ -64,6 +64,24 @@ class ArvadosModel < ActiveRecord::Base self.columns.select { |col| col.name == attr.to_s }.first end + # Return nil if current user is not allowed to see the list of + # writers. Otherwise, return a list of user_ and group_uuids with + # write permission. (If not returning nil, current_user is always in + # the list because can_manage permission is needed to see the list + # of writers.) + def writable_by + unless (owner_uuid == current_user.uuid or + current_user.is_admin or + current_user.groups_i_can(:manage).index(owner_uuid)) + return nil + end + [owner_uuid, current_user.uuid] + permissions.collect do |p| + if ['can_write', 'can_manage'].index p.name + p.tail_uuid + end + end.compact.uniq + end + # Return a query with read permissions restricted to the union of of the # permissions of the members of users_list, i.e. if something is readable by # any user in users_list, it will be readable in the query returned by this @@ -144,6 +162,8 @@ class ArvadosModel < ActiveRecord::Base if x == uuid # Test for cycles with the new version, not the DB contents x = owner_uuid + elsif !owner_class.respond_to? :find_by_uuid + raise ActiveRecord::RecordNotFound.new else x = owner_class.find_by_uuid(x).owner_uuid end @@ -166,7 +186,7 @@ class ArvadosModel < ActiveRecord::Base end def ensure_owner_uuid_is_permitted - return false if !current_user + raise PermissionDeniedError if !current_user self.owner_uuid ||= current_user.uuid if self.owner_uuid_changed? if current_user.uuid == self.owner_uuid or @@ -174,7 +194,7 @@ class ArvadosModel < ActiveRecord::Base # current_user is, or has :write permission on, the new owner else logger.warn "User #{current_user.uuid} tried to change owner_uuid of #{self.class.to_s} #{self.uuid} to #{self.owner_uuid} but does not have permission to write to #{self.owner_uuid}" - return false + raise PermissionDeniedError end end if new_record? @@ -217,6 +237,11 @@ class ArvadosModel < ActiveRecord::Base return true end + def destroy_permission_links + Link.destroy_all(['link_class=? and (head_uuid=? or tail_uuid=?)', + 'permission', uuid, uuid]) + end + def ensure_permission_to_destroy raise PermissionDeniedError unless permission_to_destroy end @@ -227,6 +252,7 @@ class ArvadosModel < ActiveRecord::Base def maybe_update_modified_by_fields update_modified_by_fields if self.changed? or self.new_record? + true end def update_modified_by_fields @@ -235,6 +261,7 @@ class ArvadosModel < ActiveRecord::Base self.modified_at = Time.now self.modified_by_user_uuid = current_user ? current_user.uuid : nil self.modified_by_client_uuid = current_api_client ? current_api_client.uuid : nil + true end def ensure_serialized_attribute_type