Skip to content
Snippets Groups Projects
Commit 3d713ac1 authored by Bob Van Landuyt's avatar Bob Van Landuyt
Browse files

Users can accept terms during registration

When a user checks the `accept` checkbox, we will track that
acceptance as usual. That way they don't need to accept again after
they complete the registration.

When an unauthenticated user visits the `/-/users/terms` page, there
is no button to accept, decline or continue. The 'current-user menu'
is also hidden from the top bar.
parent ebdc7f11
No related branches found
No related tags found
1 merge request!10495Merge Requests - Assignee
Showing
with 248 additions and 120 deletions
Loading
Loading
@@ -3,6 +3,9 @@ class RegistrationsController < Devise::RegistrationsController
include AcceptsPendingInvitations
 
before_action :whitelist_query_limiting, only: [:destroy]
before_action :ensure_terms_accepted,
if: -> { Gitlab::CurrentSettings.current_application_settings.enforce_terms? },
only: [:create]
 
def new
redirect_to(new_user_session_path)
Loading
Loading
@@ -18,7 +21,9 @@ class RegistrationsController < Devise::RegistrationsController
 
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
accept_pending_invitations
super
super do |new_user|
persist_accepted_terms_if_required(new_user)
end
else
flash[:alert] = 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
flash.delete :recaptcha_error
Loading
Loading
@@ -40,6 +45,16 @@ class RegistrationsController < Devise::RegistrationsController
 
protected
 
def persist_accepted_terms_if_required(new_user)
return unless new_user.persisted?
return unless Gitlab::CurrentSettings.current_application_settings.enforce_terms?
if terms_accepted?
terms = ApplicationSetting::Term.latest
Users::RespondToTermsService.new(new_user, terms).execute(accepted: true)
end
end
def destroy_confirmation_valid?
if current_user.confirm_deletion_with_password?
current_user.valid_password?(params[:password])
Loading
Loading
@@ -91,4 +106,14 @@ class RegistrationsController < Devise::RegistrationsController
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42380')
end
def ensure_terms_accepted
return if terms_accepted?
redirect_to new_user_session_path, alert: _('You must accept our Terms of Service and privacy policy in order to register an account')
end
def terms_accepted?
Gitlab::Utils.to_boolean(params[:terms_opt_in])
end
end
Loading
Loading
@@ -2,6 +2,7 @@ module Users
class TermsController < ApplicationController
include InternalRedirect
 
skip_before_action :authenticate_user!
skip_before_action :enforce_terms!
skip_before_action :check_password_expiration
skip_before_action :check_two_factor_requirement
Loading
Loading
@@ -14,7 +15,7 @@ module Users
def index
@redirect = redirect_path
 
if @term.accepted_by_user?(current_user)
if current_user && @term.accepted_by_user?(current_user)
flash.now[:notice] = "You have already accepted the Terms of Service as #{current_user.to_reference}"
end
end
Loading
Loading
= form_for @application_setting, url: admin_application_settings_path do |f|
= form_for @application_setting, url: admin_application_settings_path, html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
 
%fieldset
Loading
Loading
@@ -7,13 +7,13 @@
.form-check
= f.check_box :enforce_terms, class: 'form-check-input'
= f.label :enforce_terms, class: 'form-check-label' do
= _("Require all users to accept Terms of Service when they access GitLab.")
= _("Require all users to accept Terms of Service and Privacy Policy when they access GitLab.")
.form-text.text-muted
= _("When enabled, users cannot use GitLab until the terms have been accepted.")
.form-group.row
.col-sm-12
= f.label :terms do
= _("Terms of Service Agreement")
= _("Terms of Service Agreement and Privacy Policy")
.col-sm-12
= f.text_area :terms, class: 'form-control', rows: 8
.form-text.text-muted
Loading
Loading
Loading
Loading
@@ -50,11 +50,11 @@
%section.settings.as-terms.no-animate#js-terms-settings{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Terms of Service')
= _('Terms of Service and Privacy Policy')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _('Include a Terms of Service agreement that all users must accept.')
= _('Include a Terms of Service agreement and Privacy Policy that all users must accept.')
.settings-content
= render 'terms'
 
