From 43c39fa47e7d77c83ada46f8429db23cfcb2f87e Mon Sep 17 00:00:00 2001 From: mo khan <mo@mokhan.ca> Date: Sat, 4 Nov 2023 05:14:14 +0000 Subject: [PATCH] Add custom role spec for `Mutation.vulnerabilityCreate` --- ee/spec/factories/member_roles.rb | 1 - .../mutations/vulnerabilities/confirm_spec.rb | 2 +- .../mutations/vulnerabilities/create_spec.rb | 159 ++++++++++++++++++ .../mutations/vulnerabilities/resolve_spec.rb | 2 +- .../admin_vulnerability/request_spec.rb | 52 ++++-- spec/support/helpers/graphql_helpers.rb | 1 + 6 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 ee/spec/requests/api/graphql/mutations/vulnerabilities/create_spec.rb diff --git a/ee/spec/factories/member_roles.rb b/ee/spec/factories/member_roles.rb index 0f52f0278b288..9132fde33640a 100644 --- a/ee/spec/factories/member_roles.rb +++ b/ee/spec/factories/member_roles.rb @@ -10,7 +10,6 @@ trait(:guest) { base_access_level { Gitlab::Access::GUEST } } trait :admin_vulnerability do - guest admin_vulnerability { true } read_vulnerability { true } end diff --git a/ee/spec/requests/api/graphql/mutations/vulnerabilities/confirm_spec.rb b/ee/spec/requests/api/graphql/mutations/vulnerabilities/confirm_spec.rb index 91e6aa73d6412..6eb7e17947c1f 100644 --- a/ee/spec/requests/api/graphql/mutations/vulnerabilities/confirm_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/vulnerabilities/confirm_spec.rb @@ -27,7 +27,7 @@ end context "with `admin_vulnerability` enabled" do - let(:role) { create(:member_role, :admin_vulnerability, namespace: project.group) } + let(:role) { create(:member_role, :guest, :admin_vulnerability, namespace: project.group) } it "returns a successful response" do post_graphql_mutation(mutation, current_user: current_user) diff --git a/ee/spec/requests/api/graphql/mutations/vulnerabilities/create_spec.rb b/ee/spec/requests/api/graphql/mutations/vulnerabilities/create_spec.rb new file mode 100644 index 0000000000000..ca1dc83bb15e7 --- /dev/null +++ b/ee/spec/requests/api/graphql/mutations/vulnerabilities/create_spec.rb @@ -0,0 +1,159 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Mutation.vulnerabilityCreate", feature_category: :vulnerability_management do + include GraphqlHelpers + + subject(:mutation) { graphql_mutation(:vulnerability_create, arguments) } + + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project, :in_group) } + let(:arguments) do + { + project: project.to_global_id, + name: "Test vulnerability", + description: "Test vulnerability created via GraphQL", + scanner: { + id: "my-custom-scanner", + name: "My Custom Scanner", + url: "https://superscanner.com", + vendor: { name: "Custom Scanner Vendor" }, + version: "21.37.00" + }, + identifiers: [{ + name: "Test identifier", + url: "https://vulnerabilities.com/test" + }], + state: "DETECTED", + severity: "UNKNOWN", + confidence: "UNKNOWN", + solution: "rm -rf --no-preserve-root /", + message: "You can't fix this" + } + end + + let(:mutation_response) { graphql_mutation_response(:vulnerability_create) } + + context "with a Maintainer role" do + let(:at) { Time.new(2020, 6, 21, 14, 22, 20) } + + before_all do + project.add_maintainer(current_user) + end + + before do + stub_licensed_features(security_dashboard: true) + end + + it "returns a successful response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["vulnerability"]["state"]).to eq("DETECTED") + expect(mutation_response["vulnerability"]["description"]).to eq(arguments[:description]) + expect(mutation_response["vulnerability"]["solution"]).to eq(arguments[:solution]) + expect(mutation_response["errors"]).to be_empty + end + + context "when confirming a vulnerability" do + let(:arguments) { super().merge(state: "CONFIRMED", confirmed_at: at) } + + it "returns a successful response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["vulnerability"]["state"]).to eq("CONFIRMED") + expect(mutation_response["vulnerability"]["confirmedAt"]).to eq(at.utc.iso8601) + expect(mutation_response.dig("vulnerability", "confirmedBy", "id")).to eq(current_user.to_global_id.to_s) + expect(mutation_response["errors"]).to be_empty + end + end + + context "when resolving a vulnerability" do + let(:arguments) { super().merge(state: "RESOLVED", resolved_at: at) } + + it "returns a successful response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["vulnerability"]["state"]).to eq("RESOLVED") + expect(mutation_response["vulnerability"]["resolvedAt"]).to eq(at.utc.iso8601) + expect(mutation_response.dig("vulnerability", "resolvedBy", "id")).to eq(current_user.to_global_id.to_s) + expect(mutation_response["errors"]).to be_empty + end + end + + context "when dismissing a vulnerability" do + let(:arguments) { super().merge(state: "DISMISSED", dismissed_at: at) } + + it "returns a successful response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["vulnerability"]["state"]).to eq("DISMISSED") + expect(mutation_response["vulnerability"]["dismissedAt"]).to eq(at.utc.iso8601) + expect(mutation_response.dig("vulnerability", "dismissedBy", "id")).to eq(current_user.to_global_id.to_s) + expect(mutation_response["errors"]).to be_empty + end + end + end + + context "with an unauthorized role" do + before_all do + project.add_guest(current_user) + end + + before do + stub_licensed_features(security_dashboard: true) + end + + it "returns an empty response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response).to be_blank + end + + it "does not create a new vulnerability" do + expect do + post_graphql_mutation(mutation, current_user: current_user) + end.not_to change { Vulnerability.count } + end + end + + context "with a custom role" do + let!(:membership) { create(:project_member, :guest, user: current_user, source: project, member_role: role) } + + before do + stub_licensed_features(security_dashboard: true, custom_roles: true) + end + + context "with `admin_vulnerability` enabled" do + let(:role) { create(:member_role, :guest, :admin_vulnerability, namespace: project.group) } + + it "returns a successful response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["errors"]).to be_empty + end + end + + context "with `admin_vulnerability` disabled" do + let(:role) { create(:member_role, :guest, namespace: project.group) } + + it "returns an empty response" do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response).to be_nil + end + end + end +end diff --git a/ee/spec/requests/api/graphql/mutations/vulnerabilities/resolve_spec.rb b/ee/spec/requests/api/graphql/mutations/vulnerabilities/resolve_spec.rb index a62894e5b636c..9ec8a5d9edd94 100644 --- a/ee/spec/requests/api/graphql/mutations/vulnerabilities/resolve_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/vulnerabilities/resolve_spec.rb @@ -26,7 +26,7 @@ end context "with `admin_vulnerability` enabled" do - let(:role) { create(:member_role, :admin_vulnerability, namespace: project.group) } + let(:role) { create(:member_role, :guest, :admin_vulnerability, namespace: project.group) } it "returns a successful response" do post_graphql_mutation(mutation, current_user: current_user) diff --git a/ee/spec/requests/custom_roles/admin_vulnerability/request_spec.rb b/ee/spec/requests/custom_roles/admin_vulnerability/request_spec.rb index 29eb7bb8ee025..4e834dbe6e4ed 100644 --- a/ee/spec/requests/custom_roles/admin_vulnerability/request_spec.rb +++ b/ee/spec/requests/custom_roles/admin_vulnerability/request_spec.rb @@ -5,25 +5,18 @@ RSpec.describe 'User with admin_vulnerability custom role', feature_category: :system_access do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :repository, :in_group) } - let_it_be(:vulnerability) { create(:vulnerability, :with_finding, project: project) } + let_it_be(:role) { create(:member_role, :guest, :admin_vulnerability, namespace: project.group) } + let_it_be(:membership) { create(:group_member, :guest, user: user, source: project.group, member_role: role) } before do stub_licensed_features(custom_roles: true, security_dashboard: true) - - group_member = create(:group_member, :guest, user: user, source: project.group) - create( - :member_role, - :guest, - admin_vulnerability: true, - read_code: false, - read_vulnerability: true, - members: [group_member], - namespace: project.group - ) - sign_in(user) end describe Projects::Security::VulnerabilitiesController do + before do + sign_in(user) + end + describe "#new" do it 'user has access via a custom role' do get new_project_security_vulnerability_path(project) @@ -35,4 +28,37 @@ end end end + + describe Mutations::Vulnerabilities::Create do + include GraphqlHelpers + + it "has access via a custom role" do + post_graphql_mutation(graphql_mutation(:vulnerability_create, { + project: project.to_global_id, + name: "example", + description: "example", + scanner: { + id: "my-custom-scanner", + name: "example", + url: "https://example.org", + vendor: { name: "example" }, + version: "1.0.0" + }, + identifiers: [{ + name: "example", + url: "https://example.org/example" + }], + state: "DETECTED", + severity: "UNKNOWN", + confidence: "UNKNOWN", + solution: "curl -s 'https://unpkg.com/emoji.json@13.1.0/emoji.json' | jq -r '.[] | .char'", + message: "example" + }), current_user: user) + + expect(response).to have_gitlab_http_status(:success) + mutation_response = graphql_mutation_response(:vulnerability_create) + expect(mutation_response["vulnerability"]).to be_present + expect(mutation_response["errors"]).to be_empty + end + end end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index 5eba982e3da70..085340d6cb96c 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -2,6 +2,7 @@ module GraphqlHelpers def self.included(base) + base.include(::ApiHelpers) base.include(::Gitlab::Graphql::Laziness) end -- GitLab