X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/89bdd6bf07147ad707125fc3882caebb5402ab09..3a6b1a17f1b073e381b053b52e3cb0bb9c81d249:/services/api/app/models/user.rb diff --git a/services/api/app/models/user.rb b/services/api/app/models/user.rb index 2e862d3ae6..52d36ac577 100644 --- a/services/api/app/models/user.rb +++ b/services/api/app/models/user.rb @@ -21,6 +21,7 @@ class User < ArvadosModel uniqueness: true, allow_nil: true) validate :must_unsetup_to_deactivate + validate :identity_url_nil_if_empty before_update :prevent_privilege_escalation before_update :prevent_inactive_admin before_update :verify_repositories_empty, :if => Proc.new { @@ -71,6 +72,8 @@ class User < ArvadosModel t.add :is_invited t.add :prefs t.add :writable_by + t.add :can_write + t.add :can_manage end ALL_PERMISSIONS = {read: true, write: true, manage: true} @@ -86,6 +89,7 @@ class User < ArvadosModel VAL_FOR_PERM = {:read => 1, :write => 2, + :unfreeze => 3, :manage => 3} @@ -108,7 +112,6 @@ class User < ArvadosModel end def can?(actions) - return true if is_admin actions.each do |action, target| unless target.nil? if target.respond_to? :uuid @@ -120,11 +123,19 @@ class User < ArvadosModel end next if target_uuid == self.uuid + if action == :write && target && !target.new_record? && + target.respond_to?(:frozen_by_uuid) && + target.frozen_by_uuid_was + # Just an optimization to skip the PERMISSION_VIEW and + # FrozenGroup queries below + return false + end + target_owner_uuid = target.owner_uuid if target.respond_to? :owner_uuid user_uuids_subquery = USER_UUIDS_SUBQUERY_TEMPLATE % {user: "$1", perm_level: "$3"} - unless ActiveRecord::Base.connection. + if !is_admin && !ActiveRecord::Base.connection. exec_query(%{ SELECT 1 FROM #{PERMISSION_VIEW} WHERE user_uuid in (#{user_uuids_subquery}) and @@ -140,6 +151,23 @@ SELECT 1 FROM #{PERMISSION_VIEW} ).any? return false end + + if action == :write + if FrozenGroup.where(uuid: [target_uuid, target_owner_uuid]).any? + # self or parent is frozen + return false + end + elsif action == :unfreeze + # "unfreeze" permission means "can write, but only if + # explicitly un-freezing at the same time" (see + # ArvadosModel#ensure_owner_uuid_is_permitted). If the + # permission query above passed the permission level of + # :unfreeze (which is the same as :manage), and the parent + # isn't also frozen, then un-freeze is allowed. + if FrozenGroup.where(uuid: target_owner_uuid).any? + return false + end + end end true end @@ -234,8 +262,9 @@ SELECT target_uuid, perm_level name: 'can_read').empty? # Add can_read link from this user to "all users" which makes this - # user "invited" - group_perm = create_user_group_link + # user "invited", and (depending on config) a link in the opposite + # direction which makes this user visible to other users. + group_perms = add_to_all_users_group # Add git repo repo_perm = if (!repo_name.nil? || Rails.configuration.Users.AutoSetupNewUsersWithRepository) and !username.nil? @@ -267,7 +296,7 @@ SELECT target_uuid, perm_level forget_cached_group_perms - return [repo_perm, vm_login_perm, group_perm, self].compact + return [repo_perm, vm_login_perm, *group_perms, self].compact end # delete user signatures, login, repo, and vm perms, and mark as inactive @@ -300,6 +329,12 @@ SELECT target_uuid, perm_level Link.where(link_class: 'signature', tail_uuid: self.uuid).destroy_all + # delete tokens for this user + ApiClientAuthorization.where(user_id: self.id).destroy_all + # delete ssh keys for this user + AuthorizedKey.where(owner_uuid: self.uuid).destroy_all + AuthorizedKey.where(authorized_user_uuid: self.uuid).destroy_all + # delete user preferences (including profile) self.prefs = {} @@ -556,6 +591,13 @@ SELECT target_uuid, perm_level protected + def self.attributes_required_columns + super.merge( + 'can_write' => ['owner_uuid', 'uuid'], + 'can_manage' => ['owner_uuid', 'uuid'], + ) + end + def change_all_uuid_refs(old_uuid:, new_uuid:) ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |klass| klass.columns.each do |col| @@ -722,16 +764,26 @@ SELECT target_uuid, perm_level login_perm end - # add the user to the 'All users' group - def create_user_group_link - return (Link.where(tail_uuid: self.uuid, + def add_to_all_users_group + resp = [Link.where(tail_uuid: self.uuid, head_uuid: all_users_group_uuid, link_class: 'permission', - name: 'can_read').first or + name: 'can_read').first || Link.create(tail_uuid: self.uuid, head_uuid: all_users_group_uuid, link_class: 'permission', - name: 'can_read')) + name: 'can_read')] + if Rails.configuration.Users.ActivatedUsersAreVisibleToOthers + resp += [Link.where(tail_uuid: all_users_group_uuid, + head_uuid: self.uuid, + link_class: 'permission', + name: 'can_read').first || + Link.create(tail_uuid: all_users_group_uuid, + head_uuid: self.uuid, + link_class: 'permission', + name: 'can_read')] + end + return resp end # Give the special "System group" permission to manage this user and @@ -793,4 +845,10 @@ SELECT target_uuid, perm_level repo.save! end end + + def identity_url_nil_if_empty + if identity_url == "" + self.identity_url = nil + end + end end