Loading
Loading
Loading
Loading
@@ -22,6 +22,13 @@
= f.label :password
= f.password_field :password, class: "form-control bottom", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
%p.gl-field-hint Minimum length is #{@minimum_password_length} characters
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
= check_box_tag :terms_opt_in, '1', false, required: true
= label_tag :terms_opt_in do
- terms_link = link_to s_("I accept the|Terms of Service and Privacy Policy"), terms_path, target: "_blank"
- accept_terms_label = _("I accept the %{terms_link}") % { terms_link: terms_link }
= accept_terms_label.html_safe
%div
- if Gitlab::Recaptcha.enabled?
= recaptcha_tags
Loading
Loading
Loading
Loading
@@ -2,16 +2,17 @@
 
.card-body.rendered-terms
= markdown_field(@term, :terms)
.card-footer.footer-block.clearfix
- if can?(current_user, :accept_terms, @term)
.float-right
= button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do
= _('Accept terms')
- else
.pull-right
= link_to root_path, class: 'btn btn-success prepend-left-8' do
= _('Continue')
- if can?(current_user, :decline_terms, @term)
.float-right
= button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do
= _('Decline and sign out')
- if current_user
.card-footer.footer-block.clearfix
- if can?(current_user, :accept_terms, @term)
.float-right
= button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8' do
= _('Accept terms')
- else
.pull-right
= link_to root_path, class: 'btn btn-success prepend-left-8' do
= _('Continue')
- if can?(current_user, :decline_terms, @term)
.float-right
= button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do
= _('Decline and sign out')
---
title: Users can accept terms during registration
merge_request: 19583
author:
type: other
doc/user/admin_area/settings/img/enforce_terms.png

50.8 KiB | W: 1946px | H: 926px

doc/user/admin_area/settings/img/enforce_terms.png

53.6 KiB | W: 1968px | H: 956px

doc/user/admin_area/settings/img/enforce_terms.png
doc/user/admin_area/settings/img/enforce_terms.png
doc/user/admin_area/settings/img/enforce_terms.png
doc/user/admin_area/settings/img/enforce_terms.png
  • 2-up
  • Swipe
  • Onion skin
doc/user/admin_area/settings/img/sign_up_terms.png

17.7 KiB

Loading
Loading
@@ -20,6 +20,19 @@ When an admin enables this feature, they will automattically be
directed to the page to accept the terms themselves. After they
accept, they will be directed back to the settings page.
 
## New registrations
When this feature is enabled, a checkbox will be available in the
sign-up form.
![Sign up form](img/sign_up_terms.png)
This checkbox will be required during sign up.
Users can review the terms entered in the admin panel before
accepting. The page will be opened in a new window so they can
continue their registration afterwards.
## Accepting terms
 
When this feature was enabled, the users that have not accepted the
Loading
Loading
Loading
Loading
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-06-07 19:35+0200\n"
"PO-Revision-Date: 2018-06-07 19:35+0200\n"
"POT-Creation-Date: 2018-06-08 18:19+0200\n"
"PO-Revision-Date: 2018-06-08 18:19+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
Loading
Loading
@@ -232,7 +232,7 @@ msgstr ""
msgid "Account"
msgstr ""
 
msgid "Account and limit settings"
msgid "Account and limit"
msgstr ""
 
msgid "Active"
Loading
Loading
@@ -780,9 +780,6 @@ msgstr ""
msgid "CI/CD settings"
msgstr ""
 
msgid "CICD|A domain is required to use Auto Review Apps and Auto Deploy Stages."
msgstr ""
msgid "CICD|An explicit %{ci_file} needs to be specified before you can begin using Continuous Integration and Delivery."
msgstr ""
 
Loading
Loading
@@ -792,6 +789,18 @@ msgstr ""
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
msgstr ""
 
msgid "CICD|Automatic deployment to staging, manual deployment to production"
msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
msgid "CICD|Deployment strategy"
msgstr ""
msgid "CICD|Deployment strategy needs a domain name to work correctly."
msgstr ""
msgid "CICD|Disable Auto DevOps"
msgstr ""
 
