Commit b1aa39ff authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents abef8f4d 55d94517
......@@ -122,7 +122,7 @@ export default {
</p>
<gl-tabs sync-active-tab-with-query-params lazy>
<slot name="ee-security-tab"></slot>
<slot name="ee-security-tab" :cluster-agent-id="clusterAgent.id"></slot>
<gl-tab :title="$options.i18n.activity" query-param-value="activity">
<activity-events :agent-name="agentName" :project-path="projectPath" />
......
......@@ -101,7 +101,7 @@ a license, upload the license in the **Admin Area** in the web user interface.
## What happens when your license expires
One month before the license expires, a message with the upcoming expiration
Fifteen days before the license expires, a message with the upcoming expiration
date displays to GitLab administrators.
When your license expires, GitLab locks features, like Git pushes
......
......@@ -27,9 +27,9 @@ export default {
<template>
<agent-show-page>
<template v-if="showSecurityTab" #ee-security-tab>
<template v-if="showSecurityTab" #ee-security-tab="{ clusterAgentId }">
<gl-tab :title="$options.i18n.securityTabTitle">
<agent-vulnerability-report />
<agent-vulnerability-report :cluster-agent-id="clusterAgentId" />
</gl-tab>
</template>
</agent-show-page>
......
......@@ -34,23 +34,26 @@ export default {
};
},
inject: ['projectPath'],
props: {
clusterAgentId: {
type: String,
required: true,
},
},
data() {
return {
graphqlFilters: undefined,
graphqlFilters: { clusterAgentId: [this.clusterAgentId] },
};
},
computed: {
filtersToShow() {
return FILTER_PRESETS[REPORT_TAB.OPERATIONAL];
},
},
methods: {
updateGraphqlFilters(graphqlFilters) {
this.graphqlFilters = graphqlFilters;
this.graphqlFilters.reportType = REPORT_TYPE_PRESETS.OPERATIONAL;
this.graphqlFilters.clusterAgentId = [this.clusterAgentId];
},
},
fieldsToShow: FIELD_PRESETS[REPORT_TAB.OPERATIONAL],
filtersToShow: FILTER_PRESETS[REPORT_TAB.OPERATIONAL],
REPORT_TAB,
projectVulnerabilitiesQuery,
};
......@@ -59,7 +62,7 @@ export default {
<template>
<div>
<vulnerability-filters
:filters="filtersToShow"
:filters="$options.filtersToShow"
class="security-dashboard-filters gl-mt-7"
@filters-changed="updateGraphqlFilters"
/>
......
......@@ -14,6 +14,7 @@ query projectVulnerabilities(
$hasResolution: Boolean
$includeExternalIssueLinks: Boolean = false
$vetEnabled: Boolean = false
$clusterAgentId: [ClustersAgentID!]
) {
project(fullPath: $fullPath) {
id
......@@ -28,6 +29,7 @@ query projectVulnerabilities(
sort: $sort
hasIssues: $hasIssues
hasResolution: $hasResolution
clusterAgentId: $clusterAgentId
) {
nodes {
...VulnerabilityFragment
......
......@@ -11,6 +11,9 @@ class License < ApplicationRecord
LICENSE_FILE_TYPE = 'license_file'
ALLOWED_PERCENTAGE_OF_USERS_OVERAGE = (10 / 100.0)
NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY = 1.week
ADMIN_NOTIFICATION_DAYS_BEFORE_EXPIRY = 15.days
EE_ALL_PLANS = [STARTER_PLAN, PREMIUM_PLAN, ULTIMATE_PLAN].freeze
EES_FEATURES_WITH_USAGE_PING = %i[
......@@ -623,6 +626,22 @@ class License < ApplicationRecord
super || created_at
end
# Overrides method from Gitlab::License which will be removed in a future version
def notify_admins?
return true if expired?
notification_days = trial? ? NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY : ADMIN_NOTIFICATION_DAYS_BEFORE_EXPIRY
Date.today >= (expires_at - notification_days)
end
# Overrides method from Gitlab::License which will be removed in a future version
def notify_users?
notification_start_date = trial? ? expires_at - NOTIFICATION_DAYS_BEFORE_TRIAL_EXPIRY : block_changes_at
Date.today >= notification_start_date
end
private
def restricted_attr(name, default = nil)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Expiring Subscription Message', :js, :freeze_time do
context 'for self-managed subscriptions' do
context 'when signed in user is an admin' do
let_it_be(:admin) { create(:admin) }
before do
create_current_license(plan: License::ULTIMATE_PLAN, expires_at: expires_at)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
end
context 'with an expired license' do
let(:expires_at) { Date.current - 1.day }
it 'notifies the admin of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
context 'with a license expiring in 15 days' do
let(:expires_at) { Date.current + 15.days }
it 'notifies the admin of a soon expiring subscription' do
expect(page).to have_content('Your subscription will expire in 15 days')
end
end
context 'with a license expiring in more than 15 days' do
let(:expires_at) { Date.current + 16.days }
it 'does not notify the admin of an expiring subscription' do
expect(page).not_to have_content('Your subscription will expire')
end
end
end
context 'when signed in user is not an admin' do
let_it_be(:user) { create(:user) }
before do
create_current_license(plan: License::ULTIMATE_PLAN, expires_at: expires_at, block_changes_at: block_changes_at)
sign_in(user)
visit root_path
end
context 'with an expired license in the grace period' do
let(:expires_at) { Date.current - 1.day }
let(:block_changes_at) { Date.current + 13.days }
it 'notifies the admin of the expired subscription' do
expect(page).not_to have_content('Your subscription expired!')
end
end
context 'with an expired license beyond the grace period' do
let(:expires_at) { Date.current - 15.days }
let(:block_changes_at) { Date.current - 1.day }
it 'notifies the admin of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
end
end
context 'for namespace subscriptions', :saas do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
before do
enable_namespace_license_check!
create(:gitlab_subscription, namespace: group, end_date: end_date, auto_renew: false)
allow_next_instance_of(GitlabSubscriptions::CheckFutureRenewalService, namespace: group) do |service|
allow(service).to receive(:execute).and_return(false)
end
end
context 'when signed in user is a group owner' do
before do
group.add_owner(user)
sign_in(user)
visit group_path(group)
end
context 'with an expired license' do
let(:end_date) { Date.current - 1.day }
it 'notifies the group owner of the expired subscription' do
expect(page).to have_content('Your subscription expired!')
end
end
context 'with a license expiring in less than 30 days' do
let(:end_date) { Date.current + 29.days }
it 'notifies the group owner of a soon expiring subscription' do
expect(page).to have_content('Your subscription will expire in 29 days')
end
end
context 'with a license expiring in 30 or more days' do
let(:end_date) { Date.current + 30.days }
it 'does not notify the group owner of an expiring subscription' do
expect(page).not_to have_content('Your subscription will expire')
end
end
end
context 'when signed in user is not a group owner' do
before do
group.add_developer(user)
sign_in(user)
visit group_path(group)
end
context 'with an expired license' do
let(:end_date) { Date.current - 1.day }
it 'does not notify the user of the expired subscription' do
expect(page).not_to have_content('Your subscription expired!')
end
end
context 'with a license expiring in less than 30 days' do
let(:end_date) { Date.current + 29.days }
it 'does not notify the user of a soon expiring subscription' do
expect(page).not_to have_content('Your subscription will expire')
end
end
end
end
end
import { GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ClusterAgentShow from 'ee/clusters/agents/components/show.vue';
import AgentShowPage from '~/clusters/agents/components/show.vue';
import AgentVulnerabilityReport from 'ee/security_dashboard/components/agent/agent_vulnerability_report.vue';
describe('ClusterAgentShow', () => {
let wrapper;
const clusterAgentId = 'gid://gitlab/Clusters::Agent/1';
const AgentShowPageStub = stubComponent(AgentShowPage, {
provide: { agentName: 'test', projectPath: 'test' },
template: `<div><slot name="ee-security-tab" clusterAgentId="${clusterAgentId}"></slot></div>`,
});
const createWrapper = ({ glFeatures = {} } = {}) => {
wrapper = extendedWrapper(
shallowMount(ClusterAgentShow, {
provide: { glFeatures },
stubs: {
AgentShowPage: AgentShowPageStub,
},
}),
);
};
const findAgentVulnerabilityReport = () => wrapper.findComponent(AgentVulnerabilityReport);
const findTab = () => wrapper.findComponent(GlTab);
afterEach(() => {
......@@ -34,4 +47,14 @@ describe('ClusterAgentShow', () => {
expect(findTab().exists()).toBe(tabStatus);
});
});
describe('vulnerability report', () => {
it('renders with cluster agent id', async () => {
createWrapper({
glFeatures: { clusterVulnerabilities: true, kubernetesClusterVulnerabilities: true },
});
await nextTick();
expect(findAgentVulnerabilityReport().props('clusterAgentId')).toBe(clusterAgentId);
});
});
});
......@@ -9,6 +9,7 @@ exports[`Agent vulnerability report component renders 1`] = `
<vulnerability-list-graphql-stub
fields="[object Object],[object Object],[object Object],[object Object],,[object Object]"
filters="[object Object]"
query="[object Object]"
/>
</div>
......
......@@ -4,10 +4,11 @@ import AgentVulnerabilityReport from 'ee/security_dashboard/components/agent/age
describe('Agent vulnerability report component', () => {
let wrapper;
const propsData = { clusterAgentId: 'gid://gitlab/Clusters::Agent/1' };
const provide = { agentName: 'primary-agent', projectPath: '/path/to/project/' };
const createWrapper = () => {
wrapper = shallowMount(AgentVulnerabilityReport, { provide });
wrapper = shallowMount(AgentVulnerabilityReport, { propsData, provide });
};
afterEach(() => {
......
......@@ -1623,4 +1623,134 @@ RSpec.describe License do
it { is_expected.to eq(license.created_at) }
end
end
describe '#notify_admins?', :freeze_time do
subject(:notify_admins?) { license.notify_admins? }
context 'when license has expired' do
before do
gl_license.expires_at = Date.yesterday
end
it { is_expected.to eq(true) }
end
context 'when license has not expired' do
context 'when license is a trial' do
before do
gl_license.restrictions = { trial: true }
end
context 'when license expiration is more than a week from today' do
before do
gl_license.expires_at = Date.today + 8.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is a week from today' do
before do
gl_license.expires_at = Date.today + 7.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than a week from today' do
before do
gl_license.expires_at = Date.today + 6.days
end
it { is_expected.to eq(true) }
end
end
context 'when license is not a trial' do
context 'when license expiration is more than 15 days from today' do
before do
gl_license.expires_at = Date.today + 16.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is 15 days from today' do
before do
gl_license.expires_at = Date.today + 15.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than 15 days from today' do
before do
gl_license.expires_at = Date.today + 14.days
end
it { is_expected.to eq(true) }
end
end
end
end
describe '#notify_users?', :freeze_time do
subject(:notify_users?) { license.notify_users? }
context 'when license is a trial' do
before do
gl_license.restrictions = { trial: true }
end
context 'when license expiration is more than a week from today' do
before do
gl_license.expires_at = Date.today + 8.days
end
it { is_expected.to eq(false) }
end
context 'when license expiration is a week from today' do
before do
gl_license.expires_at = Date.today + 7.days
end
it { is_expected.to eq(true) }
end
context 'when license expiration is less than a week from today' do
before do
gl_license.expires_at = Date.today + 6.days
end
it { is_expected.to eq(true) }
end
end
context 'when license is not a trial' do
context 'when license block changes date is before today' do
before do
gl_license.block_changes_at = Date.today - 1.day
end
it { is_expected.to eq(true) }
end
context 'when license block changes date is today' do
before do
gl_license.block_changes_at = Date.today
end
it { is_expected.to eq(true) }
end
context 'when license block changes date is after today' do
before do
gl_license.block_changes_at = Date.today + 1.day
end
it { is_expected.to eq(false) }
end
end
end
end
......@@ -414,7 +414,7 @@ module QA
end
def remove_tracked_praefect_repository(relative_path, virtual_storage)
cmd = "gitlab-ctl praefect remove-repository --repository-relative-path #{relative_path} --virtual-storage-name #{virtual_storage}"
cmd = "gitlab-ctl praefect remove-repository --repository-relative-path #{relative_path} --virtual-storage-name #{virtual_storage} --apply"
shell "docker exec #{@praefect} bash -c '#{cmd}'"
end
......
......@@ -22,7 +22,7 @@ module QA
praefect_manager.remove_repository_from_praefect_database(repo2["relative_path"])
end
it 'allows admin to manage difference between praefect database and disk state', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347606', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347415', type: :investigating } do
it 'allows admin to manage difference between praefect database and disk state', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347606' do
# Some repos are on disk that praefect is not aware of
untracked_repositories = praefect_manager.list_untracked_repositories
expect(untracked_repositories).to include(repo1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment