Commit b783387a authored by Douwe Maan's avatar Douwe Maan

Merge branch '2501-trial-and-license-purchases-inside-gitlab-ee' into 'master'

Trial and license purchases inside GitLab EE

Closes #2500

See merge request !2266
parents 1f1a183a 0a42967a
import Cookies from 'js-cookie';
export default class EETrialBanner {
constructor($trialBanner) {
this.COOKIE_KEY = 'show_ee_trial_banner';
this.$trialBanner = $trialBanner;
this.$mainNavbar = this.$trialBanner.siblings('.js-navbar-gitlab');
this.$secondaryNavbar = this.$mainNavbar.siblings('.js-page-with-sidebar');
this.licenseExpiresOn = new Date(this.$trialBanner.data('license-expiry'));
}
init() {
// Wait for navbars to render before querying
this.setCookies();
this.$trialBanner.on('close.bs.alert', e => this.handleTrialBannerDismiss(e));
}
/**
* Trial Expiring/Expired Banner has two stages;
* 1. Show banner when user enters last 7 days of trial
* 2. Show banner again when last 7 days are over and license has expired
*
* Stage 1:
* Banner is showed when `trial_license_message` is sent by backend
* for the first time (in `app/views/layouts/header/_default.html.haml`).
* Here, we perform following steps;
*
* 1. Set cookie `show_ee_trial_banner` with expiry same as license
* 2. Set cookie value to `true`
* 3. Show banner using `toggleBanner(true)`
*
* At this stage, if user dismisses banner, we set cookie value to `false`
* and everytime page is initialized, we check for cookie existence as
* well as its value, and decide show/hide status of banner
*
* Stage 2:
* At this point, Cookie we had set earlier will be expired and
* backend will now send updated message in `trial_license_message`.
* Here, we perform following steps;
*
* 1. Check if cookie is defined (it'll not be defined as it is expired now)
* 2. If cookie is gone, we re-set `show_ee_trial_banner` cookie but with
* expiry of 20 years
* 3. Set cookie value to `true`
* 4. Show banner using `toggleBanner(true)`, which now has updated message
*
* At this stage, if user dismisses banner, we set cookie value to `false`
* and our existing logic of show/hide banner based on cookie value continues
* to work. And since, cookie is set to expire after 20 years, user won't be
* seeing banner again.
*/
setCookies() {
const today = new Date();
// Check if Cookie is defined
if (!Cookies.get(this.COOKIE_KEY)) {
// Cookie was not defined, let's define with default value
// Check if License is yet to expire
if (today < this.licenseExpiresOn) {
// License has not expired yet, we show initial banner of 7 days
// with cookie set to validity same as license expiry
Cookies.set(this.COOKIE_KEY, 'true', { expires: this.licenseExpiresOn });
} else {
// License is already expired so we show final Banner with cookie set to 20 years validity.
Cookies.set(this.COOKIE_KEY, 'true', { expires: 7300 });
}
this.toggleBanner(true);
} else {
// Cookie was defined, let's read value and show/hide banner
this.toggleBanner(Cookies.get(this.COOKIE_KEY) === 'true');
}
}
toggleMainNavbarMargin(state) {
if (this.$mainNavbar.length) {
this.$mainNavbar.toggleClass('has-trial-banner', state);
}
}
toggleSecondaryNavbarMargin(state) {
if (this.$secondaryNavbar.length) {
this.$secondaryNavbar.toggleClass('has-trial-banner', state);
}
}
toggleBanner(state) {
this.$trialBanner.toggleClass('hidden', !state);
this.toggleMainNavbarMargin(state);
this.toggleSecondaryNavbarMargin(state);
}
handleTrialBannerDismiss() {
this.toggleMainNavbarMargin(false);
this.toggleSecondaryNavbarMargin(false);
if (Cookies.get(this.COOKIE_KEY)) {
Cookies.set(this.COOKIE_KEY, 'false');
}
}
}
import EETrialBanner from './ee_trial_banner';
$(() => {
const $trialBanner = $('.js-gitlab-ee-license-banner');
if ($trialBanner.length) {
const eeTrialBanner = new EETrialBanner($trialBanner);
eeTrialBanner.init();
}
});
......@@ -150,6 +150,7 @@ import './syntax_highlight';
import './admin_email_select';
import './application_settings';
import './approvals';
import './ee_trial_banner';
import './ldap_groups_select';
import './path_locks';
import './weight_select';
......@@ -374,4 +375,9 @@ $(function () {
event.preventDefault();
gl.utils.visitUrl(`${action}${$(this).serialize()}`);
});
/**
* EE specific scripts
*/
$('#modal-upload-trial-license').modal('show');
});
......@@ -48,3 +48,23 @@
font-size: 14px;
}
}
/* EE-specific Styles */
@media (min-width: $screen-md-min) {
.blank-state-parent-container.has-start-trial-container {
display: flex;
}
}
.section-ee-trial {
.section-body {
display: flex;
align-items: center;
justify-content: center;
.blank-state {
padding: 20px;
text-align: center;
}
}
}
......@@ -9,6 +9,7 @@
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
.prepend-top-10 { margin-top: 10px; }
.prepend-top-15 { margin-top: 15px; }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top: 20px; }
.prepend-left-5 { margin-left: 5px; }
......
/* EE Trial Specific Stylesheet */
/* Main Nav Overrides */
.navbar-gitlab.has-trial-banner {
top: 52px;
}
/* Secondary Nav Overrides - Old Nav */
.page-with-sidebar.has-trial-banner {
margin-top: 102px;
}
/* Sidebar Nav Overrides - New Nav */
.page-with-sidebar.has-trial-banner .nav-sidebar {
top: 102px;
}
/* Trial Banner */
.gitlab-ee-license-banner.alert {
display: flex;
align-content: center;
justify-content: center;
padding: 15px 35px;
position: fixed;
top: 0;
width: 100%;
background: $red-400;
color: $white-light;
text-align: center;
z-index: 400;
@media (max-width: $screen-md-min) {
padding: 10px 35px;
}
.close {
color: $white-dark;
opacity: 0.7;
&:hover {
color: $black;
}
}
p a {
text-decoration: none;
font-weight: bold;
&:hover {
color: $white-dark;
text-decoration: underline;
}
}
.close {
position: absolute;
top: 15%;
right: 10px;
}
}
/* Trial License Install Modal */
.modal-upload-trial-license {
.modal-body-contents {
.trial-activated-graphic {
display: flex;
justify-content: center;
svg {
width: 90px;
height: 90px;
}
}
.confirmation-title,
.confirmation-desc {
text-align: center;
}
.confirmation-desc {
max-width: 80%;
margin: auto;
}
.confirmation-desc {
color: $gl-text-color-secondary;
}
.trial-license-preview {
max-height: 300px;
word-wrap: break-word;
word-break: break-all;
overflow-y: auto;
}
}
}
/* Pure CSS License Key Preview Toggle */
.modal-upload-trial-license {
.trial-license-preview,
.show-license,
.hide-license:target {
display: none;
}
.hide-license,
.hide-license:target + .show-license,
.hide-license:target ~ .trial-license-preview {
display: block;
}
.show-license,
.hide-license {
margin-top: 10px;
text-align: center;
font-size: 18px;
color: $gl-gray-light;
&:hover {
text-decoration: none;
color: $gl-gray-dark;
}
}
}
.blank-state-container {
margin-top: 35px;
.trial-description {
color: $gl-gray-light;
}
}
class Admin::LicensesController < Admin::ApplicationController
before_action :license, only: [:show, :download, :destroy]
before_action :require_license, only: [:show, :download, :destroy]
before_action :require_license, only: [:download, :destroy]
respond_to :html
def show
@previous_licenses = License.previous
if @license.blank?
render :missing
else
@previous_licenses = License.previous
end
end
def download
......@@ -13,7 +17,7 @@ class Admin::LicensesController < Admin::ApplicationController
end
def new
@license = License.new
build_license
end
def create
......@@ -62,6 +66,10 @@ class Admin::LicensesController < Admin::ApplicationController
redirect_to new_admin_license_path
end
def build_license
@license ||= License.new(data: params[:trial_key])
end
def license_params
license_params = params.require(:license).permit(:data_file, :data)
license_params.delete(:data) if license_params[:data_file]
......
......@@ -12,66 +12,30 @@ module LicenseHelper
HistoricalData.max_historical_user_count
end
# in_html is set to false from an initializer, which shouldn't try to render
# HTML links.
#
def license_message(signed_in: signed_in?, is_admin: (current_user && current_user.admin?), in_html: true)
@license_message =
if License.current
yes_license_message(signed_in, is_admin)
else
no_license_message(is_admin, in_html: in_html)
end
end
private
def no_license_message(is_admin, in_html: true)
upload_a_license =
if in_html
link_to('Upload a license', new_admin_license_path)
else
'Upload a license'
end
message = []
message << 'No GitLab Enterprise Edition license has been provided yet.'
message << 'Pushing code and creation of issues and merge requests has been disabled.'
message <<
if is_admin
"#{upload_a_license} in the admin area to activate this functionality."
else
'Ask an admin to upload a license to activate this functionality.'
end
if in_html
content_tag(:p, message.join(' ').html_safe)
else
message.join(' ')
end
end
def yes_license_message(signed_in, is_admin)
license = License.current
def license_message(signed_in: signed_in?, is_admin: current_user&.admin?)
return unless current_license
return unless signed_in
return unless (is_admin && current_license.notify_admins?) || current_license.notify_users?
return unless (is_admin && license.notify_admins?) || license.notify_users?
is_trial = current_license.trial?
message = ["Your Enterprise Edition #{'trial ' if is_trial}license"]
message = []
message << if current_license.expired?
"expired on #{current_license.expires_at}."
else
"will expire in #{pluralize(current_license.remaining_days, 'day')}."
end
message << 'The GitLab Enterprise Edition license'
message << (license.expired? ? 'expired' : 'will expire')
message << "on #{license.expires_at}."
message << link_to('Buy now!', Gitlab::SUBSCRIPTIONS_PLANS_URL, target: '_blank') if is_trial
if license.expired? && license.will_block_changes?
if current_license.expired? && current_license.will_block_changes?
message << 'Pushing code and creation of issues and merge requests'
message <<
if license.block_changes?
if current_license.block_changes?
'has been disabled.'
else
"will be disabled on #{license.block_changes_at}."
"will be disabled on #{current_license.block_changes_at}."
end
message <<
......@@ -82,11 +46,25 @@ module LicenseHelper
end
message << 'to'
message << (license.block_changes? ? 'restore' : 'ensure uninterrupted')
message << (current_license.block_changes? ? 'restore' : 'ensure uninterrupted')
message << 'service.'
end
message.join(' ')
message.join(' ').html_safe
end
def current_license
return @current_license if defined?(@current_license)
@current_license = License.current
end
def new_trial_url
return_to_url = URI.encode(Gitlab.config.gitlab.url)
uri = URI.parse(Gitlab::SUBSCRIPTIONS_URL)
uri.path = '/trials/new'
uri.query = "return_to=#{return_to_url}"
uri.to_s
end
extend self
......
......@@ -185,7 +185,7 @@ class License < ActiveRecord::Base
end
end
delegate :feature_available?, to: :current, allow_nil: true
delegate :block_changes?, :feature_available?, to: :current, allow_nil: true
def reset_current
RequestStore.delete(:current_license)
......@@ -198,10 +198,6 @@ class License < ActiveRecord::Base
features[feature].to_i > 0
end
def block_changes?
!current || current.block_changes?
end
def load_license
license = self.last
......@@ -272,6 +268,8 @@ class License < ActiveRecord::Base
end
def feature_available?(code)
return false if trial? && expired?
feature = FEATURE_CODES.fetch(code)
add_ons[feature].to_i > 0
end
......@@ -302,6 +300,16 @@ class License < ActiveRecord::Base
restricted_attr(:trial)
end
def active?
!expired?
end
def remaining_days
return 0 if expired?
(expires_at - Date.today).to_i
end
private
def restricted_attr(name, default = nil)
......
= link_to 'Buy License', Gitlab::SUBSCRIPTIONS_PLANS_URL, target: '_blank', rel: 'noopener noreferrer nofollow', class: "btn btn-new btn-inverted pull-right btn-buy-license"
= link_to 'Upload New License', new_admin_license_path, class: "btn pull-right btn-upload-license append-right-10"
- license_key = params[:trial_key]
#modal-upload-trial-license.modal-upload-trial-license.modal.fade.in{ tabindex: -1, role: 'dialog' }
.modal-dialog
.modal-content
.modal-body
%button.close{ type: 'button', data: { dismiss: 'modal' }, aria: { label: 'Close' } }
%span &times;
.modal-body-contents
.trial-activated-graphic.prepend-top-15
= custom_icon('ee_trial_license_activated', size: 100)
%h3.confirmation-title
Your trial license was issued!
%p.confirmation-desc.lead
Your trial license was issued and activated. Install it
to enjoy GitLab Enterprise Edition Premium for 30 days.
= form_for License.new, url: admin_license_path, html: { multipart: true, class: 'form-horizontal fieldset-form' } do |f|
= f.hidden_field :data, value: license_key
%a#hide-license.hide-license{ href: '#hide-license' }
Show license key
= icon('chevron-down')
%a#show-license.show-license{ href: '#show-license' }
Hide license key
= icon('chevron-up')
.well.trial-license-preview.prepend-top-15
= license_key
.modal-footer.form-actions
%button.btn.btn-default{ type: 'button', data: { dismiss: 'modal' } } Cancel
= f.submit 'Install license', class: 'btn btn-primary'
- page_title "License"
%h3.page-title
Your License
= render "upload_buy_license"
- if params[:trial_key].present?
= render "upload_trial_license"
%hr
.container.blank-state-container
.text-center
= custom_icon("missing_license")
%h4 You do not have a license.
%p.trial-description You can start a free trial of GitLab Enterprise Edition without any obligation or payment details.
= link_to 'Start free trial', new_trial_url, class: "btn btn-new btn-start-trial prepend-top-10"
- page_title "License"
%h3.page-title
Your License
= link_to 'Upload New License', new_admin_license_path, class: "btn btn-new pull-right"
- if current_license.trial?
= render "upload_buy_license"
- else
= link_to 'Upload New License', new_admin_license_path, class: "btn btn-new pull-right"
%hr
......@@ -32,11 +35,12 @@
Expired:
- else
Expires:
%strong
- if @license.will_expire?
= time_ago_with_tooltip @license.expires_at
- else
Never
- if @license.will_expire? && @license.active?
%strong= time_ago_with_tooltip(@license.expires_at)
- if @license.trial?
%span Free trial will expire in #{pluralize(@license.remaining_days, 'day')}
- else
%strong Never
- if @license.expired?
%span.label.label-danger.pull-right
......
.blank-state
.blank-state-icon
= custom_icon("ee_trial", size: 50)
.blank-state-body
%h3.blank-state-title
Unlock more features with GitLab Enterprise Edition
%p.blank-state-text
GitLab is free to use.
Many features for larger teams are part of
our paid
= succeed "." do
= link_to "Enterprise Edition products", "https://about.gitlab.com/products/", target: "_blank", rel: "noopener noreferrer nofollow"
You can try these out for free without
any obligation or payment details.
= link_to new_trial_url, class: "btn btn-new" do
Start free trial
.row.blank-state-parent-container
.section-container.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
- admin_without_ee_license = !current_license && current_user.admin?
.row.blank-state-parent-container{ class: ('has-start-trial-container' if admin_without_ee_license) }
.section-container.section-welcome{ class: ('col-md-6' if admin_without_ee_license) }
.container.section-body
.blank-state.blank-state-welcome
%h2.blank-state-welcome-title
......@@ -10,3 +12,7 @@
= render "blank_state_admin_welcome"
- else
= render "blank_state_welcome"
- if admin_without_ee_license
.col-md-6.section-container.section-ee-trial
.container.section-body
= render "blank_state_ee_trial"
- if license_message.present?
.broadcast-message
= icon('bullhorn')
= license_message
- BroadcastMessage.current&.each do |message|
= broadcast_message(message)
.page-with-sidebar{ class: page_with_sidebar_class }
.page-with-sidebar.js-page-with-sidebar{ class: [('page-with-new-sidebar' if @new_sidebar), page_gutter_class] }
- if show_new_nav?
- if defined?(nav) && nav
= render "layouts/nav/#{nav}"
......
%header.navbar.navbar-gitlab{ class: nav_header_class }
= render "layouts/header/ee_license_banner"
%header.navbar.navbar-gitlab.js-navbar-gitlab{ class: nav_header_class }
.navbar-border
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
......
- if license_message.present?
.alert.alert-dismissible.gitlab-ee-license-banner.hidden.js-gitlab-ee-license-banner{ role: 'alert', data: { license_expiry: current_license.expires_at } }
-# Show dismiss button only when license expiry is about trial license
- if current_license.trial?
%button.close{ type: 'button', 'data-dismiss' => 'alert', 'aria-label' => 'Dismiss banner' }
= icon('times', 'aria-hidden' => 'true')
%p
= license_message
%header.navbar.navbar-gitlab.navbar-gitlab-new{ class: nav_header_class }
= render "layouts/header/ee_license_banner"
%header.navbar.navbar-gitlab.navbar-gitlab-new.js-navbar-gitlab{ class: nav_header_class }
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
......
<svg xmlns="http://www.w3.org/2000/svg" width="330" height="132" viewBox="0 0 330 132">
<g fill="none" fill-rule="evenodd">
<path fill="#000" fill-opacity=".03" d="M174.12 42c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M211 78c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S230.33 4 211 4s-35 15.67-35 35 15.67 35 35 35z"/>
<g fill-rule="nonzero">
<path fill="#FEE1D3" d="M211.5 51c-6.42 0-12.26-2.84-17.43-8.4-1.32-1.43-1.43-3.58-.27-5.13C199 30.57 204.92 27 211.5 27s12.5 3.56 17.7 10.47c1.16 1.55 1.05 3.7-.27 5.12-5.17 5.53-11 8.4-17.43 8.4zm0-4c5.25 0 10.05-2.34 14.5-7.13-4.5-5.98-9.3-8.87-14.5-8.87-5.2 0-10 2.9-14.5 8.87 4.45 4.8 9.25 7.13 14.5 7.13z"/>
<path fill="#FC6D26" d="M211 47c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm0-4c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zm0-1c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"/>
</g>
<path fill="#000" fill-opacity=".03" d="M88.12 83c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M125 119c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35s-15.67-35-35-35-35 15.67-35 35 15.67 35 35 35z"/>
<path fill="#FEE1D3" fill-rule="nonzero" d="M116 86.34c2.33.83 4 3.05 4 5.66 0 3.3-2.7 6-6 6s-6-2.7-6-6c0-2.6 1.67-4.83 4-5.66V72h4v14.34zM128 66c5.52 0 10 4.48 10 10v12h-4V76c0-3.3-2.7-6-6-6v1.83c0 .55-.45 1-1 1-.24 0-.47-.1-.65-.24l-4.46-3.87c-.46-.36-.5-1-.15-1.4.03-.05.07-.1.1-.12l4.47-3.82c.42-.35 1.05-.3 1.4.1.16.2.25.43.25.66V66zm-14 28c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
<path fill="#FC6D26" fill-rule="nonzero" d="M114 74c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm0-4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm22 28c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm0-4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
<path fill="#000" fill-opacity=".03" d="M2.12 52C2.04 53 2 54 2 55c0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3C74.35 71.03 58.42 86 39 86S3.65 71.03 2.12 52z"/>
<path fill="#EEE" fill-rule="nonzero" d="M39 88C17.46 88 0 70.54 0 49s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 14 39 14 4 29.67 4 49s15.67 35 35 35z"/>
<path fill="#6B4FBB" fill-rule="nonzero" d="M48 41h-4c0-2.76-2.24-5-5-5s-5 2.24-5 5h-4c0-4.97 4.03-9 9-9s9 4.03 9 9zm-18 0h4v3h-4v-3zm14 0h4v3h-4v-3z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M30 47c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V48c0-.55-.45-1-1-1H30zm0-4h18c2.76 0 5 2.24 5 5v12c0 2.76-2.24 5-5 5H30c-2.76 0-5-2.24-5-5V48c0-2.76 2.24-5 5-5z"/>
<path fill="#6B4FBB" d="M38 53.73c-.6-.34-1-1-1-1.73 0-1.1.9-2 2-2s2 .9 2 2c0 .74-.4 1.4-1 1.73V55c0 .55-.45 1-1 1s-1-.45-1-1v-1.27z"/>
<path fill="#000" fill-opacity=".03" d="M254.12 92c-.08 1-.12 2-.12 3 0 20.43 16.57 37 37 37s37-16.57 37-37c0-1-.04-2-.12-3-1.53 19.03-17.46 34-36.88 34s-35.35-14.97-36.88-34z"/>
<path fill="#EEE" fill-rule="nonzero" d="M291 128c-21.54 0-39-17.46-39-39s17.46-39 39-39 39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35s-15.67-35-35-35-35 15.67-35 35 15.67 35 35 35z"/>
<path fill="#6B4BBE" fill-rule="nonzero" d="M292 78c5.52 0 10 4.48 10 10 0 2.28-.76 4.43-2.14 6.18-1.03 1.3-.8 3.2.5 4.22 1.3 1.02 3.2.8 4.2-.5 2.22-2.8 3.44-6.26 3.44-9.9 0-8.84-7.16-16-16-16v-3.13c0-.2-.06-.4-.17-.56-.3-.42-.93-.54-1.38-.23l-9.2 6.13c-.1.06-.2.16-.28.27-.3.45-.18 1.08.28 1.38l9.2 6.13c.16.1.35.17.55.17.55 0 1-.45 1-1V78z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M290 100c-5.52 0-10-4.48-10-10 0-2.25.74-4.38 2.1-6.12 1-1.3.77-3.2-.54-4.2-1.3-1.02-3.2-.78-4.2.53C275.18 83 274 86.4 274 90c0 8.84 7.16 16 16 16v3.13c0 .55.45 1 1 1 .2 0 .4-.06.55-.17l9.2-6.13c.46-.3.6-.93.28-1.38-.07-.1-.17-.2-.28-.28l-9.2-6.13c-.45-.3-1.08-.2-1.38.27-.1.2-.17.4-.17.6v3.1z"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><path fill="#6B4FBB" d="M36.6 44.687l-7.314-6.82a3 3 0 1 0-4.092 4.388l9.508 8.866a2.99 2.99 0 0 0 2.15.804 2.99 2.99 0 0 0 2.09-.952l15.686-16.821a3 3 0 1 0-4.388-4.092L36.6 44.687z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="418" height="260" viewBox="0 0 418 260">
<g fill="none" fill-rule="evenodd">
<g transform="translate(120 123)">
<path fill="#E5E5E5" fill-rule="nonzero" d="M149.583956 3L152.24163 3C160.152584 3 166.875974 8.78143126 168.061078 16.6031139L172.666667 47 168.621014 47 164.106216 17.2023354C163.217388 11.3360734 158.174845 7 152.24163 7L150 7 150 5C150 4.28889529 149.851552 3.61246235 149.583956 3zM126.416044 3L51.5839563 3C51.8515525 3.61246235 52 4.28889529 52 5L52 7 126 7 126 5C126 4.28889529 126.148448 3.61246235 126.416044 3zM5.33333333 47L9.93892213 16.6031139C11.1240256 8.78143126 17.8474164 3 25.7583702 3L28.4160437 3C28.1484475 3.61246235 28 4.28889529 28 5L28 5 28 7 25.7583702 7C19.8251549 7 14.7826117 11.3360734 13.8937841 17.2023354L9.37898649 47 5.33333333 47zM173 71L173 127C173 132.522847 168.522847 137 163 137L15 137C9.4771525 137 5 132.522847 5 127L5 71 9 71 9 127C9 130.313708 11.6862915 133 15 133L163 133C166.313708 133 169 130.313708 169 127L169 71 173 71z"/>
<g transform="translate(126 67)">
<path fill="#E5E5E5" fill-rule="nonzero" d="M5,0 C4.44771525,0 4,0.44771525 4,1 L4,65 C4,65.5522847 4.44771525,66 5,66 L19,66 C19.5522847,66 20,65.5522847 20,65 L20,1 C20,0.44771525 19.5522847,0 19,0 L5,0 Z M24,4 L24,65 C24,67.7614237 21.7614237,70 19,70 L5,70 C2.23857625,70 1.2263553e-15,67.7614237 8.8817842e-16,65 L4.16333634e-17,4 L24,4 Z"/>
<circle cx="12" cy="12" r="3" fill="#FC6D26"/>
<circle cx="12" cy="26" r="3" fill="#FDC4A8"/>
<circle cx="12" cy="40" r="3" fill="#FEE1D3"/>
<circle cx="12" cy="54" r="3" fill="#FEF0E8"/>
</g>
<g transform="translate(126)">
<path fill="#E5E5E5" fill-rule="nonzero" d="M24,47 L24,5 C24,2.23857625 21.7614237,-5.07265313e-16 19,0 L5,0 C2.23857625,5.07265313e-16 -3.38176876e-16,2.23857625 0,5 L6.90805438e-16,47 L4,47 L4,5 C4,4.44771525 4.44771525,4 5,4 L19,4 C19.5522847,4 20,4.44771525 20,5 L20,47 L24,47 Z"/>
<circle cx="12" cy="12" r="3" fill="#FEF0E8"/>
<circle cx="12" cy="26" r="3" fill="#FEE1D3"/>
<circle cx="12" cy="40" r="3" fill="#FDC4A8"/>
</g>
<g transform="translate(28)">
<path fill="#E5E5E5" fill-rule="nonzero" d="M24,47 L24,5 C24,2.23857625 21.7614237,-5.07265313e-16 19,0 L5,0 C2.23857625,5.07265313e-16 -3.38176876e-16,2.23857625 0,5 L6.90805438e-16,47 L4,47 L4,5 C4,4.44771525 4.44771525,4 5,4 L19,4 C19.5522847,4 20,4.44771525 20,5 L20,47 L24,47 Z"/>
<circle cx="12" cy="12" r="3" fill="#FEE1D3"/>
<circle cx="12" cy="26" r="3" fill="#FDC4A8"/>
<circle cx="12" cy="40" r="3" fill="#FC6D26"/>
</g>
<g transform="translate(28 67)">
<path fill="#E5E5E5" fill-rule="nonzero" d="M5,0 C4.44771525,0 4,0.44771525 4,1 L4,65 C4,65.5522847 4.44771525,66 5,66 L19,66 C19.5522847,66 20,65.5522847 20,65 L20,1 C20,0.44771525 19.5522847,0 19,0 L5,0 Z M24,4 L24,65 C24,67.7614237 21.7614237,70 19,70 L5,70 C2.23857625,70 1.2263553e-15,67.7614237 8.8817842e-16,65 L4.16333634e-17,4 L24,4 Z"/>
<circle cx="12" cy="12" r="3" fill="#FDC4A8"/>
<circle cx="12" cy="26" r="3" fill="#FEE1D3"/>
<circle cx="12" cy="40" r="3" fill="#FEF0E8"/>
<circle cx="12" cy="54" r="3" fill="#FC6D26"/>
</g>
<path fill="#E5E5E5" fill-rule="nonzero" d="M81,47 L5,47 C2.23857625,47 -3.38176876e-16,49.2385763 0,52 L0,66 C3.38176876e-16,68.7614237 2.23857625,71 5,71 L81,71 L81,67 L5,67 C4.44771525,67 4,66.5522847 4,66 L4,52 C4,51.4477153 4.44771525,51 5,51 L81,51 L81,47 Z M97,47 L173,47 C175.761424,47 178,49.2385763 178,52 L178,66 C178,68.7614237 175.761424,71 173,71 L97,71 L97,67 L173,67 C173.552285,67 174,66.5522847 174,66 L174,52 C174,51.4477153 173.552285,51 173,51 L97,51 L97,47 Z"/>
<path fill="#C3B8E3" fill-rule="nonzero" d="M105,79.1000181 L105,71 C105,65.077743 101.782413,59.9069937 97.0000045,57.1405177 L97,64.9990251 C98.255821,66.6705132 99,68.7483504 99,71 L99,79 L104,79 C104.342466,79 104.67689,79.0344303 105,79.1000181 Z M73,79.1000181 L73,71 C73,65.077743 76.217587,59.9069937 80.9999955,57.1405177 L81,64.9990251 C79.744179,66.6705132 79,68.7483504 79,71 L79,79 L74,79 L74,79 C73.6575342,79 73.3231099,79.0344303 73,79.1000181 Z"/>
<g transform="matrix(1 0 0 -1 69 115)">
<path fill="#E1DBF1" fill-rule="nonzero" d="M18,4 C10.2680135,4 4,10.2680135 4,18 L4,31 C4,31.5522847 4.44771525,32 5,32 L35,32 C35.5522847,32 36,31.5522847 36,31 L36,18 C36,10.2680135 29.7319865,4 22,4 L18,4 Z M18,-1.2888887e-14 L22,-1.2888887e-14 C31.9411255,-1.24842628e-14 40,8.0588745 40,18 L40,31 C40,33.7614237 37.7614237,36 35,36 L5,36 C2.23857625,36 -9.43169154e-15,33.7614237 -9.76996262e-15,31 L-6.02859776e-15,18 C-8.32276956e-15,8.0588745 8.0588745,-1.2384733e-14 18,-1.2888887e-14 Z"/>
<path fill="#6B4FBB" d="M18,19.4648712 C16.8043973,18.7732524 16,17.4805647 16,16 C16,13.790861 17.790861,12 20,12 C22.209139,12 24,13.790861 24,16 C24,17.4805647 23.1956027,18.7732524 22,19.4648712 L22,22 C22,23.1045695 21.1045695,24 20,24 C18.8954305,24 18,23.1045695 18,22 L18,19.4648712 Z" transform="matrix(1 0 0 -1 0 36)"/>
</g>
<path fill="#E5E5E5" fill-rule="nonzero" d="M86,45 C85.4477153,45 85,45.4477153 85,46 L85,72 C85,72.5522847 85.4477153,73 86,73 L92,73 C92.5522847,73 93,72.5522847 93,72 L93,46 C93,45.4477153 92.5522847,45 92,45 L86,45 Z M86,41 L92,41 C94.7614237,41 97,43.2385763 97,46 L97,72 C97,74.7614237 94.7614237,77 92,77 L86,77 C83.2385763,77 81,74.7614237 81,72 L81,46 C81,43.2385763 83.2385763,41 86,41 Z"/>
</g>
<g transform="translate(259 23)">
<path fill="#F9F9F9" d="M2.11986346,42 C2.04046544,42.9895269 2,43.9900378 2,45 C2,65.4345357 18.5654643,82 39,82 C59.4345357,82 76,65.4345357 76,45 C76,43.9900378 75.9595346,42.9895269 75.8801365,42 C74.3530766,61.0315425 58.4245736,76 39,76 C19.5754264,76 3.64692341,61.0315425 2.11986346,42 Z"/>
<path fill="#EEEEEE" fill-rule="nonzero" d="M39,78 C17.4608948,78 0,60.5391052 0,39 C0,17.4608948 17.4608948,0 39,0 C60.5391052,0 78,17.4608948 78,39 C78,60.5391052 60.5391052,78 39,78 Z M39,74 C58.3299662,74 74,58.3299662 74,39 C74,19.6700338 58.3299662,4 39,4 C19.6700338,4 4,19.6700338 4,39 C4,58.3299662 19.6700338,74 39,74 Z"/>
<g fill-rule="nonzero" transform="translate(21 27)">
<path fill="#FEE1D3" d="M18.5,24 C12.0765212,24 6.23859593,21.1594661 1.07030642,15.5932931 C-0.246808341,14.1747796 -0.3591904,12.016684 0.803462625,10.4690375 C5.99618499,3.55683003 11.9169941,0 18.5,0 C25.0830059,0 31.003815,3.55683003 36.1965373,10.4690375 C37.3591903,12.016684 37.2468083,14.1747794 35.9296936,15.5932931 C30.7614041,21.1594661 24.9234788,24 18.5,24 Z M18.5,20 C23.7455145,20 28.5503007,17.6621561 32.9984408,12.8715735 C28.5048777,6.8900403 23.6940274,4 18.5,4 C13.3059726,4 8.49512227,6.8900403 4.00155907,12.8715735 C8.44969929,17.6621561 13.2544855,20 18.5,20 Z"/>
<path fill="#FC6D26" d="M18,20 C13.581722,20 10,16.418278 10,12 C10,7.581722 13.581722,4 18,4 C22.418278,4 26,7.581722 26,12 C26,16.418278 22.418278,20 18,20 Z M18,16 C20.209139,16 22,14.209139 22,12 C22,9.790861 20.209139,8 18,8 C15.790861,8 14,9.790861 14,12 C14,14.209139 15.790861,16 18,16 Z M18,15 C16.3431458,15 15,13.6568542 15,12 C15,10.3431458 16.3431458,9 18,9 C19.6568542,9 21,10.3431458 21,12 C21,13.6568542 19.6568542,15 18,15 Z"/>
</g>
</g>
<g transform="translate(0 113)">
<path fill="#F9F9F9" d="M2.11986346,42 C2.04046544,42.9895269 2,43.9900378 2,45 C2,65.4345357 18.5654643,82 39,82 C59.4345357,82 76,65.4345357 76,45 C76,43.9900378 75.9595346,42.9895269 75.8801365,42 C74.3530766,61.0315425 58.4245736,76 39,76 C19.5754264,76 3.64692341,61.0315425 2.11986346,42 Z"/>
<path fill="#EEEEEE" fill-rule="nonzero" d="M39,78 C17.4608948,78 0,60.5391052 0,39 C0,17.4608948 17.4608948,0 39,0 C60.5391052,0 78,17.4608948 78,39 C78,60.5391052 60.5391052,78 39,78 Z M39,74 C58.3299662,74 74,58.3299662 74,39 C74,19.6700338 58.3299662,4 39,4 C19.6700338,4 4,19.6700338 4,39 C4,58.3299662 19.6700338,74 39,74 Z"/>
<path fill="#FEE1D3" fill-rule="nonzero" d="M42,25 C47.5228475,25 52,29.4771525 52,35 L52,47 L48,47 L48,35 C48,31.6862915 45.3137085,29 42,29 L42,30.8257794 L42,30.8257794 C42,31.3780641 41.5522847,31.8257794 41,31.8257794 C40.7612887,31.8257794 40.5304517,31.7403872 40.3492086,31.585036 L35.8857994,27.7592566 L35.8857994,27.7592566 C35.4664735,27.3998345 35.417912,26.7685345 35.7773341,26.3492086 C35.8106588,26.3103298 35.8469206,26.2740681 35.8857994,26.2407434 L35.8857994,26.2407434 L40.3492086,22.414964 L40.3492086,22.414964 C40.7685345,22.0555419 41.3998345,22.1041034 41.7592566,22.5234293 C41.9146078,22.7046724 42,22.9355094 42,23.1742206 L42,25 Z"/>
<path fill="#FEE1D3" d="M30,45.3414114 C32.3303847,46.1650842 34,48.3875623 34,51 C34,54.3137085 31.3137085,57 28,57 C24.6862915,57 22,54.3137085 22,51 C22,48.3875623 23.6696153,46.1650842 26,45.3414114 L26,31 L30,31 L30,45.3414114 Z M28,53 C29.1045695,53 30,52.1045695 30,51 C30,49.8954305 29.1045695,49 28,49 C26.8954305,49 26,49.8954305 26,51 C26,52.1045695 26.8954305,53 28,53 Z"/>
<path fill="#FC6D26" fill-rule="nonzero" d="M28 33C24.6862915 33 22 30.3137085 22 27 22 23.6862915 24.6862915 21 28 21 31.3137085 21 34 23.6862915 34 27 34 30.3137085 31.3137085 33 28 33zM28 29C29.1045695 29 30 28.1045695 30 27 30 25.8954305 29.1045695 25 28 25 26.8954305 25 26 25.8954305 26 27 26 28.1045695 26.8954305 29 28 29zM50 57C46.6862915 57 44 54.3137085 44 51 44 47.6862915 46.6862915 45 50 45 53.3137085 45 56 47.6862915 56 51 56 54.3137085 53.3137085 57 50 57zM50 53C51.1045695 53 52 52.1045695 52 51 52 49.8954305 51.1045695 49 50 49 48.8954305 49 48 49.8954305 48 51 48 52.1045695 48.8954305 53 50 53z"/>
</g>
<g transform="translate(104)">
<path fill="#F9F9F9" d="M2.11986346,42 C2.04046544,42.9895269 2,43.9900378 2,45 C2,65.4345357 18.5654643,82 39,82 C59.4345357,82 76,65.4345357 76,45 C76,43.9900378 75.9595346,42.9895269 75.8801365,42 C74.3530766,61.0315425 58.4245736,76 39,76 C19.5754264,76 3.64692341,61.0315425 2.11986346,42 Z"/>
<path fill="#EEEEEE" fill-rule="nonzero" d="M39,78 C17.4608948,78 0,60.5391052 0,39 C0,17.4608948 17.4608948,0 39,0 C60.5391052,0 78,17.4608948 78,39 C78,60.5391052 60.5391052,78 39,78 Z M39,74 C58.3299662,74 74,58.3299662 74,39 C74,19.6700338 58.3299662,4 39,4 C19.6700338,4 4,19.6700338 4,39 C4,58.3299662 19.6700338,74 39,74 Z"/>
<g transform="translate(25 22)">
<path fill="#6B4FBB" fill-rule="nonzero" d="M23,9 L19,9 C19,6.23857625 16.7614237,4 14,4 C11.2385763,4 9,6.23857625 9,9 L5,9 C5,4.02943725 9.02943725,0 14,0 C18.9705627,0 23,4.02943725 23,9 Z M5,9 L9,9 L9,12 L5,12 L5,9 Z M19,9 L23,9 L23,12 L19,12 L19,9 Z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M5,15 C4.44771525,15 4,15.4477153 4,16 L4,28 C4,28.5522847 4.44771525,29 5,29 L23,29 C23.5522847,29 24,28.5522847 24,28 L24,16 C24,15.4477153 23.5522847,15 23,15 L5,15 Z M5,11 L23,11 C25.7614237,11 28,13.2385763 28,16 L28,28 C28,30.7614237 25.7614237,33 23,33 L5,33 C2.23857625,33 3.38176876e-16,30.7614237 0,28 L0,16 C-3.38176876e-16,13.2385763 2.23857625,11 5,11 Z"/>
<path fill="#6B4FBB" d="M13,21.7324356 C12.4021986,21.3866262 12,20.7402824 12,20 C12,18.8954305 12.8954305,18 14,18 C15.1045695,18 16,18.8954305 16,20 C16,20.7402824 15.5978014,21.3866262 15,21.7324356 L15,23 C15,23.5522847 14.5522847,24 14,24 C13.4477153,24 13,23.5522847 13,23 L13,21.7324356 Z"/>
</g>
</g>
<g transform="translate(340 138)">
<path fill="#F9F9F9" d="M2.11986346,42 C2.04046544,42.9895269 2,43.9900378 2,45 C2,65.4345357 18.5654643,82 39,82 C59.4345357,82 76,65.4345357 76,45 C76,43.9900378 75.9595346,42.9895269 75.8801365,42 C74.3530766,61.0315425 58.4245736,76 39,76 C19.5754264,76 3.64692341,61.0315425 2.11986346,42 Z"/>
<path fill="#EEEEEE" fill-rule="nonzero" d="M39,78 C17.4608948,78 0,60.5391052 0,39 C0,17.4608948 17.4608948,0 39,0 C60.5391052,0 78,17.4608948 78,39 C78,60.5391052 60.5391052,78 39,78 Z M39,74 C58.3299662,74 74,58.3299662 74,39 C74,19.6700338 58.3299662,4 39,4 C19.6700338,4 4,19.6700338 4,39 C4,58.3299662 19.6700338,74 39,74 Z"/>
<path fill="#6B4BBE" fill-rule="nonzero" d="M40,28 C45.5228475,28 50,32.4771525 50,38 C50,40.2789647 49.2390936,42.433801 47.8589333,44.1844992 C46.8331752,45.4856473 47.0564228,47.3719774 48.3575709,48.3977356 C49.658719,49.4234937 51.5450491,49.200246 52.5708072,47.899098 C54.7780762,45.0992335 56,41.6388267 56,38 C56,29.163444 48.836556,22 40,22 L40,18.8685171 C40,18.6710921 39.941562,18.4780844 39.8320503,18.3138169 C39.5256978,17.8542882 38.9048285,17.7301143 38.4452998,18.0364668 L38.4452998,18.0364668 L29.2480754,24.1679497 L29.2480754,24.1679497 C29.1382232,24.2411846 29.0439602,24.3354475 28.9707253,24.4452998 C28.6643729,24.9048285 28.7885468,25.5256978 29.2480754,25.8320503 L29.2480754,25.8320503 L38.4452998,31.9635332 C38.6095673,32.0730449 38.802575,32.1314829 39,32.1314829 C39.5522847,32.1314829 40,31.6837677 40,31.1314829 L40,28 Z"/>
<path fill="#E1DBF2" fill-rule="nonzero" d="M38,50 C32.4771525,50 28,45.5228475 28,40 C28,37.7497044 28.7417573,35.6203161 30.0900571,33.8807561 C31.1050652,32.5712049 30.8662909,30.6867771 29.5567397,29.671769 C28.2471884,28.6567608 26.3627607,28.8955351 25.3477525,30.2050864 C23.1912083,32.9874336 22,36.4070765 22,40 C22,48.836556 29.163444,56 38,56 L38,59.1314829 C38,59.6837677 38.4477153,60.1314829 39,60.1314829 C39.197425,60.1314829 39.3904327,60.0730449 39.5547002,59.9635332 L48.7519246,53.8320503 C49.2114532,53.5256978 49.3356271,52.9048285 49.0292747,52.4452998 C48.9560398,52.3354475 48.8617768,52.2411846 48.7519246,52.1679497 L39.5547002,46.0364668 L39.5547002,46.0364668 C39.0951715,45.7301143 38.4743022,45.8542882 38.1679497,46.3138169 C38.058438,46.4780844 38,46.6710921 38,46.8685171 L38,50 Z"/>
</g>
</g>
</svg>
......@@ -9,7 +9,7 @@ end
# Needed to run migration
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('licenses')
message = LicenseHelper.license_message(signed_in: true, is_admin: true, in_html: false)
if message.present?
if ::License.block_changes? && message.present?
warn "WARNING: #{message}"
end
end
......@@ -8,12 +8,6 @@ Feature: Admin license
And I visit admin license page
Then I should see to whom the license is licensed
Scenario: Viewing license when there is none
Given There is no license
And I visit admin license page
Then I should see a warning telling me there is no license
And I should be redirected to the license upload page
Scenario: Viewing expired license
Given there is a license
And the current license is expired
......
......@@ -14,10 +14,6 @@ class Spinach::Features::AdminLicense < Spinach::FeatureSteps
License.destroy_all
end
step 'I should see a warning telling me there is no license' do
expect(page).to have_content "No GitLab Enterprise Edition license has been provided yet."
end
step 'I should be redirected to the license upload page' do
expect(current_path).to eq(new_admin_license_path)
end
......@@ -27,7 +23,7 @@ class Spinach::Features::AdminLicense < Spinach::FeatureSteps
end
step 'I should see a warning telling me the license has expired' do
expect(page).to have_content "The GitLab Enterprise Edition license expired"
expect(page).to have_content "Your Enterprise Edition license expired"
end
step 'the current license blocks changes' do
......
......@@ -3,6 +3,8 @@ require_dependency 'gitlab/git'
module Gitlab
SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}
COM_URL = 'https://gitlab.com'.freeze
SUBSCRIPTIONS_URL = 'https://customers.gitlab.com'.freeze
SUBSCRIPTIONS_PLANS_URL = "#{SUBSCRIPTIONS_URL}/plans".freeze
def self.com?
# Check `gl_subdomain?` as well to keep parity with gitlab.com
......
......@@ -15,4 +15,26 @@ describe Admin::LicensesController do
expect(flash[:alert]).to include 'Please enter or upload a license.'
end
end
describe 'GET show' do
context 'with an existent license' do
it 'renders the license details' do
allow(License).to receive(:current).and_return(create(:license))
get :show
expect(response).to render_template(:show)
end
end
context 'without a license' do
it 'renders missing license page' do
allow(License).to receive(:current).and_return(nil)
get :show
expect(response).to render_template(:missing)
end
end
end
end
......@@ -2,10 +2,26 @@ FactoryGirl.define do
factory :gitlab_license, class: "Gitlab::License" do
skip_create
trait :trial do
block_changes_at nil
restrictions do
{ trial: true }
end
end
trait :expired do
expires_at { 3.weeks.ago.to_date }
end
transient do
plan License::STARTER_PLAN
end
starts_at { Date.today - 1.month }
expires_at { Date.today + 11.months }
notify_users_at { |l| l.expires_at }
notify_admins_at { |l| l.expires_at }
block_changes_at { expires_at + 2.weeks }
notify_users_at { expires_at }
notify_admins_at { expires_at }
licensee do
{ "Name" => generate(:name) }
......@@ -20,27 +36,25 @@ FactoryGirl.define do
plan: plan
}
end
transient do
plan License::STARTER_PLAN
end
trait :trial do
restrictions do
{ trial: true }
end
end
end
factory :license do
transient do
plan nil
expired false
trial false
end
data { build(:gitlab_license, plan: plan).export }
end
data do
attrs = [:gitlab_license]
attrs << :trial if trial
attrs << :expired if expired
attrs << { plan: plan }
build(*attrs).export
end
factory :trial_license, class: License do
data { build(:gitlab_license, :trial).export }
# Disable validations when creating an expired license key
to_create {|instance| instance.save(validate: !expired) }
end
end
......@@ -26,5 +26,42 @@ feature "License Admin" do
end
end
end
context 'with an expired trial license' do
let!(:license) { create(:license, trial: true, expired: true) }
it 'does not mention blocking of changes' do
visit admin_license_path
page.within '.gitlab-ee-license-banner' do
expect(page).to have_content('Your Enterprise Edition trial license expired on')
expect(page).not_to have_content('Pushing code and creation of issues and merge requests has been disabled')
end
end
end
context 'when license key is provided in the query string' do
let(:license) { build(:license, data: build(:gitlab_license, restrictions: { active_user_count: 2000 }).export) }
before do
License.destroy_all
end
it 'shows the modal to install the license' do
visit admin_license_path(trial_key: license.data)
page.within '#modal-upload-trial-license' do
expect(page).to have_content('Your trial license was issued')
expect(page).to have_button('Install license')
end
end
it 'can install the license' do
visit admin_license_path(trial_key: license.data)
click_button 'Install license'
expect(page).to have_content('The license was successfully uploaded and is now active')
end
end
end
end
......@@ -11,18 +11,14 @@ describe LicenseHelper do
let(:is_admin) { true }
it 'displays correct error message for admin user' do
admin_msg = '<p>No GitLab Enterprise Edition license has been provided yet. Pushing code and creation of issues and merge requests has been disabled. <a href="/admin/license/new">Upload a license</a> in the admin area to activate this functionality.</p>'
expect(license_message(signed_in: true, is_admin: is_admin)).to eq(admin_msg)
expect(license_message(signed_in: true, is_admin: is_admin)).to be_blank
end
end
context 'normal user' do
let(:is_admin) { false }
it 'displays correct error message for normal user' do
user_msg = '<p>No GitLab Enterprise Edition license has been provided yet. Pushing code and creation of issues and merge requests has been disabled. Ask an admin to upload a license to activate this functionality.</p>'
expect(license_message(signed_in: true, is_admin: is_admin)).to eq(user_msg)
expect(license_message(signed_in: true, is_admin: is_admin)).to be_blank
end
end
end
......
......@@ -302,8 +302,24 @@ describe License do
allow(described_class).to receive(:current).and_return(nil)
end
it "returns true" do
expect(described_class.block_changes?).to be_truthy
it "returns false" do
expect(described_class.block_changes?).to be_falsey
end
end
context 'with an expired trial license' do
let!(:license) { create(:license, trial: true) }
it 'returns false' do
expect(described_class.block_changes?).to be_falsey
end
end
context 'with an expired normal license' do
let!(:license) { create(:license, expired: true) }
it 'returns true' do
expect(described_class.block_changes?).to eq(true)
end
end
......@@ -451,6 +467,19 @@ describe License do
expect { license.feature_available?(:invalid) }.to raise_error(KeyError)
end
context 'with an expired trial license' do
before(:all) do
described_class.destroy_all
create(:license, trial: true, expired: true)
end
::License::FEATURE_CODES.keys do |feature_code|
it "returns false for #{feature_code}" do
expect(license.feature_available?(feature_code)).to eq(false)
end
end
end
end
def build_license_with_add_ons(add_ons, plan: nil)
......
......@@ -781,18 +781,13 @@ describe 'Git HTTP requests' do
let(:env) { { user: user.username, password: user.password } }
before do
project.team << [user, :master]
end
it 'responds with status 403 Forbidden' do
msg = 'No GitLab Enterprise Edition license has been provided yet. Pushing code and creation of issues and merge requests has been disabled. Ask an admin to upload a license to activate this functionality.'
allow(License).to receive(:current).and_return(nil)
upload(path, env) do |response|
expect(response).to have_http_status(:forbidden)
expect(response.body).to eq(msg)
end
project.team << [user, :master]
end
it_behaves_like 'pulls are allowed'
it_behaves_like 'pushes are allowed'
end
end
......
......@@ -6,7 +6,7 @@ describe HistoricalDataWorker do
describe '#perform' do
context 'with a trial license' do
before do
FactoryGirl.create(:trial_license)
FactoryGirl.create(:license, trial: true)
end
it 'does not track historical data' do
......
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