Loading
Loading
@@ -813,6 +822,9 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline configuration will be used when there is no %{ci_file} in the project."
msgstr ""
 
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
msgstr ""
msgid "Can run untagged jobs"
msgstr ""
 
Loading
Loading
@@ -2133,6 +2145,9 @@ msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
 
msgid "Failure"
msgstr ""
msgid "Feb"
msgstr ""
 
Loading
Loading
@@ -2371,6 +2386,12 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
 
msgid "I accept the %{terms_link}"
msgstr ""
msgid "I accept the|Terms of Service and Privacy Policy"
msgstr ""
msgid "IDE|Commit"
msgstr ""
 
Loading
Loading
@@ -2407,7 +2428,7 @@ msgstr ""
msgid "Import repository"
msgstr ""
 
msgid "Include a Terms of Service agreement that all users must accept."
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
 
msgid "Install Runner on Kubernetes"
Loading
Loading
@@ -3548,7 +3569,7 @@ msgstr ""
msgid "Repository maintenance"
msgstr ""
 
msgid "Repository mirror settings"
msgid "Repository mirror"
msgstr ""
 
msgid "Repository storage"
Loading
Loading
@@ -3557,7 +3578,7 @@ msgstr ""
msgid "Request Access"
msgstr ""
 
msgid "Require all users to accept Terms of Service when they access GitLab."
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
 
msgid "Reset git storage health information"
Loading
Loading
@@ -3616,9 +3637,6 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
 
msgid "Runners settings"
msgstr ""
msgid "Running"
msgstr ""
 
Loading
Loading
@@ -3942,6 +3960,9 @@ msgstr ""
msgid "Squash commits"
msgstr ""
 
msgid "Stage"
msgstr ""
msgid "Stage all"
msgstr ""
 
Loading
Loading
@@ -4100,10 +4121,10 @@ msgstr ""
msgid "Team"
msgstr ""
 
msgid "Terms of Service"
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
 
msgid "Terms of Service Agreement"
msgid "Terms of Service and Privacy Policy"
msgstr ""
 
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
Loading
Loading
@@ -4331,6 +4352,9 @@ msgstr ""
msgid "Timeago|%s days remaining"
msgstr ""
 
msgid "Timeago|%s hours ago"
msgstr ""
msgid "Timeago|%s hours remaining"
msgstr ""
 
Loading
Loading
@@ -4346,6 +4370,9 @@ msgstr ""
msgid "Timeago|%s months remaining"
msgstr ""
 
msgid "Timeago|%s seconds ago"
msgstr ""
msgid "Timeago|%s seconds remaining"
msgstr ""
 
Loading
Loading
@@ -4361,46 +4388,43 @@ msgstr ""
msgid "Timeago|%s years remaining"
msgstr ""
 
msgid "Timeago|1 day remaining"
msgid "Timeago|1 day ago"
msgstr ""
 
msgid "Timeago|1 hour remaining"
msgstr ""
msgid "Timeago|1 minute remaining"
msgid "Timeago|1 day remaining"
msgstr ""
 
msgid "Timeago|1 month remaining"
msgid "Timeago|1 hour ago"
msgstr ""
 
msgid "Timeago|1 week remaining"
msgid "Timeago|1 hour remaining"
msgstr ""
 
msgid "Timeago|1 year remaining"
msgid "Timeago|1 minute ago"
msgstr ""
 
msgid "Timeago|Past due"
msgid "Timeago|1 minute remaining"
msgstr ""
 
msgid "Timeago|a day ago"
msgid "Timeago|1 month ago"
msgstr ""
 
msgid "Timeago|a month ago"
msgid "Timeago|1 month remaining"
msgstr ""
 
msgid "Timeago|a week ago"
msgid "Timeago|1 week ago"
msgstr ""
 
msgid "Timeago|a year ago"
msgid "Timeago|1 week remaining"
msgstr ""
 
msgid "Timeago|about %s hours ago"
msgid "Timeago|1 year ago"
msgstr ""
 
msgid "Timeago|about a minute ago"
msgid "Timeago|1 year remaining"
msgstr ""
 
