summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/main.js2
-rw-r--r--app/assets/javascripts/usage_ping_consent.js30
-rw-r--r--app/assets/stylesheets/framework/layout.scss19
-rw-r--r--app/controllers/admin/application_settings_controller.rb24
-rw-r--r--app/controllers/application_controller.rb26
-rw-r--r--app/helpers/version_check_helper.rb10
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/models/user.rb22
-rw-r--r--app/services/application_settings/update_service.rb8
-rw-r--r--app/services/submit_usage_ping_service.rb1
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/shared/_ping_consent.html.haml12
12 files changed, 144 insertions, 14 deletions
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 2718f73a830..c5a5f64abac 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -29,6 +29,7 @@ import './milestone_select';
import './frequent_items';
import initBreadcrumbs from './breadcrumb';
import initDispatcher from './dispatcher';
+import initUsagePingConsent from './usage_ping_consent';
// expose jQuery as global (TODO: remove these)
window.jQuery = jQuery;
@@ -78,6 +79,7 @@ document.addEventListener('DOMContentLoaded', () => {
initImporterStatus();
initTodoToggle();
initLogoAnimation();
+ initUsagePingConsent();
// Set the default path for all cookies to GitLab's root directory
Cookies.defaults.path = gon.relative_url_root || '/';
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/usage_ping_consent.js
new file mode 100644
index 00000000000..ae3fde190e3
--- /dev/null
+++ b/app/assets/javascripts/usage_ping_consent.js
@@ -0,0 +1,30 @@
+import $ from 'jquery';
+import axios from './lib/utils/axios_utils';
+import Flash, { hideFlash } from './flash';
+import { convertPermissionToBoolean } from './lib/utils/common_utils';
+
+export default () => {
+ $('body').on('click', '.js-usage-consent-action', (e) => {
+ e.preventDefault();
+ e.stopImmediatePropagation(); // overwrite rails listener
+
+ const { url, checkEnabled, pingEnabled } = e.target.dataset;
+ const data = {
+ application_setting: {
+ version_check_enabled: convertPermissionToBoolean(checkEnabled),
+ usage_ping_enabled: convertPermissionToBoolean(pingEnabled),
+ },
+ };
+
+ const hideConsentMessage = () => hideFlash(document.querySelector('.ping-consent-message'));
+
+ axios.put(url, data)
+ .then(() => {
+ hideConsentMessage();
+ })
+ .catch(() => {
+ hideConsentMessage();
+ Flash('Something went wrong. Try again later.');
+ });
+ });
+};
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index d4bae4cb137..9218df9b40f 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -69,10 +69,14 @@ body {
float: right;
}
- /* Center alert text and alert action links on smaller screens */
- @include media-breakpoint-down(sm) {
- .alert {
- text-align: center;
+ .flex-alert {
+ @include media-breakpoint-up(lg) {
+ display: flex;
+
+ .alert-message {
+ flex: 1;
+ padding-right: 40px;
+ }
}
.alert-link-group {
@@ -80,6 +84,13 @@ body {
}
}
+ @include media-breakpoint-down(sm) {
+ .alert-link-group {
+ float: none;
+ margin-top: $gl-padding-8;
+ }
+ }
+
/* Stripe the background colors so that adjacent alert-warnings are distinct from one another */
.alert-warning {
transition: background-color 0.15s, border-color 0.15s;
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 9723e400574..869213d61f1 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -9,11 +9,18 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
.new(@application_setting, current_user, application_setting_params)
.execute
- if successful
- redirect_to admin_application_settings_path,
- notice: 'Application settings saved successfully'
- else
- render :show
+ if recheck_user_consent?
+ session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent?
+ end
+
+ respond_to do |format|
+ if successful
+ format.json { head :ok }
+ format.html { redirect_to admin_application_settings_path, notice: 'Application settings saved successfully' }
+ else
+ format.json { head :bad_request }
+ format.html { render :show }
+ end
end
end
@@ -76,6 +83,13 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
)
end
+ def recheck_user_consent?
+ return false unless session[:ask_for_usage_stats_consent]
+ return false unless params[:application_setting]
+
+ params[:application_setting].key?(:usage_ping_enabled) || params[:application_setting].key?(:version_check_enabled)
+ end
+
def visible_application_setting_attributes
ApplicationSettingsHelper.visible_attributes + [
:domain_blacklist_file,
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 7cd68d6b92a..7e2b2cf3ad3 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -22,6 +22,7 @@ class ApplicationController < ActionController::Base
before_action :add_gon_variables, unless: [:peek_request?, :json_request?]
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :require_email, unless: :devise_controller?
+ before_action :set_usage_stats_consent_flag
around_action :set_locale
@@ -434,4 +435,29 @@ class ApplicationController < ActionController::Base
!(peek_request? || devise_controller?)
end
+
+ def set_usage_stats_consent_flag
+ return unless current_user
+ return if sessionless_user?
+ return if session.has_key?(:ask_for_usage_stats_consent)
+
+ session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent?
+
+ if session[:ask_for_usage_stats_consent]
+ disable_usage_stats
+ end
+ end
+
+ def disable_usage_stats
+ application_setting_params = {
+ usage_ping_enabled: false,
+ version_check_enabled: false,
+ skip_usage_stats_user: true
+ }
+ settings = Gitlab::CurrentSettings.current_application_settings
+
+ ApplicationSettings::UpdateService
+ .new(settings, current_user, application_setting_params)
+ .execute
+ end
end
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index c20753ece72..a7fef93e7f1 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -1,8 +1,10 @@
module VersionCheckHelper
def version_status_badge
- if Rails.env.production? && Gitlab::CurrentSettings.version_check_enabled
- image_url = VersionCheck.new.url
- image_tag image_url, class: 'js-version-status-badge'
- end
+ return unless Rails.env.production?
+ return unless Gitlab::CurrentSettings.version_check_enabled
+ return if User.single_user&.requires_usage_stats_consent?
+
+ image_url = VersionCheck.new.url
+ image_tag image_url, class: 'js-version-status-badge'
end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 03bd7fa016e..d8536c5512d 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -302,7 +302,8 @@ class ApplicationSetting < ActiveRecord::Base
instance_statistics_visibility_private: false,
user_default_external: false,
user_default_internal_regex: nil,
- user_show_add_ssh_key_message: true
+ user_show_add_ssh_key_message: true,
+ usage_stats_set_by_user_id: nil
}
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 0fcc952b5cd..568ec101016 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -490,6 +490,16 @@ class User < ActiveRecord::Base
u.name = 'Ghost User'
end
end
+
+ # Return true if there is only single non-internal user in the deployment,
+ # ghost user is ignored.
+ def single_user?
+ User.non_internal.limit(2).count == 1
+ end
+
+ def single_user
+ User.non_internal.first if single_user?
+ end
end
def full_path
@@ -1287,6 +1297,10 @@ class User < ActiveRecord::Base
!terms_accepted?
end
+ def requires_usage_stats_consent?
+ !consented_usage_stats? && 7.days.ago > self.created_at && !has_current_license? && User.single_user?
+ end
+
# @deprecated
alias_method :owned_or_masters_groups, :owned_or_maintainers_groups
@@ -1301,6 +1315,14 @@ class User < ActiveRecord::Base
private
+ def has_current_license?
+ false
+ end
+
+ def consented_usage_stats?
+ Gitlab::CurrentSettings.usage_stats_set_by_user_id == self.id
+ end
+
def owned_projects_union
Gitlab::SQL::Union.new([
Project.where(namespace: namespace),
diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb
index 19cf34e2ac4..2e4643ed668 100644
--- a/app/services/application_settings/update_service.rb
+++ b/app/services/application_settings/update_service.rb
@@ -11,11 +11,19 @@ module ApplicationSettings
params[:performance_bar_allowed_group_id] = performance_bar_allowed_group_id
end
+ if usage_stats_updated? && !params.delete(:skip_usage_stats_user)
+ params[:usage_stats_set_by_user_id] = current_user.id
+ end
+
@application_setting.update(@params)
end
private
+ def usage_stats_updated?
+ params.key?(:usage_ping_enabled) || params.key?(:version_check_enabled)
+ end
+
def update_terms(terms)
return unless terms.present?
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 93c2e222963..62222d3fd2a 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -15,6 +15,7 @@ class SubmitUsagePingService
def execute
return false unless Gitlab::CurrentSettings.usage_ping_enabled?
+ return false if User.single_user&.requires_usage_stats_consent?
response = Gitlab::HTTP.post(
URL,
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index f67a8878c80..a41d30da450 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -8,6 +8,7 @@
= render "layouts/broadcast"
= render 'layouts/header/read_only_banner'
= yield :flash_message
+ = render "shared/ping_consent"
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
= render "layouts/flash"
diff --git a/app/views/shared/_ping_consent.html.haml b/app/views/shared/_ping_consent.html.haml
new file mode 100644
index 00000000000..f8eb2b2833b
--- /dev/null
+++ b/app/views/shared/_ping_consent.html.haml
@@ -0,0 +1,12 @@
+- if session[:ask_for_usage_stats_consent]
+ .ping-consent-message.alert.alert-warning.flex-alert
+ - settings_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="alert-link">'.html_safe % { url: admin_application_settings_path(anchor: 'js-usage-settings') }
+ - info_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="alert-link">'.html_safe % { url: help_page_path('user/admin_area/settings/usage_statistics.md') }
+ .alert-message
+ = s_('To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}').html_safe % { settings_link_start: settings_link_start, info_link_start: info_link_start, link_end: '</a>'.html_safe }
+ .alert-link-group
+ - send_usage_data_path = admin_application_settings_path(application_setting: { version_check_enabled: 1, usage_ping_enabled: 1 })
+ - not_now_path = admin_application_settings_path(application_setting: { version_check_enabled: 0, usage_ping_enabled: 0 })
+ = link_to _("Send usage data"), send_usage_data_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': true, 'data-ping-enabled': true, class: 'alert-link js-usage-consent-action'
+ |
+ = link_to _('Not now'), not_now_path, 'data-url' => admin_application_settings_path, method: :put, 'data-check-enabled': false, 'data-ping-enabled': false, class: 'hide-ping-consent-message alert-link js-usage-consent-action'