Commit d6ee7289 authored by Annabel Dunstone Gray's avatar Annabel Dunstone Gray

Merge branch '20-split-sign-in-and-sign-up' into 'master'

Use separate routes for sign in and sign up

See merge request gitlab-org/gitlab!16482
parents e75fa9e9 519d09c2
import LengthValidator from '~/pages/sessions/new/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new
new LengthValidator(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
});
.signup-page {
.page-wrap {
background-color: $gray-light;
}
.gitlab-logo {
width: 80px;
height: 80px;
}
.signup-box-container {
max-width: 900px;
&.navless-container {
// overriding .devise-layout-html.navless-container to support the sticky footer
// without having a header on size xs
@include media-breakpoint-down(xs) {
padding: 65px $gl-padding; // height of footer
padding-top: $gl-padding;
}
}
}
.signup-heading h2 {
font-weight: $gl-font-weight-bold;
@include media-breakpoint-down(md) {
font-size: $gl-font-size-large;
}
}
.signup-box {
background-color: $white-light;
box-shadow: 0 0 0 1px $border-color;
border-radius: $border-radius;
}
.form-control {
&:active,
&:focus {
background-color: $white-light;
}
}
.devise-errors {
h2 {
font-size: $gl-font-size;
color: $red-700;
}
}
}
...@@ -215,6 +215,12 @@ ...@@ -215,6 +215,12 @@
body { body {
// offset height of fixed header + 1 to avoid scroll // offset height of fixed header + 1 to avoid scroll
height: calc(100% - 51px); height: calc(100% - 51px);
// offset without the header
&.navless {
height: calc(100% - 11px);
}
margin: 0; margin: 0;
padding: 0; padding: 0;
......
...@@ -6,13 +6,19 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -6,13 +6,19 @@ class RegistrationsController < Devise::RegistrationsController
include RecaptchaExperimentHelper include RecaptchaExperimentHelper
include InvisibleCaptcha include InvisibleCaptcha
layout :choose_layout
prepend_before_action :check_captcha, only: :create prepend_before_action :check_captcha, only: :create
before_action :whitelist_query_limiting, only: [:destroy] before_action :whitelist_query_limiting, only: [:destroy]
before_action :ensure_terms_accepted, before_action :ensure_terms_accepted,
if: -> { action_name == 'create' && Gitlab::CurrentSettings.current_application_settings.enforce_terms? } if: -> { action_name == 'create' && Gitlab::CurrentSettings.current_application_settings.enforce_terms? }
def new def new
redirect_to(new_user_session_path) if helpers.use_experimental_separate_sign_up_flow?
@resource = build_resource
else
redirect_to new_user_session_path(anchor: 'register-pane')
end
end end
def create def create
...@@ -144,6 +150,16 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -144,6 +150,16 @@ class RegistrationsController < Devise::RegistrationsController
def stored_location_or_dashboard(user) def stored_location_or_dashboard(user)
stored_location_for(user) || dashboard_projects_path stored_location_for(user) || dashboard_projects_path
end end
# Part of an experiment to build a new sign up flow. Will be resolved
# with https://gitlab.com/gitlab-org/growth/engineering/issues/64
def choose_layout
if helpers.use_experimental_separate_sign_up_flow?
'devise_experimental_separate_sign_up_flow'
else
'devise'
end
end
end end
RegistrationsController.prepend_if_ee('EE::RegistrationsController') RegistrationsController.prepend_if_ee('EE::RegistrationsController')
...@@ -4,4 +4,8 @@ module SessionsHelper ...@@ -4,4 +4,8 @@ module SessionsHelper
def unconfirmed_email? def unconfirmed_email?
flash[:alert] == t(:unconfirmed, scope: [:devise, :failure]) flash[:alert] == t(:unconfirmed, scope: [:devise, :failure])
end end
def use_experimental_separate_sign_up_flow?
::Gitlab.dev_env_or_com? && Feature.enabled?(:experimental_separate_sign_up_flow)
end
end end
- page_title "Sign up" - page_title "Sign up"
= render 'devise/shared/signup_box' - if use_experimental_separate_sign_up_flow?
= render 'devise/shared/experimental_separate_sign_up_flow_box'
- else
= render 'devise/shared/signup_box'
= render 'devise/shared/sign_in_link' = render 'devise/shared/sign_in_link'
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
- if form_based_providers.any? - if form_based_providers.any?
= render 'devise/shared/tabs_ldap' = render 'devise/shared/tabs_ldap'
- else - else
= render 'devise/shared/tabs_normal' - unless use_experimental_separate_sign_up_flow?
= render 'devise/shared/tabs_normal'
.tab-content .tab-content
- if password_authentication_enabled_for_web? || ldap_enabled? || crowd_enabled? - if password_authentication_enabled_for_web? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box' = render 'devise/shared/signin_box'
......
- max_name_length = 128
- max_username_length = 255
.signup-box.p-3.mb-2
.signup-body
= form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors.mt-0
= render "devise/shared/error_messages", resource: resource
= invisible_captcha
.name.form-group
= f.label :name, _('Full name'), class: 'label-bold'
= f.text_field :name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length }, :qa_selector => 'new_user_name_field' }, required: true, title: _("This field is required.")
.username.form-group
= f.label :username, class: 'label-bold'
= f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
%p.validation-error.gl-field-error-ignore.field-validation.mt-1.hide.cred= _('Username is already taken.')
%p.validation-success.gl-field-error-ignore.field-validation.mt-1.hide.cgreen= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.field-validation.mt-1.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
= f.email_field :email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.")
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
= f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
= check_box_tag :terms_opt_in, '1', false, required: true, data: { qa_selector: 'new_user_accept_terms_checkbox' }
= 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
= render_if_exists 'devise/shared/email_opted_in', f: f
.submit-container.mt-3
= f.submit _("Register"), class: "btn-register btn btn-block btn-success mb-0 p-2", data: { qa_selector: 'new_user_register_button' }
%p %p.text-center
%span.light %span.light
Already have login and password? Already have login and password?
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes') = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
...@@ -22,3 +22,8 @@ ...@@ -22,3 +22,8 @@
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' } .login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body .login-body
= render 'devise/sessions/new_base' = render 'devise/sessions/new_base'
- if use_experimental_separate_sign_up_flow?
%p.light.mt-2
= _("Don't have an account yet?")
= link_to _("Register now"), new_registration_path(:user)
- page_description brand_title unless page_description - page_description brand_title unless page_description
-# Needs a redirect on the client side since it's using an anchor to distuingish
-# between sign in and registration. We need to inline the JS to not render
-# anything from this page beforehand.
-# Part of an experiment to build a new sign up flow. Will be removed again with
-# https://gitlab.com/gitlab-org/growth/engineering/issues/64
- if use_experimental_separate_sign_up_flow? && current_path?("sessions#new")
= javascript_tag nonce: true do
:plain
if (window.location.hash === '#register-pane') {
window.location.replace("/users/sign_up")
}
- site_name = "GitLab" - site_name = "GitLab"
%head{ prefix: "og: http://ogp.me/ns#" } %head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" } %meta{ charset: "utf-8" }
......
!!! 5
%html.devise-layout-html.navless{ class: system_message_class }
= render "layouts/head"
%body.ui-indigo.signup-page.application.navless{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
= header_message
= render "layouts/init_client_detection_flags"
.page-wrap
.container.signup-box-container.navless-container.mt-0
= render "layouts/broadcast"
.content
= render "layouts/flash"
.row.mb-3
.col-sm-8.offset-sm-2.col-md-6.offset-md-3.new-session-forms-container
= render_if_exists 'layouts/devise_help_text'
.text-center.signup-heading.mt-3.mb-3
= image_tag(image_url('logo.svg'), class: 'gitlab-logo', alt: 'GitLab Logo')
%h2= _('Register for GitLab.com')
= yield
%hr.footer-fixed
.footer-container
.container
.footer-links
= link_to _("Help"), help_path
= link_to _("About GitLab"), "https://about.gitlab.com/"
= footer_message
---
title: Experimental separate sign up flow
merge_request: 16482
author:
type: other
...@@ -5472,6 +5472,9 @@ msgstr "" ...@@ -5472,6 +5472,9 @@ msgstr ""
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled" msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
msgstr "" msgstr ""
msgid "Don't have an account yet?"
msgstr ""
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'." msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgstr "" msgstr ""
...@@ -13081,6 +13084,12 @@ msgstr "" ...@@ -13081,6 +13084,12 @@ msgstr ""
msgid "Register and see your runners for this project." msgid "Register and see your runners for this project."
msgstr "" msgstr ""
msgid "Register for GitLab.com"
msgstr ""
msgid "Register now"
msgstr ""
msgid "Register with two-factor app" msgid "Register with two-factor app"
msgstr "" msgstr ""
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe 'Signup' do shared_examples 'Signup' do
include TermsHelper include TermsHelper
before do before do
...@@ -13,8 +13,7 @@ describe 'Signup' do ...@@ -13,8 +13,7 @@ describe 'Signup' do
describe 'username validation', :js do describe 'username validation', :js do
before do before do
visit root_path visit new_user_registration_path
click_link 'Register'
end end
it 'does not show an error border if the username is available' do it 'does not show an error border if the username is available' do
...@@ -130,8 +129,7 @@ describe 'Signup' do ...@@ -130,8 +129,7 @@ describe 'Signup' do
describe 'user\'s full name validation', :js do describe 'user\'s full name validation', :js do
before do before do
visit root_path visit new_user_registration_path
click_link 'Register'
end end
it 'does not show an error border if the user\'s fullname length is not longer than 128 characters' do it 'does not show an error border if the user\'s fullname length is not longer than 128 characters' do
...@@ -177,13 +175,17 @@ describe 'Signup' do ...@@ -177,13 +175,17 @@ describe 'Signup' do
end end
it 'creates the user account and sends a confirmation email' do it 'creates the user account and sends a confirmation email' do
visit root_path visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email 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 unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
expect { click_button 'Register' }.to change { User.count }.by(1) expect { click_button 'Register' }.to change { User.count }.by(1)
...@@ -198,13 +200,17 @@ describe 'Signup' do ...@@ -198,13 +200,17 @@ describe 'Signup' do
end end
it 'creates the user account and sends a confirmation email' do it 'creates the user account and sends a confirmation email' do
visit root_path visit new_user_registration_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
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_password', with: new_user.password
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
expect { click_button 'Register' }.to change { User.count }.by(1) expect { click_button 'Register' }.to change { User.count }.by(1)
...@@ -216,13 +222,17 @@ describe 'Signup' do ...@@ -216,13 +222,17 @@ describe 'Signup' do
context "when sigining up with different cased emails" do context "when sigining up with different cased emails" do
it "creates the user successfully" do it "creates the user successfully" do
visit root_path visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email fill_in 'new_user_email', with: new_user.email
fill_in 'new_user_email_confirmation', with: new_user.email.capitalize
fill_in 'new_user_password', with: new_user.password unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email.capitalize
end
fill_in 'new_user_password', with: new_user.password
click_button "Register" click_button "Register"
expect(current_path).to eq dashboard_projects_path expect(current_path).to eq dashboard_projects_path
...@@ -236,13 +246,17 @@ describe 'Signup' do ...@@ -236,13 +246,17 @@ describe 'Signup' do
end end
it 'creates the user account and goes to dashboard' do it 'creates the user account and goes to dashboard' do
visit root_path visit new_user_registration_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_name', with: new_user.name unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_username', with: new_user.username fill_in 'new_user_email_confirmation', with: new_user.email
fill_in 'new_user_email', with: new_user.email end
fill_in 'new_user_email_confirmation', with: new_user.email
fill_in 'new_user_password', with: new_user.password fill_in 'new_user_password', with: new_user.password
click_button "Register" click_button "Register"
expect(current_path).to eq dashboard_projects_path expect(current_path).to eq dashboard_projects_path
...@@ -255,28 +269,34 @@ describe 'Signup' do ...@@ -255,28 +269,34 @@ describe 'Signup' do
it "displays the errors" do it "displays the errors" do
existing_user = create(:user) existing_user = create(:user)
visit root_path visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_email', with: existing_user.email
fill_in 'new_user_password', with: new_user.password fill_in 'new_user_password', with: new_user.password
click_button "Register" click_button "Register"
expect(current_path).to eq user_registration_path expect(current_path).to eq user_registration_path
expect(page).to have_content("errors prohibited this user from being saved")
expect(page).to have_content("Email has already been taken") if Feature.enabled?(:experimental_separate_sign_up_flow)
expect(page).to have_content("Email confirmation doesn't match") expect(page).to have_content("error prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
else
expect(page).to have_content("errors prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
expect(page).to have_content("Email confirmation doesn't match")
end
end end
it 'does not redisplay the password' do it 'does not redisplay the password' do
existing_user = create(:user) existing_user = create(:user)
visit root_path visit new_user_registration_path
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: existing_user.email fill_in 'new_user_email', with: existing_user.email
fill_in 'new_user_password', with: new_user.password fill_in 'new_user_password', with: new_user.password
click_button "Register" click_button "Register"
...@@ -291,13 +311,17 @@ describe 'Signup' do ...@@ -291,13 +311,17 @@ describe 'Signup' do
end end
it 'requires the user to check the checkbox' do it 'requires the user to check the checkbox' do
visit root_path visit new_user_registration_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
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_password', with: new_user.password
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
click_button 'Register' click_button 'Register'
...@@ -306,13 +330,17 @@ describe 'Signup' do ...@@ -306,13 +330,17 @@ describe 'Signup' do
end end
it 'asks the user to accept terms before going to the dashboard' do it 'asks the user to accept terms before going to the dashboard' do
visit root_path visit new_user_registration_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
unless Feature.enabled?(:experimental_separate_sign_up_flow)
fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_name', with: new_user.name fill_in 'new_user_password', with: new_user.password
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 check :terms_opt_in
click_button "Register" click_button "Register"
...@@ -321,3 +349,20 @@ describe 'Signup' do ...@@ -321,3 +349,20 @@ describe 'Signup' do
end end
end end
end end
describe 'With original flow' do
it_behaves_like 'Signup' do
before do
stub_feature_flags(experimental_separate_sign_up_flow: false)
end
end
end
describe 'With experimental flow on GitLab.com' do
it_behaves_like 'Signup' do
before do
expect(Gitlab).to receive(:com?).and_return(true).at_least(:once)
stub_feature_flags(experimental_separate_sign_up_flow: true)
end
end
end
...@@ -634,10 +634,47 @@ describe API::Users do ...@@ -634,10 +634,47 @@ describe API::Users do
end end
describe "GET /users/sign_up" do describe "GET /users/sign_up" do
it "redirects to sign in page" do context 'when experimental_separate_sign_up_flow is active' do
get "/users/sign_up" before do
expect(response).to have_gitlab_http_status(302) stub_feature_flags(experimental_separate_sign_up_flow: true)
expect(response).to redirect_to(new_user_session_path) end
context 'on gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(true)
end
it "shows sign up page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(200)
expect(response).to render_template(:new)
end
end
context 'not on gitlab.com' do
before do
allow(::Gitlab).to receive(:com?).and_return(false)
end
it "redirects to sign in page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
end
end
end
context 'when experimental_separate_sign_up_flow is not active' do
before do
allow(::Gitlab).to receive(:com?).and_return(true)
stub_feature_flags(experimental_separate_sign_up_flow: false)
end
it "redirects to sign in page" do
get "/users/sign_up"
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane'))
end
end end
end end
......
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