msgid "Timeago|about an hour ago"
msgid "Timeago|Past due"
msgstr ""
 
msgid "Timeago|in %s days"
Loading
Loading
@@ -4442,7 +4466,7 @@ msgstr ""
msgid "Timeago|in 1 year"
msgstr ""
 
msgid "Timeago|less than a minute ago"
msgid "Timeago|just now"
msgstr ""
 
msgid "Timeago|right now"
Loading
Loading
@@ -4872,6 +4896,9 @@ msgstr ""
msgid "You have reached your project limit"
msgstr ""
 
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
 
Loading
Loading
require 'spec_helper'
 
describe RegistrationsController do
include TermsHelper
describe '#create' do
let(:user_params) { { user: { name: 'new_user', username: 'new_username', email: 'new@user.com', password: 'Any_password' } } }
 
Loading
Loading
@@ -67,6 +69,25 @@ describe RegistrationsController do
expect(flash[:notice]).to include 'Welcome! You have signed up successfully.'
end
end
context 'when terms are enforced' do
before do
enforce_terms
end
it 'redirects back with a notice when the checkbox was not checked' do
post :create, user_params
expect(flash[:alert]).to match /you must accept our terms/i
end
it 'creates the user with agreement when terms are accepted' do
post :create, user_params.merge(terms_opt_in: '1')
expect(subject.current_user).to be_present
expect(subject.current_user.terms_accepted?).to be(true)
end
end
end
 
describe '#destroy' do
Loading
Loading
Loading
Loading
@@ -94,7 +94,7 @@ feature 'Admin updates settings' do
accept_terms(admin)
 
page.within('.as-terms') do
check 'Require all users to accept Terms of Service when they access GitLab.'
check 'Require all users to accept Terms of Service and Privacy Policy when they access GitLab.'
fill_in 'Terms of Service Agreement', with: 'Be nice!'
click_button 'Save changes'
end
Loading
Loading
Loading
Loading
@@ -140,7 +140,7 @@ describe 'Signup' do
enforce_terms
end
 
it 'asks the user to accept terms before going to the dashboard' do
it 'requires the user to check the checkbox' do
visit root_path
 
fill_in 'new_user_name', with: new_user.name
Loading
Loading
@@ -148,11 +148,24 @@ describe 'Signup' do
fill_in 'new_user_email', with: new_user.email
fill_in 'new_user_email_confirmation', with: new_user.email
fill_in 'new_user_password', with: new_user.password
click_button "Register"
 
expect_to_be_on_terms_page
click_button 'Register'
expect(current_path).to eq new_user_session_path
expect(page).to have_content(/you must accept our terms of service/i)
end
it 'asks the user to accept terms before going to the dashboard' do
visit root_path
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
fill_in 'new_user_email_confirmation', with: new_user.email
fill_in 'new_user_password', with: new_user.password
check :terms_opt_in
 
click_button 'Accept terms'
click_button "Register"
 
expect(current_path).to eq dashboard_projects_path
end
Loading
Loading
Loading
Loading
@@ -3,12 +3,10 @@ require 'spec_helper'
describe 'Users > Terms' do
include TermsHelper
 
let(:user) { create(:user) }
let!(:term) { create(:term, terms: 'By accepting, you promise to be nice!') }
 
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(user)
end
 
it 'shows the terms' do
Loading
Loading
@@ -17,102 +15,119 @@ describe 'Users > Terms' do
expect(page).to have_content('By accepting, you promise to be nice!')
end
 
context 'declining the terms' do
it 'returns the user to the app' do
visit terms_path
it 'does not show buttons to accept, decline or sign out', :aggregate_failures do
visit terms_path
expect(page).not_to have_css('.footer-block')
expect(page).not_to have_content('Accept terms')
expect(page).not_to have_content('Decline and sign out')
expect(page).not_to have_content('Continue')
end
 
click_button 'Decline and sign out'
context 'when signed in' do
let(:user) { create(:user) }
 
expect(page).not_to have_content(term.terms)
expect(user.reload.terms_accepted?).to be(false)
before do
sign_in(user)
end
end
 
