1 class Link < ArvadosModel
4 include CommonApiTemplate
5 serialize :properties, Hash
6 before_create :permission_to_attach_to_objects
7 before_update :permission_to_attach_to_objects
8 after_update :maybe_invalidate_permissions_cache
9 after_create :maybe_invalidate_permissions_cache
10 after_destroy :maybe_invalidate_permissions_cache
11 attr_accessor :head_kind, :tail_kind
12 validate :name_links_are_obsolete
14 api_accessible :user, extend: :common do |t|
25 @properties ||= Hash.new
30 if k = ArvadosModel::resource_class_for_uuid(head_uuid)
36 if k = ArvadosModel::resource_class_for_uuid(tail_uuid)
43 def permission_to_attach_to_objects
44 # Anonymous users cannot write links
45 return false if !current_user
47 # All users can write links that don't affect permissions
48 return true if self.link_class != 'permission'
50 # Administrators can grant permissions
51 return true if current_user.is_admin
53 # All users can grant permissions on objects they own or can manage
54 head_obj = ArvadosModel.find_by_uuid(head_uuid)
55 return true if current_user.can?(manage: head_obj)
61 def maybe_invalidate_permissions_cache
62 if self.link_class == 'permission'
63 # Clearing the entire permissions cache can generate many
64 # unnecessary queries if many active users are not affected by
65 # this change. In such cases it would be better to search cached
66 # permissions for head_uuid and tail_uuid, and invalidate the
67 # cache for only those users. (This would require a browseable
69 User.invalidate_permissions_cache
73 def name_links_are_obsolete
74 if link_class == 'name'
75 errors.add('name', 'Name links are obsolete')
82 # A user is permitted to create, update or modify a permission link
83 # if and only if they have "manage" permission on the object
84 # indicated by the permission link's head_uuid.
86 # All other links are treated as regular ArvadosModel objects.
88 def ensure_owner_uuid_is_permitted
89 if link_class == 'permission'
90 ob = ArvadosModel.find_by_uuid(head_uuid)
91 raise PermissionDeniedError unless current_user.can?(manage: ob)
92 # All permission links should be owned by the system user.
93 self.owner_uuid = system_user_uuid