X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/c1e7255a85dfc2807ba78e1cf9d109d896c80b42..66fc74001e777ac7ceff2b02cfc459b1368f42f3:/services/api/lib/has_uuid.rb diff --git a/services/api/lib/has_uuid.rb b/services/api/lib/has_uuid.rb index 481d27a037..dc8bdcb6c5 100644 --- a/services/api/lib/has_uuid.rb +++ b/services/api/lib/has_uuid.rb @@ -1,11 +1,28 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + module HasUuid + UUID_REGEX = /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/ + def self.included(base) base.extend(ClassMethods) + base.validate :validate_uuid base.before_create :assign_uuid base.before_destroy :destroy_permission_links - base.has_many :links_via_head, class_name: 'Link', foreign_key: :head_uuid, primary_key: :uuid, conditions: "not (link_class = 'permission')", dependent: :restrict - base.has_many :links_via_tail, class_name: 'Link', foreign_key: :tail_uuid, primary_key: :uuid, conditions: "not (link_class = 'permission')", dependent: :restrict + base.has_many(:links_via_head, + -> { where("not (link_class = 'permission')") }, + class_name: 'Link', + foreign_key: :head_uuid, + primary_key: :uuid, + dependent: :destroy) + base.has_many(:links_via_tail, + -> { where("not (link_class = 'permission')") }, + class_name: 'Link', + foreign_key: :tail_uuid, + primary_key: :uuid, + dependent: :destroy) end module ClassMethods @@ -26,13 +43,38 @@ module HasUuid self.respond_to? :uuid end - def assign_uuid - return true if !self.respond_to_uuid? - if (uuid.is_a?(String) and uuid.length>0 and - current_user and current_user.is_admin) + def validate_uuid + if self.respond_to_uuid? and self.uuid_changed? + if current_user.andand.is_admin and self.uuid.is_a?(String) + if (re = self.uuid.match HasUuid::UUID_REGEX) + if re[1] == self.class.uuid_prefix + return true + else + self.errors.add(:uuid, "type field is '#{re[1]}', expected '#{self.class.uuid_prefix}'") + return false + end + else + self.errors.add(:uuid, "not a valid Arvados uuid '#{self.uuid}'") + return false + end + else + if self.new_record? + self.errors.add(:uuid, "assignment not permitted") + else + self.errors.add(:uuid, "change not permitted") + end + return false + end + else return true end - self.uuid = self.class.generate_uuid + end + + def assign_uuid + if self.respond_to_uuid? and self.uuid.nil? or self.uuid.empty? + self.uuid = self.class.generate_uuid + end + true end def destroy_permission_links