before_create :check_auto_admin
after_create :add_system_group_permission_link
after_create :send_admin_notifications
+ after_update :send_profile_created_notification
+
has_many :authorized_keys, :foreign_key => :authorized_user_uuid, :primary_key => :uuid
end
def groups_i_can(verb)
- self.group_permissions.select { |uuid, mask| mask[verb] }.keys
+ my_groups = self.group_permissions.select { |uuid, mask| mask[verb] }.keys
+ if verb == :read
+ my_groups << anonymous_group_uuid
+ end
+ my_groups
end
def can?(actions)
return true if is_admin
actions.each do |action, target|
- target_uuid = target
- if target.respond_to? :uuid
- target_uuid = target.uuid
+ unless target.nil?
+ if target.respond_to? :uuid
+ target_uuid = target.uuid
+ else
+ target_uuid = target
+ target = ArvadosModel.find_by_uuid(target_uuid)
+ end
end
next if target_uuid == self.uuid
next if (group_permissions[target_uuid] and
# Return a hash of {group_uuid: perm_hash} where perm_hash[:read]
# and perm_hash[:write] are true if this user can read and write
# objects owned by group_uuid.
+ #
+ # The permission graph is built by repeatedly enumerating all
+ # permission links reachable from self.uuid, and then calling
+ # search_permissions
def group_permissions
Rails.cache.fetch "groups_for_user_#{self.uuid}" do
permissions_from = {}
todo = {self.uuid => true}
done = {}
+ # Build the equivalence class of permissions starting with
+ # self.uuid. On each iteration of this loop, todo contains
+ # the next set of uuids in the permission equivalence class
+ # to evaluate.
while !todo.empty?
lookup_uuids = todo.keys
lookup_uuids.each do |uuid| done[uuid] = true end
todo = {}
newgroups = []
+ # include all groups owned by the current set of uuids.
Group.where('owner_uuid in (?)', lookup_uuids).each do |group|
newgroups << [group.owner_uuid, group.uuid, 'can_manage']
end
+ # add any permission links from the current lookup_uuids to a
+ # User or Group.
Link.where('tail_uuid in (?) and link_class = ? and (head_uuid like ? or head_uuid like ?)',
lookup_uuids,
'permission',
# delete user signatures, login, repo, and vm perms, and mark as inactive
def unsetup
# delete oid_login_perms for this user
- oid_login_perms = Link.where(tail_uuid: self.email,
- link_class: 'permission',
- name: 'can_login')
- oid_login_perms.each do |perm|
- Link.delete perm
- end
+ Link.destroy_all(tail_uuid: self.email,
+ link_class: 'permission',
+ name: 'can_login')
# delete repo_perms for this user
- repo_perms = Link.where(tail_uuid: self.uuid,
- link_class: 'permission',
- name: 'can_write')
- repo_perms.each do |perm|
- Link.delete perm
- end
+ Link.destroy_all(tail_uuid: self.uuid,
+ link_class: 'permission',
+ name: 'can_manage')
# delete vm_login_perms for this user
- vm_login_perms = Link.where(tail_uuid: self.uuid,
- link_class: 'permission',
- name: 'can_login')
- vm_login_perms.each do |perm|
- Link.delete perm
- end
+ Link.destroy_all(tail_uuid: self.uuid,
+ link_class: 'permission',
+ name: 'can_login')
# delete "All users' group read permissions for this user
group = Group.where(name: 'All users').select do |g|
g[:uuid].match /-f+$/
end.first
- group_perms = Link.where(tail_uuid: self.uuid,
- head_uuid: group[:uuid],
- link_class: 'permission',
- name: 'can_read')
- group_perms.each do |perm|
- Link.delete perm
- end
+ Link.destroy_all(tail_uuid: self.uuid,
+ head_uuid: group[:uuid],
+ link_class: 'permission',
+ name: 'can_read')
# delete any signatures by this user
- signed_uuids = Link.where(link_class: 'signature',
- tail_uuid: self.uuid)
- signed_uuids.each do |sign|
- Link.delete sign
- end
+ Link.destroy_all(link_class: 'signature',
+ tail_uuid: self.uuid)
# mark the user as inactive
self.is_active = false
self.save!
end
- def owns? object_uuid
- return User.find_user_owning(object_uuid).andand.uuid == uuid
- end
-
- def can_manage? object_uuid
- is_admin or
- owns?(object_uuid) or
- has_permission?(:can_manage, object_uuid)
- end
-
protected
- # Returns the first User found in the ownership path for obj_uuid.
- # If obj_uuid is not owned by any user, returns nil.
- #
- # TODO(twp): this code largely stolen from
- # ArvadosModel::ensure_ownership_path_leads_to_user. See if we can
- # refactor these methods to share more code.
- #
- def self.find_user_owning obj_uuid
- uuid_in_path = {obj_uuid => true}
- # Walk up the owner_uuid chain for obj_uuid until one of these
- # conditions is met:
- # - the owner_uuid belongs to the User class
- # - no owner_uuid is found (no User owns this object)
- # - we discover an ownership cycle (a fatal consistency error)
- #
- x = obj_uuid
- while (owner_class = ArvadosModel.resource_class_for_uuid(x)) != User
- begin
- if !owner_class.respond_to? :find_by_uuid
- raise ActiveRecord::RecordNotFound.new
- else
- x = owner_class.find_by_uuid(x).owner_uuid
- end
- rescue ActiveRecord::RecordNotFound => e
- # errors.add :owner_uuid, "is not owned by any user: #{e}"
- return nil
- end
- # If there is an ownership cycle, we can conclude that
- # no User owns this object.
- if uuid_in_path[x]
- return nil
- end
- uuid_in_path[x] = true
- end
- return owner_class.find_by_uuid(x)
- end
-
def ensure_ownership_path_leads_to_user
true
end
def check_auto_admin
if User.where("uuid not like '%-000000000000000'").where(:is_admin => true).count == 0 and Rails.configuration.auto_admin_user
- if current_user.email == Rails.configuration.auto_admin_user
+ if self.email == Rails.configuration.auto_admin_user
self.is_admin = true
self.is_active = true
end
repo_perms = Link.where(tail_uuid: self.uuid,
head_uuid: repo[:uuid],
link_class: 'permission',
- name: 'can_write')
+ name: 'can_manage')
if repo_perms.any?
logger.warn "User already has repository access " +
repo_perms.collect { |p| p[:uuid] }.inspect
repo_perm = Link.create(tail_uuid: self.uuid,
head_uuid: repo[:uuid],
link_class: 'permission',
- name: 'can_write')
+ name: 'can_manage')
logger.info { "repo permission: " + repo_perm[:uuid] }
return repo_perm
end
AdminNotifier.new_inactive_user(self).deliver
end
end
+
+ # Send notification if the user saved profile for the first time
+ def send_profile_created_notification
+ if self.prefs_changed?
+ if self.prefs_was.andand.empty? || !self.prefs_was.andand['profile']
+ profile_notification_address = Rails.configuration.user_profile_notification_address
+ ProfileNotifier.profile_created(self, profile_notification_address).deliver if profile_notification_address
+ end
+ end
+ end
+
end