diff --git a/app/graphql/irida_schema.rb b/app/graphql/irida_schema.rb index 88c2a17e60..8d0ec20e3d 100644 --- a/app/graphql/irida_schema.rb +++ b/app/graphql/irida_schema.rb @@ -38,6 +38,11 @@ def self.resolve_type(_type, object, _ctx) # Stop validating when it encounters this many errors: validate_max_errors 100 + def self.execute(query_str = nil, **kwargs) + Current.token = kwargs[:context][:token] + super + end + # Relay-style Object Identification: # Return a string UUID for `object` diff --git a/app/models/current.rb b/app/models/current.rb index 91fb092687..23d21682e7 100644 --- a/app/models/current.rb +++ b/app/models/current.rb @@ -3,4 +3,5 @@ # thread-isolated attributes class class Current < ActiveSupport::CurrentAttributes attribute :user + attribute :token end diff --git a/app/models/member.rb b/app/models/member.rb index d285a0ef42..a0d6acc725 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -30,6 +30,10 @@ class Member < ApplicationRecord # rubocop:disable Metrics/ClassLength scope :not_expired, -> { where('expires_at IS NULL OR expires_at > ?', Time.zone.now.beginning_of_day) } class << self + DEFAULT_CAN_OPTIONS = { + include_group_links: true + }.freeze + def access_levels(member) case member.access_level when AccessLevel::OWNER @@ -41,7 +45,7 @@ def access_levels(member) end end - def effective_access_level(namespace, user, include_group_links = true) # rubocop:disable Metrics/CyclomaticComplexity, Style/OptionalBooleanParameter + def effective_access_level(namespace, user, include_group_links = true) # rubocop:disable Metrics/CyclomaticComplexity,Style/OptionalBooleanParameter return AccessLevel::OWNER if namespace.parent&.user_namespace? && namespace.parent.owner == user access_level = Member.for_namespace_and_ancestors(namespace).not_expired @@ -64,9 +68,13 @@ def can_create?(user, object_namespace) ) end - def can_view?(user, object_namespace, include_group_links = true) # rubocop:disable Style/OptionalBooleanParameter - effective_access_level = effective_access_level(object_namespace, user, include_group_links) - return false if effective_access_level == Member::AccessLevel::UPLOADER + def can_view?(user, object_namespace, **options) + options = DEFAULT_CAN_OPTIONS.merge(options) + effective_access_level = effective_access_level(object_namespace, user, options[:include_group_links]) + if effective_access_level == Member::AccessLevel::UPLOADER && + !Current.token&.active? + return false + end effective_access_level > Member::AccessLevel::NO_ACCESS end @@ -86,7 +94,9 @@ def can_transfer_into_namespace?(user, object_namespace, include_group_links = t end def can_transfer_sample?(user, object_namespace) - namespace_owners_include_user?(user, object_namespace) + Member::AccessLevel.manageable.include?( + effective_access_level(object_namespace, user, false) + ) end def can_transfer_sample_to_project?(user, object_namespace, include_group_links = true) # rubocop:disable Style/OptionalBooleanParameter @@ -141,6 +151,26 @@ def can_create_export?(user, object_namespace) effective_access_level(object_namespace, user) >= Member::AccessLevel::ANALYST end + def can_create_sample?(user, object_namespace) + effective_access_level = effective_access_level(object_namespace, user) + + return true if (effective_access_level == Member::AccessLevel::UPLOADER) && Current.token&.active? + + Member::AccessLevel.manageable.include?( + effective_access_level + ) + end + + def can_modify_sample?(user, object_namespace) + effective_access_level = effective_access_level(object_namespace, user) + + return true if (effective_access_level == Member::AccessLevel::UPLOADER) && Current.token&.active? + + Member::AccessLevel.manageable.include?( + effective_access_level + ) + end + def access_level_in_namespace_group_links(user, namespace) effective_namespace_group_link = NamespaceGroupLink.for_namespace_and_ancestors(namespace) .where(group: user.groups.self_and_descendants) diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 3f46c86b21..f6909800a7 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -17,7 +17,7 @@ def create_subgroup? end def view_history? - return true if Member.can_view?(user, record, false) == true + return true if Member.can_view?(user, record, include_group_links: false) == true details[:name] = record.name false diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 0a6eebaee8..11499f674f 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -12,7 +12,7 @@ def activity? def view_history? return true if record.namespace.parent.user_namespace? && record.namespace.parent.owner == user - return true if Member.can_view?(user, record.namespace, false) == true + return true if Member.can_view?(user, record.namespace, include_group_links: false) == true details[:name] = record.name false @@ -76,7 +76,7 @@ def sample_listing? def create_sample? return true if record.namespace.parent.user_namespace? && record.namespace.parent.owner == user - return true if Member.can_create?(user, record.namespace) == true + return true if Member.can_create_sample?(user, record.namespace) == true details[:name] = record.name false @@ -100,16 +100,13 @@ def read_sample? def update_sample? return true if record.namespace.parent.user_namespace? && record.namespace.parent.owner == user - return true if Member.can_modify?(user, record.namespace) == true + return true if Member.can_modify_sample?(user, record.namespace) == true details[:name] = record.name false end - def transfer_sample? # rubocop:disable Metrics/AbcSize - # Maintainer is allowed to transfer a sample to another namespace which has the same parent or ancestor - return true if Member.user_has_namespace_maintainer_access?(user, record.namespace, false) - return true if record.namespace.parent.user_namespace? && record.namespace.parent.owner == user + def transfer_sample? return true if Member.can_transfer_sample?(user, record.namespace) == true details[:name] = record.name diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb index 6c259b9243..037b85d892 100644 --- a/app/services/members/create_service.rb +++ b/app/services/members/create_service.rb @@ -25,7 +25,7 @@ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Met namespace_type: namespace.class.model_name.human) end - has_previous_access = Member.can_view?(member.user, namespace, true) if member.valid? + has_previous_access = Member.can_view?(member.user, namespace) if member.valid? send_emails if member.save && @email_notification && !has_previous_access member rescue Members::CreateService::MemberCreateError => e diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb index 81d6316364..779b9c510b 100644 --- a/app/services/members/destroy_service.rb +++ b/app/services/members/destroy_service.rb @@ -34,7 +34,7 @@ def execute # rubocop:disable Metrics/AbcSize private def send_emails - return if Member.can_view?(member.user, namespace, true) + return if Member.can_view?(member.user, namespace) MemberMailer.access_revoked_user_email(member, namespace).deliver_later diff --git a/docs-site/docs/user/organization/members/member-permissions.md b/docs-site/docs/user/organization/members/member-permissions.md index 73eaded9d2..c3af6af33b 100644 --- a/docs-site/docs/user/organization/members/member-permissions.md +++ b/docs-site/docs/user/organization/members/member-permissions.md @@ -35,14 +35,17 @@ The following table lists group permissions available for each role: | Create Group and Subgroups | | | | ✓ | ✓ | | Edit Group and Subgroups | | | | ✓ | ✓ | | Delete Group and Subgroups | | | | | ✓ | -| View Group and Subgroups | ✓ | | ✓ | ✓ | ✓ | +| View Group and Subgroups | ✓ | ✓ (2) | ✓ | ✓ | ✓ | | Transfer Group and Subgroups | | | | | ✓ | | Add Group Member | | | | ✓(1) | ✓ | | Edit Group Member | | | | ✓(1) | ✓ | | Remove Group Member | | | | ✓(1) | ✓ | | View Group Members | ✓ | | ✓ | ✓ | ✓ | - + + + 1. A user with the **Maintainer** role can only modify members upto and including their role +2. A user or bot account with the **Uploader** role can only perform these actions via the api ## Subgroup permissions @@ -50,21 +53,24 @@ When you add a member to a subgroup where they are also a member of one of the p ## Project Members Permissions -| Action | Guest | Analyst | Maintainer | Owner | -| :-------------------- | :---- | ------- | ---------- | ----- | -| Create Project | | | ✓ | ✓ | -| Edit Project | | | ✓ | ✓ | -| Delete Project | | | | ✓ | -| View Project | ✓ | ✓ | ✓ | ✓ | -| Transfer Project | | | | ✓ | -| Add Project Member | | | ✓(1) | ✓ | -| Edit Project Member | | | ✓(1) | ✓ | -| Remove Project Member | | | ✓(1) | ✓ | -| View Project Members | ✓ | ✓ | ✓ | ✓ | -| Create Samples | | | ✓ | ✓ | -| Edit Samples | | | ✓ | ✓ | -| Delete Samples | | | | ✓ | -| Transfer Samples | | | ✓(2) | ✓ | +| Action | Guest | Uploader | Analyst | Maintainer | Owner | +| :-------------------- | :---- | -------- | ------- | ---------- | ----- | +| Create Project | | | | ✓ | ✓ | +| Edit Project | | | | ✓ | ✓ | +| Delete Project | | | | | ✓ | +| View Project | ✓ | ✓(3) | ✓ | ✓ | ✓ | +| Transfer Project | | | | | ✓ | +| Add Project Member | | | | ✓(1) | ✓ | +| Edit Project Member | | | | ✓(1) | ✓ | +| Remove Project Member | | | | ✓(1) | ✓ | +| View Project Members | ✓ | | ✓ | ✓ | ✓ | +| Create Samples | | ✓(3) | | ✓ | ✓ | +| Edit Samples | | ✓(3) | | ✓ | ✓ | +| Delete Samples | | | | | ✓ | +| Transfer Samples | | | | ✓(2) | ✓ | + + 1. A user with the **Maintainer** role can only modify members upto and including their role 2. A user with the **Maintainer** role can only transfer samples to another project under the common ancestor for the current project +3. A user or bot account with the **Uploader** role can only perform these actions via the api diff --git a/test/fixtures/members.yml b/test/fixtures/members.yml index 20d2e9fb2f..16b3298dfb 100644 --- a/test/fixtures/members.yml +++ b/test/fixtures/members.yml @@ -535,3 +535,9 @@ projectA_member_joan_doe: created_by_id: <%= ActiveRecord::FixtureSet.identify(:jeff_doe, :uuid) %> namespace_id: <%= ActiveRecord::FixtureSet.identify(:projectA_namespace, :uuid) %> access_level: <%= Member::AccessLevel::MAINTAINER %> + +project_jeff_member_user_bot_account: + user_id: <%= ActiveRecord::FixtureSet.identify(:projectJeff_bot, :uuid) %> + created_by_id: <%= ActiveRecord::FixtureSet.identify(:jeff_doe, :uuid) %> + namespace_id: <%= ActiveRecord::FixtureSet.identify(:project_jeff_namespace, :uuid) %> + access_level: <%= Member::AccessLevel::UPLOADER %> diff --git a/test/fixtures/namespace_bots.yml b/test/fixtures/namespace_bots.yml index 39d8482521..a83d6753f2 100644 --- a/test/fixtures/namespace_bots.yml +++ b/test/fixtures/namespace_bots.yml @@ -15,3 +15,7 @@ group1_bot<%= (n) %>: invalid_user_bot: namespace_id: <%= ActiveRecord::FixtureSet.identify(:john_doe_namespace, :uuid) %> user_id: <%= ActiveRecord::FixtureSet.identify(:john_doe, :uuid) %> + +projectJeff_bot: + namespace_id: <%= ActiveRecord::FixtureSet.identify(:project_jeff_namespace, :uuid) %> + user_id: <%= ActiveRecord::FixtureSet.identify(:projectJeff_bot, :uuid) %> diff --git a/test/fixtures/personal_access_tokens.yml b/test/fixtures/personal_access_tokens.yml index 3a96b459a1..f0955c5598 100644 --- a/test/fixtures/personal_access_tokens.yml +++ b/test/fixtures/personal_access_tokens.yml @@ -93,7 +93,6 @@ user_bot_account<%= (n) %>_valid_pat: last_used_at: nil <% end %> - <% 21.times do |n| %> user_group_bot_account<%= (n) %>_valid_pat: user_id: <%= ActiveRecord::FixtureSet.identify(:"user_group_bot_account#{n}", :uuid) %> @@ -106,3 +105,36 @@ user_group_bot_account<%= (n) %>_valid_pat: token_digest: <%= Devise.token_generator.digest(PersonalAccessToken, :token_digest, "AX3wwK3sWCjn#{n}xdCyZtH") %> last_used_at: nil <% end %> + +projectJeff_bot_account_valid_pat: + user_id: <%= ActiveRecord::FixtureSet.identify(:projectJeff_bot, :uuid) %> + scopes: + - read_api + - api + name: Valid PAT1 %> + revoked: false + expires_at: <%= 10.days.from_now.to_date %> + token_digest: <%= Devise.token_generator.digest(PersonalAccessToken, :token_digest, "FX3wwK3sWCjn1xdCyZtA") %> + last_used_at: nil + +user_bot_account0_expired_pat: + user_id: <%= ActiveRecord::FixtureSet.identify(:user_bot_account0, :uuid) %> + scopes: + - read_api + - api + name: Expired Valid PAT0 + revoked: false + expires_at: <%= 10.days.ago.to_date %> + token_digest: <%= Devise.token_generator.digest(PersonalAccessToken, :token_digest, "VX3wwK3sWCjn0xdCyZtH") %> + last_used_at: nil + +user_group_bot_account0_expired_pat: + user_id: <%= ActiveRecord::FixtureSet.identify(:user_group_bot_account0, :uuid) %> + scopes: + - read_api + - api + name: Expired PAT 0 + revoked: false + expires_at: <%= 5.days.ago.to_date %> + token_digest: <%= Devise.token_generator.digest(PersonalAccessToken, :token_digest, "TA3wwK3sWCjn0xdCyZtH") %> + last_used_at: nil diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 5180205024..ded98202ba 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -211,3 +211,10 @@ janitor_doe: first_name: project last_name: "end to end user" locale: en + +projectJeff_bot: + email: <%= "inxt_prj_aaaaaaaabp_001@localhost" %> + encrypted_password: <%= User.new.send :password_digest, "password1" %> + first_name: INXT_PRJ_AAAAAAAABP + last_name: Bot + user_type: <%= User.user_types[:project_bot] %> diff --git a/test/graphql/attach_files_to_sample_test.rb b/test/graphql/attach_files_to_sample_test.rb index f4e2e01b2e..91667f8435 100644 --- a/test/graphql/attach_files_to_sample_test.rb +++ b/test/graphql/attach_files_to_sample_test.rb @@ -85,6 +85,34 @@ def setup assert_equal 'afts.fastq', sample.attachments[0].filename.to_s end + test 'attachFilesToSample mutation should work with valid params, puid, and api scope token for uploader access level' do # rubocop:disable Layout/LineLength + user = users(:projectJeff_bot) + token = personal_access_tokens(:projectJeff_bot_account_valid_pat) + sample = samples(:sampleJeff) + blob_file = active_storage_blobs(:attachment_attach_files_to_sample_test_blob) + + assert_equal 0, sample.attachments.count + + result = IridaSchema.execute(ATTACH_FILES_TO_SAMPLE_BY_SAMPLE_PUID_MUTATION, + context: { current_user: user, token: }, + variables: { files: [blob_file.signed_id], + samplePuid: sample.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['attachFilesToSample'] + + assert_not_empty data, 'attachFilesToSample should be populated when no authorization errors' + expected_status = { blob_file.signed_id => :success } + assert_equal expected_status, data['status'] + assert_not_empty data['sample'] + + assert_equal 1, sample.attachments.count + + # check that filename matches + assert_equal 'afts.fastq', sample.attachments[0].filename.to_s + end + test 'attachFilesToSample mutation should not work with read api scope token' do sample = samples(:sampleJeff) blob_file = active_storage_blobs(:attachment_attach_files_to_sample_test_blob) diff --git a/test/graphql/attachments_query_test.rb b/test/graphql/attachments_query_test.rb index 272303bea4..8cff468455 100644 --- a/test/graphql/attachments_query_test.rb +++ b/test/graphql/attachments_query_test.rb @@ -107,6 +107,36 @@ def setup assert_equal 'none', attachments[1]['node']['metadata']['compression'] end + test 'attachment query should work for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + result = IridaSchema.execute(ATTACHMENTS_QUERY, context: { current_user: user, token: }, + variables: { puid: @sample.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['sample'] + + assert_not_empty data, 'sample type should work' + + assert_not_empty data['attachments'] + assert_not_empty data['attachments']['edges'] + + attachments = data['attachments']['edges'] + assert_equal 2, attachments.count + + assert_equal 'test_file.fastq', attachments[0]['node']['filename'] + assert_equal 'test_file_A.fastq', attachments[1]['node']['filename'] + + assert_equal 2102, attachments[0]['node']['byteSize'] + assert_equal 2101, attachments[1]['node']['byteSize'] + + assert_equal 'fastq', attachments[0]['node']['metadata']['format'] + assert_equal 'none', attachments[0]['node']['metadata']['compression'] + assert_equal 'fastq', attachments[1]['node']['metadata']['format'] + assert_equal 'none', attachments[1]['node']['metadata']['compression'] + end + test 'attachment url query should work' do result = IridaSchema.execute(ATTACHMENTS_URL_QUERY, context: { current_user: @user }, variables: { puid: @sample.puid }) @@ -126,6 +156,19 @@ def setup assert_equal file_url2, attachments[1]['node']['attachmentUrl'] end + test 'attachment url query should not work due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + result = IridaSchema.execute(ATTACHMENTS_URL_QUERY, context: { current_user: user, token: }, + variables: { puid: @sample.puid }) + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal 'An object of type Sample was hidden due to permissions', error_message + end + test 'attachment metadata delimit query should work' do result = IridaSchema.execute(ATTACHMENTS_METADATA_QUERY, context: { current_user: @user }, variables: { puid: @sample.puid }) diff --git a/test/graphql/create_direct_upload_test.rb b/test/graphql/create_direct_upload_test.rb index 5b1d658e3a..9b5e18735a 100644 --- a/test/graphql/create_direct_upload_test.rb +++ b/test/graphql/create_direct_upload_test.rb @@ -48,6 +48,29 @@ def setup assert_not_empty data['directUpload']['signedBlobId'] end + test 'createDirectUpload mutation should work with valid params and api scope token with uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + result = IridaSchema.execute(CREATE_DIRECT_UPLOAD_MUTATION, + context: { current_user: user, token: }, + variables: { filename: 'dev.to', + contentType: 'image/jpeg', + checksum: 'asZ3Yzc2Q5iA5eXIgeTJndf', + byteSize: 123 }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['createDirectUpload'] + + assert_not_empty data, 'createDirectUpload should be populated when no authorization errors' + assert_not_empty data['directUpload'] + + assert_equal '{"Content-Type":"image/jpeg"}', data['directUpload']['headers'] + assert_not_empty data['directUpload']['blobId'] + assert_not_empty data['directUpload']['url'] + assert_not_empty data['directUpload']['signedBlobId'] + end + test 'createDirectUpload mutation should not work with read api scope token' do result = IridaSchema.execute(CREATE_DIRECT_UPLOAD_MUTATION, context: { current_user: @user, token: @read_api_scope_token }, diff --git a/test/graphql/create_sample_mutation_test.rb b/test/graphql/create_sample_mutation_test.rb index 462f0bfdcc..92fc7cd4cd 100644 --- a/test/graphql/create_sample_mutation_test.rb +++ b/test/graphql/create_sample_mutation_test.rb @@ -77,6 +77,29 @@ def setup assert_equal 'New Sample Two Description', data['sample']['description'] end + test 'createSample mutation should work with valid params, project puid, and api scope token with uploader access level' do # rubocop:disable Layout/LineLength + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + project = projects(:project1) + + result = IridaSchema.execute(CREATE_SAMPLE_USING_PROJECT_PUID_MUTATION, + context: { current_user: user, token: }, + variables: { projectPuid: project.puid, + name: 'New Sample Two', + description: 'New Sample Two Description' }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['createSample'] + + assert_not_empty data, 'createSample should be populated when no authorization errors' + assert_empty data['errors'] + assert_not_empty data['sample'] + + assert_equal 'New Sample Two', data['sample']['name'] + assert_equal 'New Sample Two Description', data['sample']['description'] + end + test 'createSample mutation should not work with invalid params and api scope token' do project = projects(:project1) sample1 = samples(:sample1) @@ -114,6 +137,24 @@ def setup assert_equal 'You are not authorized to perform this action', error_message end + test 'createSample mutation should not work with valid params due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + project = projects(:project1) + + result = IridaSchema.execute(CREATE_SAMPLE_USING_PROJECT_ID_MUTATION, + context: { current_user: user, token: }, + variables: { projectId: project.to_global_id.to_s, + name: 'New Sample', + description: 'New Sample Description' }) + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal 'You are not authorized to create samples for project Project 1 on this server.', error_message + end + test 'createSample mutation should not work with unauthorized project and valid api scope token' do project = projects(:project1) sample1 = samples(:sample1) diff --git a/test/graphql/group_query_test.rb b/test/graphql/group_query_test.rb index fb0c2d5748..fd637e78b6 100644 --- a/test/graphql/group_query_test.rb +++ b/test/graphql/group_query_test.rb @@ -79,6 +79,24 @@ def setup assert_equal group.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'group query by puid should work with uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_valid_pat) + group = groups(:group_one) + + result = IridaSchema.execute(GROUP_QUERY_BY_PUID, context: { current_user: user, token: }, + variables: { groupPuid: group.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['group'] + + assert_not_empty data, 'group type should work' + assert_equal group.name, data['name'] + + assert_equal group.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'group query by full_path should work when not including parent descendants' do group = groups(:group_one) @@ -128,7 +146,7 @@ def setup assert_equal I18n.t('action_policy.policy.group.read?', name: group.name), error_message end - test 'group query should not return a result when unauthorized a' do + test 'group query should not return a result when user is not authorized to read the group due to no membership' do user = users(:user_no_access) group = groups(:david_doe_group_four) @@ -143,4 +161,21 @@ def setup assert_equal I18n.t('action_policy.policy.group.read?', name: group.name), error_message end + + test 'group query should not return a result when unauthorized due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + group = groups(:group_one) + + result = IridaSchema.execute(GROUP_QUERY_BY_FULL_PATH, context: { current_user: user, token: }, + variables: { groupPath: group.full_path }) + + assert_nil result['data']['group'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal I18n.t('action_policy.policy.group.read?', name: group.name), error_message + end end diff --git a/test/graphql/groups_query_test.rb b/test/graphql/groups_query_test.rb index 49bea75422..64825d9816 100644 --- a/test/graphql/groups_query_test.rb +++ b/test/graphql/groups_query_test.rb @@ -33,6 +33,20 @@ def setup assert_not_empty data['nodes'] end + test 'groups query should work with uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_valid_pat) + result = IridaSchema.execute(GROUPS_QUERY, context: { current_user: user, token: }, + variables: { first: 1 }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['groups'] + + assert_not_empty data, 'groups type should work' + assert_not_empty data['nodes'] + end + test 'groups query only returns scoped groups' do groups_via_namespace_group_links = Group.where(id: NamespaceGroupLink .where(group: @user.groups.self_and_descendants) @@ -54,4 +68,16 @@ def setup assert_equal groups_count, data['totalCount'] end + + test 'groups query should work but with errors due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + + result = IridaSchema.execute(GROUPS_QUERY, context: { current_user: user, token: }, + variables: { first: 20 }) + + assert_not_nil result['errors'], 'should work and have errors.' + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Group was hidden due to permissions', error_message + end end diff --git a/test/graphql/namespace_query_test.rb b/test/graphql/namespace_query_test.rb index 69be05a54b..db43520a54 100644 --- a/test/graphql/namespace_query_test.rb +++ b/test/graphql/namespace_query_test.rb @@ -36,6 +36,24 @@ def setup assert_equal namespace.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'namespace query should work for Group with uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_valid_pat) + namespace = groups(:group_one) + + result = IridaSchema.execute(NAMESPACE_QUERY, context: { current_user: user, token: }, + variables: { namespacePath: namespace.full_path }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['namespace'] + + assert_not_empty data, 'namespace type should work' + assert_equal namespace.name, data['name'] + + assert_equal namespace.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'namespace query should work for Namespaces::UserNamespace' do namespace = namespaces_user_namespaces(:john_doe_namespace) @@ -75,4 +93,21 @@ def setup assert_equal I18n.t('action_policy.policy.group.read?', name: namespace.name), error_message end + + test 'namespace query should not return a result when unauthorized due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + namespace = groups(:group_one) + + result = IridaSchema.execute(NAMESPACE_QUERY, context: { current_user: user, token: }, + variables: { namespacePath: namespace.full_path }) + + assert_nil result['data']['group'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal I18n.t('action_policy.policy.group.read?', name: namespace.name), error_message + end end diff --git a/test/graphql/node_query_test.rb b/test/graphql/node_query_test.rb index c1401d6613..e2487305b7 100644 --- a/test/graphql/node_query_test.rb +++ b/test/graphql/node_query_test.rb @@ -51,6 +51,22 @@ def setup assert_equal group.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'node query should work for group with uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_valid_pat) + group = groups(:group_one) + + result = IridaSchema.execute(NODE_QUERY, context: { current_user: user, token: }, + variables: { id: group.to_global_id.to_s }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['node'] + + assert_not_empty data, 'node type should work' + assert_equal group.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'node query should not return an unauthorized group' do @user = users(:user_no_access) group = groups(:david_doe_group_four) @@ -64,6 +80,20 @@ def setup assert_equal 'An object of type Group was hidden due to permissions', error_message end + test 'node query should not return an unauthorized group due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + group = groups(:group_one) + + result = IridaSchema.execute(NODE_QUERY, context: { current_user: user, token: }, + variables: { id: group.to_global_id.to_s }) + + assert_not_nil result['errors'], 'should not work and have errors.' + + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Group was hidden due to permissions', error_message + end + test 'node query for group should be able to return group attributes' do group = groups(:group_one) @@ -93,6 +123,22 @@ def setup assert_equal project.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'node query should work for project with uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + project = projects(:project1) + + result = IridaSchema.execute(NODE_QUERY, context: { current_user: user, token: }, + variables: { id: project.to_global_id.to_s }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['node'] + + assert_not_empty data, 'node type should work' + assert_equal project.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'node query should not return an unauthorized project' do project = projects(:project1) diff --git a/test/graphql/nodes_query_test.rb b/test/graphql/nodes_query_test.rb index b80d0ab818..a71b95ecd5 100644 --- a/test/graphql/nodes_query_test.rb +++ b/test/graphql/nodes_query_test.rb @@ -62,6 +62,22 @@ def setup assert_equal 1, data.length end + test 'nodes query should work when passed a list of group ids with uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_valid_pat) + group = groups(:group_one) + + result = IridaSchema.execute(NODES_QUERY, context: { current_user: user, token: }, + variables: { ids: [group.to_global_id.to_s] }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['nodes'] + + assert_not_empty data, 'nodes type should work' + assert_equal 1, data.length + end + test 'nodes query should not return an unauthorized group' do user = users(:user_no_access) group = groups(:david_doe_group_four) @@ -75,6 +91,20 @@ def setup assert_equal 'An object of type Group was hidden due to permissions', error_message end + test 'nodes query should not return an unauthorized group due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + group = groups(:group_one) + + result = IridaSchema.execute(NODES_QUERY, context: { current_user: user, token: }, + variables: { ids: [group.to_global_id.to_s] }) + + assert_not_nil result['errors'], 'should not work and have errors.' + + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Group was hidden due to permissions', error_message + end + test 'nodes query for group should be able to return group attributes' do group = groups(:group_one) @@ -105,6 +135,22 @@ def setup assert_equal 1, data.length end + test 'nodes query should work when passed a list of project ids with uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + project = projects(:project1) + + result = IridaSchema.execute(NODES_QUERY, context: { current_user: user, token: }, + variables: { ids: [project.to_global_id.to_s] }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['nodes'] + + assert_not_empty data, 'nodes type should work' + assert_equal 1, data.length + end + test 'nodes query should not return an unauthorized project' do project = projects(:project1) @@ -117,6 +163,20 @@ def setup assert_equal 'An object of type Project was hidden due to permissions', error_message end + test 'nodes query should not return an unauthorized project due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + project = projects(:project1) + + result = IridaSchema.execute(NODES_QUERY, context: { current_user: user, token: }, + variables: { ids: [project.to_global_id.to_s] }) + + assert_not_nil result['errors'], 'should not work and have errors.' + + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Project was hidden due to permissions', error_message + end + test 'nodes query should not return samples from an unauthorized project' do project = projects(:project1) @@ -129,6 +189,20 @@ def setup assert_equal 'An object of type Sample was hidden due to permissions', error_message end + test 'nodes query should not return samples from an unauthorized project due to expired token for uploader access level' do # rubocop:disable Layout/LineLength + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + project = projects(:project1) + + result = IridaSchema.execute(NODES_QUERY, context: { current_user: user, token: }, + variables: { ids: [project.samples[0].to_global_id.to_s] }) + + assert_not_nil result['errors'], 'should not work and have errors.' + + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Sample was hidden due to permissions', error_message + end + test 'nodes query for project should be able to return project attributes' do project = projects(:project1) diff --git a/test/graphql/project_query_test.rb b/test/graphql/project_query_test.rb index 2785b79bdf..f300961771 100644 --- a/test/graphql/project_query_test.rb +++ b/test/graphql/project_query_test.rb @@ -65,6 +65,24 @@ def setup assert_equal project.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'project query by puid should work when uploader access level' do + user = users(:user_bot_account0) + project = projects(:project1) + token = personal_access_tokens(:user_bot_account0_valid_pat) + + result = IridaSchema.execute(PROJECT_QUERY_BY_PUID, context: { current_user: user, token: }, + variables: { projectPuid: project.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['project'] + + assert_not_empty data, 'project type should work' + assert_equal project.name, data['name'] + + assert_equal project.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'project query should not return a result when unauthorized' do project = projects(:project1) @@ -79,4 +97,21 @@ def setup assert_equal I18n.t('action_policy.policy.project.read?', name: project.name), error_message end + + test 'project query should not return a result when unauthorized due to expired token for uploader access level' do + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + project = projects(:project1) + + result = IridaSchema.execute(PROJECT_QUERY_BY_FULL_PATH, context: { current_user: user, token: }, + variables: { projectPath: project.full_path }) + + assert_nil result['data']['project'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal I18n.t('action_policy.policy.project.read?', name: project.name), error_message + end end diff --git a/test/graphql/project_sample_query_test.rb b/test/graphql/project_sample_query_test.rb index 92004fea62..d433a4c166 100644 --- a/test/graphql/project_sample_query_test.rb +++ b/test/graphql/project_sample_query_test.rb @@ -65,6 +65,26 @@ def setup assert_equal sample.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'project sample query by sample puid should work for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + project = projects(:project1) + sample = samples(:sample1) + + result = IridaSchema.execute(PROJECT_SAMPLE_QUERY_BY_SAMPLE_PUID, context: { current_user: user, token: }, + variables: { projectPuid: project.puid, + samplePuid: sample.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['projectSample'] + + assert_not_empty data, 'sample type should work' + assert_equal sample.name, data['name'] + + assert_equal sample.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'project sample query should not return a result when unauthorized' do project = projects(:project1) sample = samples(:sample1) @@ -81,4 +101,23 @@ def setup assert_equal 'An object of type Sample was hidden due to permissions', error_message end + + test 'project sample query should not return a result when unauthorized due to expired token for uploader access level' do # rubocop:disable Layout/LineLength + user = users(:user_group_bot_account0) + token = personal_access_tokens(:user_group_bot_account0_expired_pat) + project = projects(:project1) + sample = samples(:sample1) + + result = IridaSchema.execute(PROJECT_SAMPLE_QUERY_BY_SAMPLE_PUID, context: { current_user: user, token: }, + variables: { projectPuid: project.puid, + samplePuid: sample.puid }) + + assert_nil result['data']['projectSample'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal 'An object of type Sample was hidden due to permissions', error_message + end end diff --git a/test/graphql/project_samples_query_test.rb b/test/graphql/project_samples_query_test.rb index 85a5ce22d1..5a67fd28d8 100644 --- a/test/graphql/project_samples_query_test.rb +++ b/test/graphql/project_samples_query_test.rb @@ -49,4 +49,47 @@ def setup assert_equal data['samples']['nodes'][index]['project']['id'], project.to_global_id.to_s end end + + test 'project with sample query should work for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + project = projects(:project1) + + result = IridaSchema.execute(PROJECT_QUERY, context: { current_user: user, token: }, + variables: { projectPath: project.full_path }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['project'] + + assert_not_empty data, 'project type should work' + assert_equal project.name, data['name'] + + assert_equal project.to_global_id.to_s, data['id'], 'id should be GlobalID' + assert_equal project.samples.count, data['samples']['nodes'].count + + # verify fetched sample data matches data on project + project.samples.each_with_index do |sample, index| + assert_equal data['samples']['nodes'][index]['id'], sample.to_global_id.to_s + assert_equal data['samples']['nodes'][index]['name'], sample.name + assert_equal data['samples']['nodes'][index]['project']['id'], project.to_global_id.to_s + end + end + + test 'project with sample query should not work for uploader access level with expired token' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + project = projects(:project1) + + result = IridaSchema.execute(PROJECT_QUERY, context: { current_user: user, token: }, + variables: { projectPath: project.full_path }) + + assert_nil result['data']['project'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal I18n.t('action_policy.policy.project.read?', name: project.name), error_message + end end diff --git a/test/graphql/projects_query_test.rb b/test/graphql/projects_query_test.rb index 85a013a2d0..9f93680594 100644 --- a/test/graphql/projects_query_test.rb +++ b/test/graphql/projects_query_test.rb @@ -33,6 +33,21 @@ def setup assert_not_empty data['nodes'] end + test 'projects query should work for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + + result = IridaSchema.execute(PROJECTS_QUERY, context: { current_user: user, token: }, + variables: { first: 1 }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['projects'] + + assert_not_empty data, 'projects type should work' + assert_not_empty data['nodes'] + end + test 'projects query only returns scoped projects' do policy = ProjectPolicy.new(user: @user) projects_count = policy.apply_scope(Project, type: :relation).count @@ -48,4 +63,17 @@ def setup assert_equal projects_count, data['totalCount'] end + + test 'projects query should work but with errors due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + + result = IridaSchema.execute(PROJECTS_QUERY, context: { current_user: user, token: }, + variables: { first: 20 }) + + assert_not_nil result['errors'], 'should work and have errors.' + error_message = result['errors'][0]['message'] + assert_equal 'An object of type Project was hidden due to permissions', + error_message + end end diff --git a/test/graphql/sample_query_test.rb b/test/graphql/sample_query_test.rb index a519cec3ba..a0110b0484 100644 --- a/test/graphql/sample_query_test.rb +++ b/test/graphql/sample_query_test.rb @@ -34,6 +34,25 @@ def setup assert_equal sample.to_global_id.to_s, data['id'], 'id should be GlobalID' end + test 'sample query should work for uploader access level' do + user = users(:user_bot_account0) + project = projects(:project1) + token = personal_access_tokens(:user_bot_account0_valid_pat) + sample = project.samples.first + + result = IridaSchema.execute(SAMPLE_QUERY, context: { current_user: user, token: }, + variables: { samplePuid: sample.puid }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['sample'] + + assert_not_empty data, 'sample type should work' + assert_equal sample.name, data['name'] + + assert_equal sample.to_global_id.to_s, data['id'], 'id should be GlobalID' + end + test 'sample query should not return a result when unauthorized' do project = projects(:project1) sample = project.samples.first @@ -49,4 +68,22 @@ def setup assert_equal 'An object of type Sample was hidden due to permissions', error_message end + + test 'sample query should not return a result when unauthorized due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + project = projects(:project1) + sample = project.samples.first + + result = IridaSchema.execute(SAMPLE_QUERY, context: { current_user: user, token: }, + variables: { samplePuid: sample.puid }) + + assert_nil result['data']['sample'] + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal 'An object of type Sample was hidden due to permissions', error_message + end end diff --git a/test/graphql/samples_query_test.rb b/test/graphql/samples_query_test.rb index 9b8a34ef74..53e11d3501 100644 --- a/test/graphql/samples_query_test.rb +++ b/test/graphql/samples_query_test.rb @@ -79,6 +79,21 @@ def setup assert_not_empty data['nodes'] end + test 'samples query should work for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + + result = IridaSchema.execute(SAMPLES_QUERY, context: { current_user: user, token: }, + variables: { first: 1 }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['samples'] + + assert_not_empty data, 'samples type should work' + assert_not_empty data['nodes'] + end + test 'group samples query should work' do result = IridaSchema.execute(GROUP_SAMPLES_QUERY, context: { current_user: @user }, variables: @@ -107,6 +122,24 @@ def setup assert_nil data end + test 'group samples query should throw authorization error due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + group = groups(:group_one) + result = IridaSchema.execute(GROUP_SAMPLES_QUERY, context: { current_user: user, token: }, + variables: + { group_id: group.to_global_id.to_s }) + + assert_not_nil result['errors'], 'should not work and have authorization errors.' + + assert_equal "You are not authorized to view samples for group #{group.name} on this server.", + result['errors'].first['message'] + + data = result['data']['samples'] + + assert_nil data + end + test 'sample and metadata fields query should work' do result = IridaSchema.execute(SAMPLE_AND_METADATA_QUERY, context: { current_user: @user }, variables: { sample_id: @sample32.to_global_id.to_s }) @@ -121,6 +154,22 @@ def setup assert data['metadata'].key?('metadatafield2') end + test 'sample and metadata fields query should not work due to expired token for uploader access level' do + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + result = IridaSchema.execute(SAMPLE_AND_METADATA_QUERY, context: { current_user: user, token: }, + variables: { sample_id: @sample.to_global_id.to_s }) + + assert_not_nil result['errors'], + 'shouldn\'t work and have errors.' + + assert_nil result['data']['sample'] + + error_message = result['errors'][0]['message'] + + assert_equal 'An object of type Sample was hidden due to permissions', error_message + end + test 'sample and metadata fields query should be able to limit to a specific set of keys' do result = IridaSchema.execute(SAMPLE_AND_LIMITED_METADATA_QUERY, context: { current_user: @user }, diff --git a/test/graphql/update_sample_metadata_test.rb b/test/graphql/update_sample_metadata_test.rb index ecb8f6489f..84a978ca17 100644 --- a/test/graphql/update_sample_metadata_test.rb +++ b/test/graphql/update_sample_metadata_test.rb @@ -82,6 +82,29 @@ def setup assert_equal 'value1', data['sample']['metadata']['key1'] end + test 'updateSampleMetadata mutation should work with valid params, puid, and api scope token with uploader access level' do # rubocop:disable Layout/LineLength + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_valid_pat) + result = IridaSchema.execute(UPDATE_SAMPLE_METADATA_BY_SAMPLE_PUID_MUTATION, + context: { current_user: user, token: }, + variables: { samplePuid: @sample.puid, + metadata: { key1: 'value1' } }) + + assert_nil result['errors'], 'should work and have no errors.' + + data = result['data']['updateSampleMetadata'] + + assert_not_empty data, 'updateSampleMetadata should be populated when no authorization errors' + assert_empty data['errors'] + assert_not_empty data['status'] + assert_not_empty data['status'][:added] + assert_equal 'key1', data['status'][:added].first + assert_not_empty data['sample'] + assert_not_empty data['sample']['metadata'] + assert_not_empty data['sample']['metadata']['key1'] + assert_equal 'value1', data['sample']['metadata']['key1'] + end + test 'updateSampleMetadata mutation should error with empty metadata params and api scope token' do result = IridaSchema.execute(UPDATE_SAMPLE_METADATA_BY_SAMPLE_ID_MUTATION, context: { current_user: @user, token: @api_scope_token }, @@ -130,4 +153,20 @@ def setup assert_equal I18n.t(:'action_policy.policy.project.update_sample?', name: @sample.project.name), error_message end + + test 'updateSampleMetadata mutation should not work with valid params due to expired token for uploader access level' do # rubocop:disable Layout/LineLength + user = users(:user_bot_account0) + token = personal_access_tokens(:user_bot_account0_expired_pat) + + result = IridaSchema.execute(UPDATE_SAMPLE_METADATA_BY_SAMPLE_ID_MUTATION, + context: { current_user: user, token: }, + variables: { sampleId: @sample.to_global_id.to_s, + metadata: { key1: 'value1' } }) + + assert_not_nil result['errors'], 'shouldn\'t work and have errors.' + + error_message = result['errors'][0]['message'] + + assert_equal 'You are not authorized to update samples for project Project 1 on this server.', error_message + end end diff --git a/test/models/namespace_bot_test.rb b/test/models/namespace_bot_test.rb index 8b17286ca4..762c94ccf3 100644 --- a/test/models/namespace_bot_test.rb +++ b/test/models/namespace_bot_test.rb @@ -29,7 +29,7 @@ def setup assert_difference( -> { NamespaceBot.count } => -1, -> { User.count } => -1, - -> { PersonalAccessToken.count } => -1, + -> { PersonalAccessToken.count } => -2, -> { Member.count } => -1 ) do namespace_bot.destroy diff --git a/test/services/bots/destroy_service_test.rb b/test/services/bots/destroy_service_test.rb index 7f99ac3c32..c7cb36a20f 100644 --- a/test/services/bots/destroy_service_test.rb +++ b/test/services/bots/destroy_service_test.rb @@ -17,7 +17,7 @@ def setup assert_difference -> { NamespaceBot.count } => -1, -> { User.count } => -1, - -> { PersonalAccessToken.count } => -1, + -> { PersonalAccessToken.count } => -2, -> { Member.count } => -1 do Bots::DestroyService.new(@project_bot, @user).execute end @@ -53,7 +53,7 @@ def setup assert_difference -> { NamespaceBot.count } => -1, -> { User.count } => -1, - -> { PersonalAccessToken.count } => -1, + -> { PersonalAccessToken.count } => -2, -> { Member.count } => -1 do Bots::DestroyService.new(@group_bot, @user).execute end diff --git a/test/system/dashboard/projects_test.rb b/test/system/dashboard/projects_test.rb index 2d29b59b81..efa16e99f6 100644 --- a/test/system/dashboard/projects_test.rb +++ b/test/system/dashboard/projects_test.rb @@ -141,6 +141,7 @@ def setup assert_no_text I18n.t(:'dashboard.projects.index.sorting.updated_at_desc') assert_text I18n.t(:'dashboard.projects.index.sorting.namespace_name_desc') + assert_text 'Displaying items 1-20 of 38 in total' assert_selector 'tr', count: 20 within first('tr') do assert_text projects(:projectHotel).human_name @@ -148,6 +149,7 @@ def setup fill_in I18n.t(:'dashboard.projects.index.search.placeholder'), with: projects(:project1).name + assert_text 'Displaying 12 items' assert_selector 'tr', count: 12 assert_no_selector 'a', text: /\A#{I18n.t(:'components.pagination.next')}\Z/ assert_no_selector 'a', text: I18n.t(:'components.pagination.previous') diff --git a/test/system/groups/bots_test.rb b/test/system/groups/bots_test.rb index f360d6e5e0..727ac94e3c 100644 --- a/test/system/groups/bots_test.rb +++ b/test/system/groups/bots_test.rb @@ -150,6 +150,7 @@ def setup test 'can view personal access tokens for bot account' do namespace_bot = namespace_bots(:group1_bot0) + active_personal_tokens = namespace_bot.user.personal_access_tokens.active visit group_bots_path(@namespace) assert_selector 'h1', text: I18n.t(:'groups.bots.index.title') @@ -158,7 +159,7 @@ def setup table_row = find(:table_row, { 'Username' => namespace_bot.user.email }) within table_row do - click_link namespace_bot.user.personal_access_tokens.count.to_s + click_link active_personal_tokens.count.to_s end within('dialog') do @@ -171,7 +172,7 @@ def setup within('table') do assert_selector 'tr', count: 2 - token = namespace_bot.user.personal_access_tokens.first + token = active_personal_tokens.first table_row = find(:table_row, { 'Token name' => token.name }) @@ -233,6 +234,7 @@ def setup test 'can revoke a personal access token' do namespace_bot = namespace_bots(:group1_bot0) + active_personal_tokens = namespace_bot.user.personal_access_tokens.active token = nil visit group_bots_path(@namespace) @@ -242,7 +244,7 @@ def setup table_row = find(:table_row, { 'Username' => namespace_bot.user.email }) within table_row do - click_link namespace_bot.user.personal_access_tokens.count.to_s + click_link active_personal_tokens.count.to_s end within('dialog') do @@ -255,7 +257,7 @@ def setup within('table') do assert_selector 'tr', count: 2 - token = namespace_bot.user.personal_access_tokens.first + token = active_personal_tokens.first table_row = find(:table_row, { 'Token name' => token.name }) diff --git a/test/system/projects/bots_test.rb b/test/system/projects/bots_test.rb index 35123f619a..22359feac9 100644 --- a/test/system/projects/bots_test.rb +++ b/test/system/projects/bots_test.rb @@ -152,6 +152,7 @@ def setup test 'can view personal access tokens for bot account' do namespace_bot = namespace_bots(:project1_bot0) + active_personal_tokens = namespace_bot.user.personal_access_tokens.active visit namespace_project_bots_path(@namespace, @project) assert_selector 'h1', text: I18n.t(:'projects.bots.index.title') @@ -160,7 +161,7 @@ def setup table_row = find(:table_row, { 'Username' => namespace_bot.user.email }) within table_row do - click_link namespace_bot.user.personal_access_tokens.count.to_s + click_link active_personal_tokens.count.to_s end within('dialog') do @@ -173,7 +174,7 @@ def setup within('table') do assert_selector 'tr', count: 2 - token = namespace_bot.user.personal_access_tokens.first + token = active_personal_tokens.first table_row = find(:table_row, { 'Token name' => token.name }) @@ -235,6 +236,7 @@ def setup test 'can revoke a personal access token' do namespace_bot = namespace_bots(:project1_bot0) + active_personal_tokens = namespace_bot.user.personal_access_tokens.active token = nil visit namespace_project_bots_path(@namespace, @project) @@ -244,7 +246,7 @@ def setup table_row = find(:table_row, { 'Username' => namespace_bot.user.email }) within table_row do - click_link namespace_bot.user.personal_access_tokens.count.to_s + click_link active_personal_tokens.count.to_s end within('dialog') do @@ -257,7 +259,7 @@ def setup within('table') do assert_selector 'tr', count: 2 - token = namespace_bot.user.personal_access_tokens.first + token = active_personal_tokens.first table_row = find(:table_row, { 'Token name' => token.name })