summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2018-04-27 14:56:50 +0200
committerBob Van Landuyt <bob@vanlanduyt.co>2018-05-04 13:54:43 +0200
commit10aa55a770c2985c22c92d17b8a7ea90b0a09085 (patch)
tree15b66bb5e3f26d0a49c07bf781c644deb998f0c8 /app
parent65bea3f7d0bf30b5f9a9b3f94567474d3c8f7cbc (diff)
downloadgitlab-ce-10aa55a770c2985c22c92d17b8a7ea90b0a09085.tar.gz
Allow a user to accept/decline terms
When a user accepts, we store this in the agreements to keep track of which terms they accepted. We also update the flag on the user.
Diffstat (limited to 'app')
-rw-r--r--app/assets/stylesheets/framework/terms.scss8
-rw-r--r--app/controllers/users/terms_controller.rb43
-rw-r--r--app/helpers/users_helper.rb17
-rw-r--r--app/models/user.rb6
-rw-r--r--app/policies/application_setting/term_policy.rb30
-rw-r--r--app/services/users/respond_to_terms_service.rb24
-rw-r--r--app/views/layouts/terms.html.haml11
-rw-r--r--app/views/users/terms/index.html.haml12
8 files changed, 142 insertions, 9 deletions
diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss
index 0e9bdba034c..c73274540ac 100644
--- a/app/assets/stylesheets/framework/terms.scss
+++ b/app/assets/stylesheets/framework/terms.scss
@@ -33,5 +33,13 @@
.panel-content {
padding: 0 $gl-padding;
}
+
+ .footer-block {
+ margin: 0;
+
+ .btn {
+ margin-left: 5px;
+ }
+ }
}
}
diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb
index 778e388ff5a..32507bdb7b1 100644
--- a/app/controllers/users/terms_controller.rb
+++ b/app/controllers/users/terms_controller.rb
@@ -2,18 +2,55 @@ module Users
class TermsController < ApplicationController
before_action :terms
-
layout 'terms'
def index
+ @redirect = redirect_path
+ end
+
+ def accept
+ agreement = Users::RespondToTermsService.new(current_user, viewed_term)
+ .execute(accepted: true)
+
+ if agreement.persisted?
+ redirect_to redirect_path
+ else
+ flash[:alert] = agreement.errors.full_messages.join(', ')
+ redirect_to terms_path, redirect: redirect_path
+ end
+ end
+
+ def decline
+ agreement = Users::RespondToTermsService.new(current_user, viewed_term)
+ .execute(accepted: false)
+
+ if agreement.persisted?
+ sign_out(current_user)
+ redirect_to root_path
+ else
+ flash[:alert] = agreement.errors.full_messages.join(', ')
+ redirect_to terms_path, redirect: redirect_path
+ end
end
private
+ def viewed_term
+ @viewed_term ||= ApplicationSetting::Term.find(params[:id])
+ end
+
def terms
- unless @terms = Gitlab::CurrentSettings.current_application_settings.latest_terms
- redirect_to request.referer || root_path
+ unless @term = Gitlab::CurrentSettings.current_application_settings.latest_terms
+ redirect_to redirect_path
end
end
+
+ def redirect_path
+ referer = if request.referer && !request.referer.include?(terms_path)
+ URI(request.referer).path
+ end
+
+ params[:redirect] || referer || root_path
+ end
end
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 517268175e6..e803cd3a8d8 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -38,13 +38,24 @@ module UsersHelper
end
def get_current_user_menu_items
- items = [:help, :sign_out]
+ items = []
- if can?(current_user, :read_user, current_user)
+ items << :sign_out if current_user
+
+ # TODO: Remove these conditions when the permissions are prevented in
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/45849
+ terms_not_enforced = !Gitlab::CurrentSettings
+ .current_application_settings
+ .enforce_terms?
+ required_terms_accepted = terms_not_enforced || current_user.terms_accepted?
+
+ items << :help if required_terms_accepted
+
+ if can?(current_user, :read_user, current_user) && required_terms_accepted
items << :profile
end
- if can?(current_user, :update_user, current_user)
+ if can?(current_user, :update_user, current_user) && required_terms_accepted
items << :settings
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4a602ffbb05..a9cfd39f604 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -138,6 +138,8 @@ class User < ActiveRecord::Base
has_many :custom_attributes, class_name: 'UserCustomAttribute'
has_many :callouts, class_name: 'UserCallout'
has_many :uploads, as: :model, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :term_agreements
+ belongs_to :accepted_term, class_name: 'ApplicationSetting::Term'
#
# Validations
@@ -1187,6 +1189,10 @@ class User < ActiveRecord::Base
max_member_access_for_group_ids([group_id])[group_id]
end
+ def terms_accepted?
+ accepted_term_id.present?
+ end
+
protected
# override, from Devise::Validatable
diff --git a/app/policies/application_setting/term_policy.rb b/app/policies/application_setting/term_policy.rb
new file mode 100644
index 00000000000..648932ddba9
--- /dev/null
+++ b/app/policies/application_setting/term_policy.rb
@@ -0,0 +1,30 @@
+class ApplicationSetting
+ class TermPolicy < BasePolicy
+ include Gitlab::Utils::StrongMemoize
+
+ condition(:logged_in, scope: :user) { @user }
+
+ condition(:current_terms, scope: :subject) do
+ Gitlab::CurrentSettings.current_application_settings.latest_terms == @subject
+ end
+
+ condition(:terms_accepted, scope: :user, score: 1) do
+ agreement&.accepted
+ end
+
+ rule { logged_in & current_terms }.policy do
+ enable :accept_terms
+ enable :decline_terms
+ end
+
+ rule { terms_accepted }.prevent :accept_terms
+
+ def agreement
+ strong_memoize(:agreement) do
+ next nil if @user.nil? || @subject.nil?
+
+ @user.term_agreements.find_by(term: @subject)
+ end
+ end
+ end
+end
diff --git a/app/services/users/respond_to_terms_service.rb b/app/services/users/respond_to_terms_service.rb
new file mode 100644
index 00000000000..06d660186cf
--- /dev/null
+++ b/app/services/users/respond_to_terms_service.rb
@@ -0,0 +1,24 @@
+module Users
+ class RespondToTermsService
+ def initialize(user, term)
+ @user, @term = user, term
+ end
+
+ def execute(accepted:)
+ agreement = @user.term_agreements.find_or_initialize_by(term: @term)
+ agreement.accepted = accepted
+
+ if agreement.save
+ store_accepted_term(accepted)
+ end
+
+ agreement
+ end
+
+ private
+
+ def store_accepted_term(accepted)
+ @user.update_column(:accepted_term_id, accepted ? @term.id : nil)
+ end
+ end
+end
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 09c4567a362..b04dbc595a5 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -3,11 +3,18 @@
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
- %body{ class: "#{user_application_theme} #{@body_class}", data: { page: body_data_page } }
+ %body{ data: { page: body_data_page } }
= render 'peek/bar'
.layout-page.terms
.content-wrapper
- %div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
+ .mobile-overlay
+ .alert-wrapper
+ = render "layouts/broadcast"
+ = render 'layouts/header/read_only_banner'
+ = yield :flash_message
+ = render "layouts/flash"
+
+ %div{ class: "#{container_class}" }
.content{ id: "content-body" }
.panel.panel-default
.panel-heading
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index 49fdab84069..614dab57331 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -1,2 +1,12 @@
+- redirect_params = { redirect: @redirect } if @redirect
.panel-content.rendered-terms
- = markdown_field(@terms, :terms)
+ = markdown_field(@term, :terms)
+.row-content-block.footer-block.clearfix
+ - if can?(current_user, :accept_terms, @term)
+ .pull-right
+ = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do
+ = _('Accept terms')
+ - if can?(current_user, :decline_terms, @term)
+ .pull-right
+ = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do
+ = _('Decline and sign out')