context 'accepting the terms' do
it 'returns the user to the app' do
visit terms_path
context 'declining the terms' do
it 'returns the user to the app' do
visit terms_path
 
click_button 'Accept terms'
click_button 'Decline and sign out'
 
expect(page).not_to have_content(term.terms)
expect(user.reload.terms_accepted?).to be(true)
expect(page).not_to have_content(term.terms)
expect(user.reload.terms_accepted?).to be(false)
end
end
end
 
context 'when the user has already accepted the terms' do
before do
accept_terms(user)
context 'accepting the terms' do
it 'returns the user to the app' do
visit terms_path
click_button 'Accept terms'
expect(page).not_to have_content(term.terms)
expect(user.reload.terms_accepted?).to be(true)
end
end
 
it 'allows the user to continue to the app' do
visit terms_path
context 'when the user has already accepted the terms' do
before do
accept_terms(user)
end
it 'allows the user to continue to the app' do
visit terms_path
 
expect(page).to have_content "You have already accepted the Terms of Service as #{user.to_reference}"
expect(page).to have_content "You have already accepted the Terms of Service as #{user.to_reference}"
 
click_link 'Continue'
click_link 'Continue'
 
expect(current_path).to eq(root_path)
expect(current_path).to eq(root_path)
end
end
end
 
context 'terms were enforced while session is active', :js do
let(:project) { create(:project) }
context 'terms were enforced while session is active', :js do
let(:project) { create(:project) }
 
before do
project.add_developer(user)
end
before do
project.add_developer(user)
end
 
it 'redirects to terms and back to where the user was going' do
visit project_path(project)
it 'redirects to terms and back to where the user was going' do
visit project_path(project)
 
enforce_terms
enforce_terms
 
within('.nav-sidebar') do
click_link 'Issues'
end
within('.nav-sidebar') do
click_link 'Issues'
end
 
expect_to_be_on_terms_page
expect_to_be_on_terms_page
 
click_button('Accept terms')
click_button('Accept terms')
 
expect(current_path).to eq(project_issues_path(project))
end
expect(current_path).to eq(project_issues_path(project))
end
 
# Disabled until https://gitlab.com/gitlab-org/gitlab-ce/issues/37162 is solved properly
xit 'redirects back to the page the user was trying to save' do
visit new_project_issue_path(project)
# Disabled until https://gitlab.com/gitlab-org/gitlab-ce/issues/37162 is solved properly
xit 'redirects back to the page the user was trying to save' do
visit new_project_issue_path(project)
 
fill_in :issue_title, with: 'Hello world, a new issue'
fill_in :issue_description, with: "We don't want to lose what the user typed"
fill_in :issue_title, with: 'Hello world, a new issue'
fill_in :issue_description, with: "We don't want to lose what the user typed"
 
enforce_terms
enforce_terms
 
click_button 'Submit issue'
click_button 'Submit issue'
 
expect(current_path).to eq(terms_path)
expect(current_path).to eq(terms_path)
 
click_button('Accept terms')
click_button('Accept terms')
 
expect(current_path).to eq(new_project_issue_path(project))
expect(find_field('issue_title').value).to eq('Hello world, a new issue')
expect(find_field('issue_description').value).to eq("We don't want to lose what the user typed")
expect(current_path).to eq(new_project_issue_path(project))
expect(find_field('issue_title').value).to eq('Hello world, a new issue')
expect(find_field('issue_description').value).to eq("We don't want to lose what the user typed")
end
end
end
 
context 'when the terms are enforced' do
before do
enforce_terms
end
context 'when the terms are enforced' do
before do
enforce_terms
end
 
context 'signing out', :js do
it 'allows the user to sign out without a response' do
visit terms_path
context 'signing out', :js do
it 'allows the user to sign out without a response' do
visit terms_path
 
find('.header-user-dropdown-toggle').click
click_link('Sign out')
find('.header-user-dropdown-toggle').click
click_link('Sign out')
 
expect(page).to have_content('Sign in')
expect(page).to have_content('Register')
expect(page).to have_content('Sign in')
expect(page).to have_content('Register')
end
end
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment