+ PermLevel = {
+ 'can_read' => 0,
+ 'can_write' => 1,
+ 'can_manage' => 2,
+ }
+
+ def apply_max_overlapping_permissions
+ return if self.link_class != 'permission' || !PermLevel[self.name]
+ Link.
+ lock. # select ... for update
+ where(link_class: 'permission',
+ tail_uuid: self.tail_uuid,
+ head_uuid: self.head_uuid,
+ name: PermLevel.keys).
+ where('uuid <> ?', self.uuid).each do |other|
+ if PermLevel[other.name] > PermLevel[self.name]
+ self.name = other.name
+ end
+ end
+ end
+
+ def delete_overlapping_permissions
+ return if self.link_class != 'permission'
+ redundant = nil
+ if PermLevel[self.name]
+ redundant = Link.
+ lock. # select ... for update
+ where(link_class: 'permission',
+ tail_uuid: self.tail_uuid,
+ head_uuid: self.head_uuid,
+ name: PermLevel.keys).
+ where('uuid <> ?', self.uuid)
+ elsif self.name == 'can_login' &&
+ self.properties.respond_to?(:has_key?) &&
+ self.properties.has_key?('username')
+ redundant = Link.
+ lock. # select ... for update
+ where(link_class: 'permission',
+ tail_uuid: self.tail_uuid,
+ head_uuid: self.head_uuid,
+ name: 'can_login').
+ where('properties @> ?', SafeJSON.dump({'username' => self.properties['username']})).
+ where('uuid <> ?', self.uuid)
+ end
+ if redundant
+ redundant.each do |link|
+ link.clear_permissions
+ end
+ redundant.delete_all
+ end