diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index 700ca28181..dfaf65a185 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -56,7 +56,8 @@ #= require_tree . document.addEventListener "turbo:load", -> - window.injector = angular.bootstrap document.body, ["Darkswarm"] + try + window.injector = angular.bootstrap document.body, ["Darkswarm"] true document.addEventListener "turbo:before-render", -> diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee deleted file mode 100644 index 8a0a2121de..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee +++ /dev/null @@ -1,19 +0,0 @@ -angular.module('Darkswarm').controller "ForgotCtrl", ($scope, $http, $location, AuthenticationService) -> - $scope.path = "/forgot" - $scope.sent = false - - $scope.submit = -> - if $scope.spree_user.email != null - $http.post("/user/spree_user/password", {spree_user: $scope.spree_user}).then (response)-> - $scope.sent = true - .catch (response) -> - $scope.errors = response.data.error - $scope.user_unconfirmed = (response.status == 401) - else - $scope.errors = t 'email_required' - - $scope.resend_confirmation = -> - $http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.messages = t('devise.confirmations.send_instructions') - .catch (response) -> - $scope.errors = t('devise.confirmations.failed_to_send') diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee deleted file mode 100644 index 63dfb719b4..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee +++ /dev/null @@ -1,36 +0,0 @@ -angular.module('Darkswarm').controller "LoginCtrl", ($scope, $timeout, $location, $http, $window, AuthenticationService, Redirections, Loading) -> - $scope.path = "/login" - - $scope.modalMessage = null - - $scope.$watch (-> - AuthenticationService.modalMessage - ), (newValue) -> - $scope.errors = newValue - - $scope.submit = -> - Loading.message = t 'logging_in' - $http.post("/user/spree_user/sign_in", {spree_user: $scope.spree_user}).then (response)-> - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Login Submit Success', $location.absUrl()]); - if Redirections.after_login - $window.location.href = $window.location.origin + Redirections.after_login - else - $window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments - .catch (response) -> - Loading.clear() - $scope.errors = response.data.message || response.data.error - $scope.user_unconfirmed = (response.data.error == t('devise.failure.unconfirmed')) - - $scope.resend_confirmation = -> - $http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.messages = t('devise.confirmations.send_instructions') - .catch (response) -> - $scope.errors = t('devise.confirmations.failed_to_send') - - $timeout -> - if angular.isDefined($location.search()['validation']) - if $location.search()['validation'] == 'confirmed' - $scope.messages = t('devise.confirmations.confirmed') - if $location.search()['validation'] == 'not_confirmed' - $scope.errors = t('devise.confirmations.not_confirmed') diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee deleted file mode 100644 index 7c742b91f8..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee +++ /dev/null @@ -1,17 +0,0 @@ -angular.module('Darkswarm').controller "SignupCtrl", ($scope, $http, $window, $location, Redirections, AuthenticationService) -> - $scope.path = "/signup" - - $scope.spree_user.password_confirmation = '' - - $scope.errors = - email: null - password: null - - $scope.submit = -> - $http.post("/user/spree_user", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.errors = {email: null, password: null} - $scope.messages = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Signup Submit Success', $location.absUrl()]); - .catch (response) -> - $scope.errors = response.data diff --git a/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee deleted file mode 100644 index 689048722d..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee +++ /dev/null @@ -1,12 +0,0 @@ -angular.module('Darkswarm').controller "AuthenticationCtrl", ($scope, AuthenticationService, SpreeUser)-> - $scope.open = AuthenticationService.open - $scope.toggle = AuthenticationService.toggle - - $scope.spree_user = SpreeUser.spree_user - $scope.isActive = AuthenticationService.isActive - $scope.select = AuthenticationService.select - - $scope.tabs = - login: { active: $scope.isActive('/login') } - signup: { active: $scope.isActive('/signup') } - forgot: { active: $scope.isActive('/forgot') } diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee index c3e07f8c68..294a0c4d10 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageService, Checkout, CurrentUser, CurrentHub, AuthenticationService, SpreeUser, $http) -> +angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageService, Checkout, CurrentUser, CurrentHub, $http) -> $scope.Checkout = Checkout $scope.submitted = false @@ -35,14 +35,9 @@ angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageServ $scope.$broadcast 'purchaseFormInvalid', $scope.formdata $scope.ensureUserIsGuest = (callback = null) -> - $http.post("/user/registered_email", {email: $scope.order.email}).then (response)-> - if response.data.registered == true - $scope.promptLogin() - else + $http.post("/user/registered_email", {email: $scope.order.email}) + .then (response)-> + window.CableReady.perform(response.data) + .catch -> $scope.validateForm() if $scope.submitted callback() if callback - - $scope.promptLogin = -> - SpreeUser.spree_user.email = $scope.order.email - AuthenticationService.pushMessage t('devise.failure.already_registered') - AuthenticationService.open '/login' diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee index a163923597..26bc783743 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module('Darkswarm').controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, AuthenticationService, SpreeUser, $controller) -> +angular.module('Darkswarm').controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, SpreeUser, $controller) -> angular.extend this, $controller('FieldsetMixin', {$scope: $scope}) $scope.name = "details" diff --git a/app/assets/javascripts/darkswarm/directives/auth.js.coffee b/app/assets/javascripts/darkswarm/directives/auth.js.coffee deleted file mode 100644 index aaa8be0def..0000000000 --- a/app/assets/javascripts/darkswarm/directives/auth.js.coffee +++ /dev/null @@ -1,11 +0,0 @@ -angular.module('Darkswarm').directive 'auth', (AuthenticationService) -> - restrict: 'A' - link: (scope, elem, attrs) -> - elem.bind "click", -> - AuthenticationService.open '/' + attrs.auth - - window.addEventListener "login:modal:open", -> - AuthenticationService.open '/login' - - scope.$on "$destroy", -> - window.removeEventListener "login:modal:open" diff --git a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee deleted file mode 100644 index 7c5711d992..0000000000 --- a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee +++ /dev/null @@ -1,57 +0,0 @@ -# This class deals with displaying things in the login modal. It chooses -# the modal tab templates and deals with switching tabs and passing data -# between the tabs. It has direct access to the instance of the login modal, -# and provides that access to other controllers as a service. - -angular.module('Darkswarm').factory "AuthenticationService", (Navigation, $modal, $location, Redirections, Loading)-> - - new class AuthenticationService - selectedPath: "/login" - modalMessage: null - - constructor: -> - if $location.path() in ["/login", "/signup", "/forgot"] || location.pathname is '/register/auth' - @open @initialTab(), @initialTemplate() - - open: (path = false, template = 'authentication.html') => - @modalInstance = $modal.open - templateUrl: template - windowClass: "login-modal medium" - @modalInstance.result.then @close, @close - @selectedPath = path || @selectedPath - Navigation.navigate @selectedPath - - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) - - # Opens the /login tab if returning from email confirmation, - # the /signup tab if opened from the enterprise registration page, - # otherwise opens whichever tab is selected in the URL params ('/login', '/signup', or '/forgot') - initialTab: -> - if angular.isDefined($location.search()['validation']) - '/login' - else if location.pathname is '/register/auth' - '/signup' - else - $location.path() - - # Loads the registration page modal when needed, otherwise the default modal - initialTemplate: -> - if location.pathname is '/register/auth' - 'registration_authentication.html' - else - 'authentication.html' - pushMessage: (message) -> - @modalMessage = String(message) - - select: (path)=> - @selectedPath = path - Navigation.navigate @selectedPath - - isActive: Navigation.isActive - - close: -> - if location.pathname in ["/register", "/register/auth"] - Loading.message = t 'going_back_to_home_page' - location.hash = "" - location.pathname = "/" diff --git a/app/assets/javascripts/darkswarm/services/redirections.js.coffee b/app/assets/javascripts/darkswarm/services/redirections.js.coffee deleted file mode 100644 index a2950b123a..0000000000 --- a/app/assets/javascripts/darkswarm/services/redirections.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -angular.module('Darkswarm').factory "Redirections", ($location)-> - new class Redirections - after_login: $location.search().after_login diff --git a/app/assets/javascripts/templates/authentication.html.haml b/app/assets/javascripts/templates/authentication.html.haml deleted file mode 100644 index db1b5ecd7d..0000000000 --- a/app/assets/javascripts/templates/authentication.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%div{"ng-controller" => "AuthenticationCtrl"} - %tabset - %ng-include{src: "'login.html'"} - %ng-include{src: "'signup.html'"} - %ng-include{src: "'forgot.html'"} -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/forgot.html.haml b/app/assets/javascripts/templates/forgot.html.haml deleted file mode 100644 index 94e85af2bc..0000000000 --- a/app/assets/javascripts/templates/forgot.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -%tab#forgot{ heading: "{{'forgot_password' | t}}", active: "tabs.forgot.active", select: "select(path)"} - %form{ ng: { controller: "ForgotCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.success{"ng-show" => "sent"} - {{ 'password_reset_sent' | t }} - - .alert-box.success{"ng-show" => "messages != null"} - {{ messages }} - - .alert-box.alert{"ng-show" => "errors != null"} - {{ errors }} - %a{ng: {show: 'user_unconfirmed', click: 'resend_confirmation()'}} - = t('devise.confirmations.resend_confirmation_email') - - .row - .large-12.columns - %label{for: "email"} {{'signup_email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: 1, - inputmode: "email", - "ng-model" => "spree_user.email"} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "3", - type: "submit", - value: "{{'reset_password' | t}}"} - diff --git a/app/assets/javascripts/templates/login.html.haml b/app/assets/javascripts/templates/login.html.haml deleted file mode 100644 index 7ca17bfbe9..0000000000 --- a/app/assets/javascripts/templates/login.html.haml +++ /dev/null @@ -1,44 +0,0 @@ -%tab#login-content{ heading: "{{'label_login' | t}}", active: "tabs.login.active", select: "select(path)"} - %form{ ng: { controller: "LoginCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.alert{"ng-show" => "errors != null"} - {{ errors }} - %a{ng: {show: 'user_unconfirmed', click: 'resend_confirmation()'}} - = t('devise.confirmations.resend_confirmation_email') - .alert-box.success{ng: {show: 'messages != null'}} - {{ messages }} - .row - .large-12.columns - %label{for: "email"} {{'email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: "1", - inputmode: "email", - "ng-model" => "spree_user.email"} - .row - .large-12.columns - %label{for: "password"} {{'password' | t}} - %input.title.input-text{name: "password", - type: "password", - id: "password", - autocomplete: "off", - tabindex: "2", - inputmode: "password", - "ng-model" => "spree_user.password"} - .row - .large-12.columns - %input{name: "remember_me", - type: "checkbox", - id: "remember_me", - value: "1", - tabindex: "3", - "ng-model" => "spree_user.remember_me"} - %label{for: "remember_me"} {{'remember_me' | t}} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "4", - type: "submit", - value: "{{'label_login' | t}}"} diff --git a/app/assets/javascripts/templates/registration_authentication.html.haml b/app/assets/javascripts/templates/registration_authentication.html.haml deleted file mode 100644 index b5a525c3f2..0000000000 --- a/app/assets/javascripts/templates/registration_authentication.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -.container - .row.modal-centered - %h2 {{'js.registration.welcome_to_ofn' | t}} - %h5 {{'js.registration.signup_or_login' | t}}: - %div{"ng-controller" => "AuthenticationCtrl"} - %tabset - %ng-include{src: "'signup.html'"} - %ng-include{src: "'login.html'"} - %ng-include{src: "'forgot.html'"} - %div{ ng: { show: "active('/signup')"} } - %hr - {{'js.registration.have_an_account' | t}} - %a{ href: "", ng: { click: "select('/login')"}} - {{'js.registration.action_login' | t}} - -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/signup.html.haml b/app/assets/javascripts/templates/signup.html.haml deleted file mode 100644 index 4ee026adb5..0000000000 --- a/app/assets/javascripts/templates/signup.html.haml +++ /dev/null @@ -1,51 +0,0 @@ -%tab#sign-up-content{ heading: "{{'label_signup' | t}}", active: 'tabs.signup.active', select: "select(path)"} - %form{ ng: { controller: "SignupCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.success{ng: {show: 'messages != null'}} - {{ messages }} - .large-12.columns - .alert-box.alert{ng: {show: 'errors.message != null'}} - {{ errors.message }} - .row - .large-12.columns - %label{for: "email"} {{'signup_email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: 1, - inputmode: "email", - "ng-model" => "spree_user.email"} - %span.error{"ng-show" => "errors.email != null"} - {{ errors.email.join(' ') }} - .row - .large-12.columns - %label{for: "password"} {{'choose_password' | t}} - %input.title.input-text{name: "password", - type: "password", - id: "password", - autocomplete: "off", - tabindex: 2, - inputmode: "password", - "ng-model" => "spree_user.password"} - %span.error{"ng-show" => "errors.password != null"} - {{ errors.password.join(' ') }} - .row - .large-12.columns - %label{for: "password_confirmation"} {{'confirm_password' | t}} - %input.title.input-text{name: "password_confirmation", - type: "password", - id: "password_confirmation", - autocomplete: "off", - tabindex: 2, - inputmode: "password", - "ng-model" => "spree_user.password_confirmation"} - %span.error{"ng-show" => "errors.password_confirmation != null"} - {{ errors.password_confirmation.join(' ') }} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "3", - type: "submit", - value: "{{'action_signup' | t}}"} - diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d62aa2b9d9..b9a40dafe5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -38,6 +38,7 @@ class ApplicationController < ActionController::Base include Spree::Core::ControllerHelpers::Common before_action :set_cache_headers # prevent cart emptying via cache when using back button #1213 + before_action :set_after_login_url include RawParams include EnterprisesHelper @@ -61,15 +62,9 @@ class ApplicationController < ActionController::Base end def set_checkout_redirect - referer_path = OpenFoodNetwork::RefererParser.path(request.referer) - if referer_path - is_checkout_path_the_referer = [main_app.checkout_path].include?(referer_path) - session["spree_user_return_to"] = if is_checkout_path_the_referer - referer_path - else - main_app.root_path - end - end + return unless URI(request.referer.to_s).path == main_app.checkout_path + + session["spree_user_return_to"] = main_app.checkout_path end def shopfront_session @@ -102,6 +97,10 @@ class ApplicationController < ActionController::Base private + def set_after_login_url + store_location_for(:spree_user, params[:after_login]) if params[:after_login] + end + def shopfront_redirect session[:shopfront_redirect] end @@ -111,7 +110,7 @@ class ApplicationController < ActionController::Base end def require_distributor_chosen - unless @distributor = current_distributor + unless (@distributor = current_distributor) redirect_to main_app.root_path false end diff --git a/app/controllers/payment_gateways/stripe_controller.rb b/app/controllers/payment_gateways/stripe_controller.rb index 6cbd3ee871..cabf14b4bf 100644 --- a/app/controllers/payment_gateways/stripe_controller.rb +++ b/app/controllers/payment_gateways/stripe_controller.rb @@ -47,7 +47,7 @@ module PaymentGateways return if session[:access_token] || params[:order_token] || spree_current_user flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to root_path(anchor: "login", after_login: request.original_fullpath) end def validate_stock diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index e232574b63..92e39715a8 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -9,7 +9,7 @@ class PaymentsController < BaseController @payment = Spree::Payment.find(params[:id]) authorize! :show, @payment.order - if url = @payment.cvv_response_message + if (url = @payment.cvv_response_message) redirect_to url else redirect_to order_url(@payment.order) @@ -21,7 +21,9 @@ class PaymentsController < BaseController def require_logged_in return if session[:access_token] || spree_current_user + store_location_for :spree_user, request.original_fullpath + flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end end diff --git a/app/controllers/registration_controller.rb b/app/controllers/registration_controller.rb index 29b523289e..7352786e74 100644 --- a/app/controllers/registration_controller.rb +++ b/app/controllers/registration_controller.rb @@ -19,7 +19,7 @@ class RegistrationController < BaseController def check_user if spree_current_user.nil? - redirect_to registration_auth_path(anchor: "signup?after_login=#{request.env['PATH_INFO']}") + redirect_to registration_auth_path(anchor: "/signup", after_login: request.original_fullpath) elsif !spree_current_user.can_own_more_enterprises? render :limit_reached end diff --git a/app/controllers/split_checkout_controller.rb b/app/controllers/split_checkout_controller.rb index ac3eefad89..013e99a2fe 100644 --- a/app/controllers/split_checkout_controller.rb +++ b/app/controllers/split_checkout_controller.rb @@ -58,7 +58,7 @@ class SplitCheckoutController < ::BaseController return unless selected_payment_method&.external_gateway? return unless (redirect_url = selected_payment_method.external_payment_url(order: @order)) - render operations: cable_car.redirect_to(url: URI(redirect_url)) + render operations: cable_car.redirect_to(url: redirect_url) true end diff --git a/app/controllers/spree/orders_controller.rb b/app/controllers/spree/orders_controller.rb index 1e522e0eca..f467dbd196 100644 --- a/app/controllers/spree/orders_controller.rb +++ b/app/controllers/spree/orders_controller.rb @@ -139,8 +139,10 @@ module Spree def require_order_authentication return if session[:access_token] || params[:order_token] || spree_current_user + store_location_for :spree_user, request.original_fullpath + flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end def order_to_update diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index 2b5b0a93b6..6b1572757c 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -16,24 +16,6 @@ module Spree include I18nHelper before_action :set_locale - # Overridden due to bug in Devise. - # respond_with resource, :location => new_session_path(resource_name) - # is generating bad url /session/new.user - # - # overridden to: - # respond_with resource, :location => spree.login_path - # - def create - self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name]) - - if resource.errors.empty? - set_flash_message(:notice, :send_instructions) if is_navigational_format? - respond_with resource, location: spree.login_path - else - respond_with_navigational(resource) { render :new } - end - end - # Devise::PasswordsController allows for blank passwords. # Silly Devise::PasswordsController! # Fixes spree/spree#2190. diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 6de8e67b30..342b5dddc9 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -6,11 +6,12 @@ require "spree/core/controller_helpers/order" module Spree class UserSessionsController < Devise::SessionsController - helper 'spree/base' - include Spree::Core::ControllerHelpers::Auth include Spree::Core::ControllerHelpers::Common include Spree::Core::ControllerHelpers::Order + include CablecarResponses + + helper 'spree/base' before_action :set_checkout_redirect, only: :create after_action :ensure_valid_locale_persisted, only: :create @@ -19,25 +20,16 @@ module Spree authenticate_spree_user! if spree_user_signed_in? - respond_to do |format| - format.html { - flash[:success] = t('devise.success.logged_in_succesfully') - redirect_back_or_default(after_sign_in_path_for(spree_current_user)) - } - format.js { - render json: { email: spree_current_user.login }, status: :ok - } - end + flash[:success] = t('devise.success.logged_in_succesfully') + + render operations: cable_car.redirect_to( + url: return_url_or_default(after_sign_in_path_for(spree_current_user)) + ) else - respond_to do |format| - format.html { - flash.now[:error] = t('devise.failure.invalid') - render :new - } - format.js { - render json: { message: t('devise.failure.invalid') }, status: :unauthorized - } - end + render status: :unauthorized, operations: cable_car.inner_html( + "#login-feedback", + partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.invalid') }) + ) end end @@ -57,11 +49,6 @@ module Spree Spree.t(:login) end - def redirect_back_or_default(default) - redirect_to(session["spree_user_return_to"] || default) - session["spree_user_return_to"] = nil - end - def ensure_valid_locale_persisted # When creating a new user session we have to wait until after a successful # login to be able to persist a selected locale on the current user diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 0b4ded410a..cf87ba49da 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -4,6 +4,7 @@ module Spree class UsersController < ::BaseController include Spree::Core::ControllerHelpers include I18nHelper + include CablecarResponses layout 'darkswarm' @@ -26,16 +27,33 @@ module Spree # Endpoint for queries to check if a user is already registered def registered_email - user = Spree::User.find_by email: params[:email] - render json: { registered: user.present? } + registered = Spree::User.find_by(email: params[:email]).present? + + if registered + render status: :ok, operations: cable_car. + inner_html( + "#login-feedback", + partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.already_registered') }) + ). + dispatch_event(name: "login:modal:open") + else + head :not_found + end end def create @user = Spree::User.new(user_params) + if @user.save - redirect_back_or_default(main_app.root_url) + render operations: cable_car.inner_html( + "#signup-feedback", + partial("layouts/alert", locals: { type: "success", message: t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') }) + ) else - render :new + render status: :unprocessable_entity, operations: cable_car.morph( + "#signup-tab", + partial("layouts/signup_tab", locals: { signup_form_user: @user }) + ) end end diff --git a/app/controllers/user_confirmations_controller.rb b/app/controllers/user_confirmations_controller.rb index b024504345..5575c4eee7 100644 --- a/app/controllers/user_confirmations_controller.rb +++ b/app/controllers/user_confirmations_controller.rb @@ -3,6 +3,7 @@ class UserConfirmationsController < DeviseController # Needed for access to current_ability, so we can authorize! actions include Spree::Core::ControllerHelpers::Auth + include CablecarResponses # GET /resource/confirmation/new def new @@ -20,6 +21,12 @@ class UserConfirmationsController < DeviseController else set_flash_message(:error, :confirmation_not_sent) end + else + render operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "success", message: t("devise.confirmations.send_instructions") }) + ) + return end respond_with_navigational(resource){ redirect_to login_path } @@ -39,22 +46,25 @@ class UserConfirmationsController < DeviseController end def after_confirmation_path_for(resource) - result = - if resource.errors.empty? - 'confirmed' - else - 'not_confirmed' - end + result = resource.errors.empty? ? "confirmed" : "not_confirmed" if result == 'confirmed' && resource.reset_password_token.present? - raw_reset_password_token = resource.regenerate_reset_password_token return spree.edit_spree_user_password_path( - reset_password_token: raw_reset_password_token + reset_password_token: resource.regenerate_reset_password_token ) end - path = (session[:confirmation_return_url] || login_path).to_s - path += path.include?('?') ? '&' : '?' - path + "validation=#{result}" + path = session[:confirmation_return_url] || root_path(anchor: "/login") + append_query_to_url(path, "validation", result) + end + + private + + def append_query_to_url(url, key, value) + uri = URI.parse(url.to_s) + query = URI.decode_www_form(uri.query || "") << [key, value] + uri.query = URI.encode_www_form(query) + + uri.to_s end end diff --git a/app/controllers/user_passwords_controller.rb b/app/controllers/user_passwords_controller.rb index c33a1716f3..604e4a113d 100644 --- a/app/controllers/user_passwords_controller.rb +++ b/app/controllers/user_passwords_controller.rb @@ -1,38 +1,36 @@ # frozen_string_literal: true class UserPasswordsController < Spree::UserPasswordsController + include CablecarResponses + layout 'darkswarm' - before_action :set_admin_redirect, only: :edit - def create - render_unconfirmed_response && return if user_unconfirmed? + return render_unconfirmed_response if user_unconfirmed? self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name]) if resource.errors.empty? - set_flash_message(:success, :send_instructions) if is_navigational_format? - respond_with resource, location: main_app.login_path + render operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "success", message: t(:password_reset_sent) }) + ) else - respond_to do |format| - format.html do - respond_with_navigational(resource) { render :new } - end - format.js do - render json: { error: t('email_not_found') }, status: :not_found - end - end + render status: :not_found, operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "alert", message: t(:email_not_found) }) + ) end end private - def set_admin_redirect - session["spree_user_return_to"] = params[:return_to] if params[:return_to] - end - def render_unconfirmed_response - render json: { error: t('email_unconfirmed') }, status: :unauthorized + render status: :unprocessable_entity, operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", + locals: { type: "alert", message: t(:email_unconfirmed), unconfirmed: true }) + ) end def user_unconfirmed? diff --git a/app/views/checkout/_authentication.html.haml b/app/views/checkout/_authentication.html.haml index d157901059..d3362107a8 100644 --- a/app/views/checkout/_authentication.html.haml +++ b/app/views/checkout/_authentication.html.haml @@ -3,17 +3,17 @@ .small-12.columns.text-center %h3.pad-top = t :checkout_headline - .row.pad-top - -if guest_checkout_allowed? + .row.pad-top{ "data-controller": "login-modal" } + - if guest_checkout_allowed? .small-5.columns.text-center - %button.primary.expand{"auth" => "login"} + %button.primary.expand{ "data-action": "click->login-modal#call" } = t :label_login .small-2.columns.text-center %p.pad-top= "#{t :action_or}" .small-5.columns.text-center %button.neutral-btn.dark.expand{"ng-click" => "enabled = true"} = t :checkout_as_guest - -else + - else .small-6.columns.small-centered - %button.primary.expand{"auth" => "login"} + %button.primary.expand{ "data-action": "click->login-modal#call" } = t :label_login diff --git a/app/views/layouts/_alert.html.haml b/app/views/layouts/_alert.html.haml new file mode 100644 index 0000000000..539031e1fd --- /dev/null +++ b/app/views/layouts/_alert.html.haml @@ -0,0 +1,5 @@ +.alert-box{ class: "#{type}" } + = message + - if local_assigns[:unconfirmed] + %a{ "data-action": "login-modal#resend_confirmation" } + = t('devise.confirmations.resend_confirmation_email') \ No newline at end of file diff --git a/app/views/layouts/_forgot_tab.html.haml b/app/views/layouts/_forgot_tab.html.haml new file mode 100644 index 0000000000..47ad3c03d2 --- /dev/null +++ b/app/views/layouts/_forgot_tab.html.haml @@ -0,0 +1,12 @@ +#forgot-tab + = form_with url: spree_user_password_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#forgot-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, inputmode: "email", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.submit t(:reset_password), { class: "button primary", tabindex: 2 } diff --git a/app/views/layouts/_login_modal.html.haml b/app/views/layouts/_login_modal.html.haml new file mode 100644 index 0000000000..b5fda75568 --- /dev/null +++ b/app/views/layouts/_login_modal.html.haml @@ -0,0 +1,24 @@ +%div{"data-controller": "login-modal" } + .reveal-modal-bg.fade{ "data-login-modal-target": "background", "data-action": "click->login-modal#close" } + + .reveal-modal.fade.login-modal.medium{ "data-login-modal-target": "modal" } + %div{ "data-controller": "tabs" } + %dl.tabs + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_login) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_signup) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:forgot_password) + + .tabs-content + .content.active + %div{ data: { "tabs-target": "content" } } + = render "layouts/login_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/signup_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/forgot_tab" + + %a.close-reveal-modal{ "data-action": "click->login-modal#close" } + %i.ofn-i_009-close diff --git a/app/views/layouts/_login_tab.html.haml b/app/views/layouts/_login_tab.html.haml new file mode 100644 index 0000000000..06a09b1d85 --- /dev/null +++ b/app/views/layouts/_login_tab.html.haml @@ -0,0 +1,24 @@ +#login-content + = form_with url: spree.spree_user_session_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#login-feedback + - confirmation_result = request.query_parameters[:validation] + - if confirmation_result.in? ["confirmed", "not_confirmed"] + .alert-box{ class: "#{confirmation_result == "confirmed" ? "success" : "alert" }" } + = t("devise.confirmations.#{confirmation_result}") + + .row + .large-12.columns + = form.label :email, t(:email) + = form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.label :password, t(:password) + = form.password_field :password, { tabindex: 2, inputmode: "password" } + .row + .large-12.columns + = form.check_box :remember_me, { tabindex: 3 } + = form.label :remember_me, t(:remember_me) + .row + .large-12.columns + = form.submit t(:label_login), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/_signup_tab.html.haml b/app/views/layouts/_signup_tab.html.haml new file mode 100644 index 0000000000..5d2af646e5 --- /dev/null +++ b/app/views/layouts/_signup_tab.html.haml @@ -0,0 +1,25 @@ +- signup_form_user = Spree::User.new if local_assigns[:signup_form_user].nil? + +#signup-tab + = form_with model: signup_form_user, url: spree.account_path, scope: :user, data: { remote: "true" } do |form| + .row + .large-12.columns#signup-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + = form.error_message_on :email + .row + .large-12.columns + = form.label :password, t(:choose_password) + = form.password_field :password, { tabindex: 2, autocomplete: "off" } + = form.error_message_on :password + .row + .large-12.columns + = form.label :password_confirmation, t(:confirm_password) + = form.password_field :password_confirmation, { tabindex: 3, autocomplete: "off" } + = form.error_message_on :password_confirmation + .row + .large-12.columns + = form.submit t(:action_signup), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index fedbcdddfc..23a0aeda5e 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -57,3 +57,5 @@ = yield :injection_data = render "layouts/matomo_tag" + + = render "layouts/login_modal" diff --git a/app/views/registration/authenticate.html.haml b/app/views/registration/authenticate.html.haml index 2b65757a5d..4b62d71c7c 100644 --- a/app/views/registration/authenticate.html.haml +++ b/app/views/registration/authenticate.html.haml @@ -1 +1,28 @@ -%div{"ng-controller" => "AuthenticationCtrl"} \ No newline at end of file +%div{"data-controller": "login-modal" } + .reveal-modal-bg.fade.in{ "data-login-modal-target": "background", "data-action": "click->login-modal#returnHome", style: "display: block;" } + + .reveal-modal.fade.login-modal.medium.in{ "data-login-modal-target": "modal", style: "display: block;" } + .row.modal-centered + %h2= t('js.registration.welcome_to_ofn') + %h5= t('js.registration.signup_or_login') + + %div{ "data-controller": "tabs" } + %dl.tabs + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_signup) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_login) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:forgot_password) + + .tabs-content + .content.active + %div{ data: { "tabs-target": "content" } } + = render "layouts/signup_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/login_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/forgot_tab" + + %a.close-reveal-modal{ "data-action": "click->login-modal#returnHome" } + %i.ofn-i_009-close diff --git a/app/views/shared/_login.html.haml b/app/views/shared/_login.html.haml deleted file mode 100644 index 5c4d579944..0000000000 --- a/app/views/shared/_login.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- if spree_current_user.nil? - %li#login-link= link_to t(:label_login), "#login", id: "sidebarLoginButton", class: "sidebar-button" - %li#login-name.hide - %li.divider - %li#sign-up-link= link_to t(:label_signup), "#signup", id: "sidebarSignUpButton", class: "sidebar-button" - %li#sign-out-link.hide= link_to "Sign Out", "/logout" -- else - %li#login-link.hide= link_to t(:label_login), "#sidebar", id: "sidebarLoginButton", class: "sidebar-button" - %li#login-name= link_to "#{spree_current_user.email}", "#" - %li.divider - %li#sign-up-link.hide= link_to t(:label_signup), "#" - %li#sign-out-link= link_to t(:label_logout), "/logout" diff --git a/app/views/shared/menu/_signed_out.html.haml b/app/views/shared/menu/_signed_out.html.haml index a5d527632a..570c707b31 100644 --- a/app/views/shared/menu/_signed_out.html.haml +++ b/app/views/shared/menu/_signed_out.html.haml @@ -1,5 +1,5 @@ -%li#login-link - %a{"auth" => "login"} +%li#login-link{ "data-controller": "login-modal" } + %a{"auth": "login", "data-action": "click->login-modal#call" } %img{ src: image_pack_path("menu/icn-login.svg") } %span = t 'label_login' diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js new file mode 100644 index 0000000000..941df160dd --- /dev/null +++ b/app/webpacker/controllers/login_modal_controller.js @@ -0,0 +1,79 @@ +import { Controller } from "stimulus" +import CableReady from "cable_ready" + +export default class extends Controller { + static targets = ["background", "modal", "email"] + static values = { email: String } + + connect() { + if(this.hasModalTarget) { + window.addEventListener("login:modal:open", this.open) + + if(location.hash.substr(1).includes("/login")) { + this.open() + } + } + } + + call(event) { + event.preventDefault() + window.dispatchEvent(new Event("login:modal:open")) + } + + emailOnInput(event) { + this.emailValue = event.currentTarget.value + this.emailTargets.forEach((element) => { + element.value = this.emailValue + }) + } + + open = () => { + if(!location.hash.substr(1).includes("/login")) { + history.pushState({}, "", "#/login") + } + + this.backgroundTarget.style.display = "block" + this.modalTarget.style.display = "block" + + setTimeout(() => { + this.modalTarget.classList.add("in") + this.backgroundTarget.classList.add("in") + document.querySelector("body").classList.add("modal-open") + }) + + window._paq?.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) + } + + close() { + history.pushState({}, "", window.location.pathname + window.location.search) + + this.modalTarget.classList.remove("in") + this.backgroundTarget.classList.remove("in") + + document.querySelector("body").classList.remove("modal-open") + + setTimeout(() => { + this.backgroundTarget.style.display = "none" + this.modalTarget.style.display = "none" + }, 200) + } + + resend_confirmation() { + fetch("/user/spree_user/confirmation", { + method: "POST", + body: JSON.stringify({ + spree_user: { email: this.emailValue } + }) + }).then(data => data.json()).then(CableReady.perform) + } + + returnHome() { + window.location = "/" + } + + disconnect() { + if(this.hasModalTarget) { + window.removeEventListener("login:modal:open", this.open) + } + } +} diff --git a/app/webpacker/controllers/tabs_controller.js b/app/webpacker/controllers/tabs_controller.js new file mode 100644 index 0000000000..9d9995b94e --- /dev/null +++ b/app/webpacker/controllers/tabs_controller.js @@ -0,0 +1,36 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["tab", "content"] + + select(event) { + this.setCurrentTab(this.tabTargets.indexOf(event.currentTarget)) + } + + // private + + connect() { + this.setCurrentTab() + } + + setCurrentTab(tabIndex = 0) { + this.showSelectedContent(tabIndex) + this.setButtonActiveClass(tabIndex) + } + + showSelectedContent(tabIndex) { + this.contentTargets.forEach((element, index) => { + element.hidden = index !== tabIndex + }) + } + + setButtonActiveClass(tabIndex) { + this.tabTargets.forEach((element, index) => { + if(index === tabIndex) { + element.classList.add("active") + } else { + element.classList.remove("active") + } + }) + } +} diff --git a/app/webpacker/css/darkswarm/pages/login_modal.scss b/app/webpacker/css/darkswarm/pages/login_modal.scss index 98ee4730c7..b72763eb13 100644 --- a/app/webpacker/css/darkswarm/pages/login_modal.scss +++ b/app/webpacker/css/darkswarm/pages/login_modal.scss @@ -5,6 +5,21 @@ .login-modal { background: $modal-background-color; + visibility: visible; + position: fixed; + top: 3em; + + a.active { + background-color: white; + + &:hover { + background-color: white; + } + } + + span.formError { + @extend .error; + } .tabs-content { background: $modal-content-background-color; diff --git a/app/webpacker/packs/application.js b/app/webpacker/packs/application.js index 2610d9bee3..2d04d92039 100644 --- a/app/webpacker/packs/application.js +++ b/app/webpacker/packs/application.js @@ -14,6 +14,7 @@ import { CableCar } from "mrujs/plugins" import * as Turbo from "@hotwired/turbo" window.Turbo = Turbo +window.CableReady = CableReady mrujs.start({ plugins: [ new CableCar(CableReady) diff --git a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee index 2fd9fbb4c7..079d3206c8 100644 --- a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee +++ b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee @@ -1,5 +1,4 @@ -angular.module('Darkswarm').factory "CookiesBannerService", (Navigation, $modal, $location, Redirections, Loading)-> - +angular.module('Darkswarm').factory "CookiesBannerService", (Navigation, $modal, $location, Loading)-> new class CookiesBannerService modalMessage: null isEnabled: false diff --git a/lib/spree/core/controller_helpers/auth.rb b/lib/spree/core/controller_helpers/auth.rb index 85c4e91095..98b1aa70b5 100644 --- a/lib/spree/core/controller_helpers/auth.rb +++ b/lib/spree/core/controller_helpers/auth.rb @@ -29,7 +29,8 @@ module Spree redirect_to '/unauthorized' else store_location - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end end @@ -49,9 +50,8 @@ module Spree session['spree_user_return_to'] = request.fullpath.gsub('//', '/') end - def redirect_back_or_default(default) - redirect_to(session["spree_user_return_to"] || default) - session["spree_user_return_to"] = nil + def return_url_or_default(default) + session.delete("spree_user_return_to") || default end # Need to generate an API key for a user due to some actions potentially diff --git a/spec/controllers/registration_controller_spec.rb b/spec/controllers/registration_controller_spec.rb index 29af1c0e91..363b77704d 100644 --- a/spec/controllers/registration_controller_spec.rb +++ b/spec/controllers/registration_controller_spec.rb @@ -6,7 +6,7 @@ describe RegistrationController, type: :controller do describe "redirecting when user not logged in" do it "index" do get :index - expect(response).to redirect_to registration_auth_path(anchor: "signup?after_login=/register") + expect(response).to redirect_to registration_auth_path(anchor: "/signup", after_login: "/register") end end diff --git a/spec/controllers/spree/admin/base_controller_spec.rb b/spec/controllers/spree/admin/base_controller_spec.rb index 887118b665..7e53deb55e 100644 --- a/spec/controllers/spree/admin/base_controller_spec.rb +++ b/spec/controllers/spree/admin/base_controller_spec.rb @@ -12,7 +12,7 @@ describe Spree::Admin::BaseController, type: :controller do it "redirects to Angular login" do spree_get :index - expect(response).to redirect_to root_path(anchor: "login?after_login=/spree/admin/base") + expect(response).to redirect_to root_path(anchor: "/login", after_login: "/spree/admin/base") end describe "rendering as json ActiveModelSerializer" do diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 91307e6d7b..ef221178c7 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -77,7 +77,7 @@ describe Spree::OrdersController, type: :controller do it "redirects to unauthorized" do get :show, params: { id: order.number } - expect(response).to redirect_to(root_path(anchor: "login?after_login=#{order_path(order)}")) + expect(response).to redirect_to(root_path(anchor: "/login", after_login: order_path(order))) expect(flash[:error]).to eq("Please log in to view your order.") end end diff --git a/spec/controllers/spree/user_sessions_controller_spec.rb b/spec/controllers/spree/user_sessions_controller_spec.rb index 2885f53fc3..34053783b7 100644 --- a/spec/controllers/spree/user_sessions_controller_spec.rb +++ b/spec/controllers/spree/user_sessions_controller_spec.rb @@ -10,12 +10,13 @@ describe Spree::UserSessionsController, type: :controller do end describe "create" do - context "succeed" do + context "success" do context "when referer is not '/checkout'" do it "redirects to root" do - spree_post :create, spree_user: { email: user.email, password: user.password }, - use_route: :spree - expect(response).to redirect_to root_path + spree_post :create, spree_user: { email: user.email, password: user.password } + + expect(response).to have_http_status(:ok) + expect(response.body).to match(root_path).and match("redirect") end end @@ -23,12 +24,24 @@ describe Spree::UserSessionsController, type: :controller do before { @request.env['HTTP_REFERER'] = 'http://test.com/checkout' } it "redirects to checkout" do - spree_post :create, spree_user: { email: user.email, password: user.password }, - use_route: :spree - expect(response).to redirect_to checkout_path + spree_post :create, spree_user: { email: user.email, password: user.password } + + expect(response).to have_http_status(:ok) + expect(response.body).to match(checkout_path).and match("redirect") end end end + + context "failing to log in" do + render_views + + it "returns an error" do + spree_post :create, spree_user: { email: user.email, password: "wrong" } + + expect(response).to have_http_status(:unauthorized) + expect(response.body).to include "Invalid email or password" + end + end end describe "destroy" do diff --git a/spec/controllers/spree/users_controller_spec.rb b/spec/controllers/spree/users_controller_spec.rb index a1855cea11..9a0e4298fa 100644 --- a/spec/controllers/spree/users_controller_spec.rb +++ b/spec/controllers/spree/users_controller_spec.rb @@ -60,14 +60,14 @@ describe Spree::UsersController, type: :controller do let!(:user) { create(:user) } - it "returns true if email corresponds to a registered user" do + it "returns ok (200) if email corresponds to a registered user" do post :registered_email, params: { email: user.email } - expect(json_response['registered']).to eq true + expect(response).to have_http_status(:ok) end - it "returns false if email does not correspond to a registered user" do + it "returns not_found (404) if email does not correspond to a registered user" do post :registered_email, params: { email: 'nonregistereduser@example.com' } - expect(json_response['registered']).to eq false + expect(response).to have_http_status(:not_found) end end diff --git a/spec/controllers/user_confirmations_controller_spec.rb b/spec/controllers/user_confirmations_controller_spec.rb index fd78ef500e..fd32ca2a37 100644 --- a/spec/controllers/user_confirmations_controller_spec.rb +++ b/spec/controllers/user_confirmations_controller_spec.rb @@ -22,7 +22,7 @@ describe UserConfirmationsController, type: :controller do end it "redirects the user to login" do - expect(response).to redirect_to login_path(validation: 'not_confirmed') + expect(response).to redirect_to root_path(anchor: "/login", validation: "not_confirmed") end end @@ -34,19 +34,21 @@ describe UserConfirmationsController, type: :controller do it "redirects the user to #/login by default" do spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to login_path(validation: 'confirmed') + expect(response).to redirect_to root_path(anchor: "/login", validation: "confirmed") end it "redirects to previous url, if present" do - session[:confirmation_return_url] = producers_path + '#/login' + session[:confirmation_return_url] = producers_path(anchor: "#/login") spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to producers_path + '#/login?validation=confirmed' + expect(response).to redirect_to producers_path(anchor: "#/login", validation: "confirmed") end it "redirects to previous url on /register path" do - session[:confirmation_return_url] = registration_path + '#/signup?after_login=%2Fregister' + session[:confirmation_return_url] = registration_path(anchor: "#/signup", after_login: "/register") spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to registration_path + '#/signup?after_login=%2Fregister&validation=confirmed' + expect(response). + to redirect_to registration_path(anchor: "#/signup", + after_login: "/register", validation: "confirmed") end it "redirects to set password page, if user needs to reset their password" do diff --git a/spec/controllers/user_passwords_controller_spec.rb b/spec/controllers/user_passwords_controller_spec.rb index c90a2a3917..a2e5861455 100644 --- a/spec/controllers/user_passwords_controller_spec.rb +++ b/spec/controllers/user_passwords_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe UserPasswordsController, type: :controller do - include OpenFoodNetwork::EmailHelper + render_views let(:user) { create(:user) } let(:unconfirmed_user) { create(:user, confirmed_at: nil) } @@ -13,30 +13,35 @@ describe UserPasswordsController, type: :controller do end describe "create" do - it "returns errors" do - spree_post :create, spree_user: {} - expect(response.status).to eq 200 - expect(response).to render_template "spree/user_passwords/new" + it "returns 404 if user is not found" do + spree_post :create, spree_user: { email: "xxxxxxxxxx@example.com" } + expect(response.status).to eq 404 + expect(response.body).to match I18n.t(:email_not_found) end - it "redirects to login when data is valid" do + it "returns 422 if user is registered but not confirmed" do + spree_post :create, spree_user: { email: unconfirmed_user.email } + expect(response.status).to eq 422 + expect(response.body).to match I18n.t(:email_unconfirmed) + end + + it "returns 200 when password reset was successful" do spree_post :create, spree_user: { email: user.email } - expect(response).to be_redirect + expect(response.status).to eq 200 + expect(response.body).to match I18n.t(:password_reset_sent) end end describe "edit" do context "when given a redirect" do it "stores the redirect path in 'spree_user_return_to'" do - spree_post :edit, reset_password_token: "token", return_to: "/return_path" + spree_post :edit, reset_password_token: "token", after_login: "/return_path" expect(session["spree_user_return_to"]).to eq "/return_path" end end end it "renders Darkswarm" do - setup_email - user.send_reset_password_instructions user.reload @@ -44,19 +49,4 @@ describe UserPasswordsController, type: :controller do expect(response).to render_template "user_passwords/edit" end - - describe "via ajax" do - it "returns error when email not found" do - post :create, xhr: true, params: { spree_user: {}, use_route: :spree } - expect(response.status).to eq 404 - expect(json_response).to eq 'error' => I18n.t('email_not_found') - end - - it "returns error when user is unconfirmed" do - post :create, xhr: true, - params: { spree_user: { email: unconfirmed_user.email }, use_route: :spree } - expect(response.status).to eq 401 - expect(json_response).to eq 'error' => I18n.t('email_unconfirmed') - end - end end diff --git a/spec/javascripts/stimulus/tabs_controller_test.js b/spec/javascripts/stimulus/tabs_controller_test.js new file mode 100644 index 0000000000..a67296bd0b --- /dev/null +++ b/spec/javascripts/stimulus/tabs_controller_test.js @@ -0,0 +1,67 @@ +/** + * @jest-environment jsdom + */ + +import { Application } from "stimulus"; +import tabs_controller from "../../../app/webpacker/controllers/tabs_controller"; + +describe("TabsController", () => { + describe("#select", () => { + beforeEach(() => { + document.body.innerHTML = ` +
+ + + + +
+ Dogs content +
+
+ Cats content +
+
+ Birds content +
+
+ `; + + const application = Application.start(); + application.register("tabs", tabs_controller); + }); + + it("shows the corresponding content when a tab button is clicked", () => { + const dogs_button = document.querySelectorAll('button')[0]; + const cats_button = document.querySelectorAll('button')[1]; + const birds_button = document.querySelectorAll('button')[2]; + const dogs_content = document.querySelectorAll('.content-area')[0]; + const cats_content = document.querySelectorAll('.content-area')[1]; + const birds_content = document.querySelectorAll('.content-area')[2]; + + expect(dogs_content.hidden).toBe(false); + expect(cats_content.hidden).toBe(true); + expect(birds_content.hidden).toBe(true); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(dogs_button); + + birds_button.click(); + + expect(dogs_content.hidden).toBe(true); + expect(cats_content.hidden).toBe(true); + expect(birds_content.hidden).toBe(false); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(birds_button); + + cats_button.click(); + + expect(dogs_content.hidden).toBe(true); + expect(cats_content.hidden).toBe(false); + expect(birds_content.hidden).toBe(true); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(cats_button); + }); + }); +}); diff --git a/spec/support/request/authentication_helper.rb b/spec/support/request/authentication_helper.rb index 147e7ff631..813121f49a 100644 --- a/spec/support/request/authentication_helper.rb +++ b/spec/support/request/authentication_helper.rb @@ -24,8 +24,8 @@ module AuthenticationHelper end def fill_in_and_submit_login_form(user) - fill_in "email", with: user.email - fill_in "password", with: user.password + fill_in "Email", with: user.email + fill_in "Password", with: user.password click_button "Login" end diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index b48cfe16e0..f6bf0e41b2 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -111,8 +111,8 @@ module UIComponentHelper end def fill_in_using_keyboard - page.find('#email').send_keys(user.email, :tab, user.password, :tab, :space) - expect(page.find('#remember_me')).to be_checked - page.find('#remember_me').send_keys(:tab, :enter) + page.find('#spree_user_email').send_keys(user.email, :tab, user.password, :tab, :space) + expect(page.find('#spree_user_remember_me')).to be_checked + page.find('#spree_user_remember_me').send_keys(:tab, :enter) end end diff --git a/spec/system/consumer/authentication_spec.rb b/spec/system/consumer/authentication_spec.rb index b1137a3bf4..dc2a8930ba 100644 --- a/spec/system/consumer/authentication_spec.rb +++ b/spec/system/consumer/authentication_spec.rb @@ -12,7 +12,7 @@ describe "Authentication", js: true do describe "With redirects" do it "logging in with a redirect set" do - visit groups_path(anchor: "login?after_login=#{producers_path}") + visit groups_path(anchor: "/login", after_login: producers_path) fill_in "Email", with: user.email fill_in "Password", with: user.password click_login_button @@ -61,38 +61,35 @@ describe "Authentication", js: true do end it "Failing to sign up because password is too short" do - fill_in "Email", with: "test@foo.com" + fill_in "Your email", with: "test@foo.com" fill_in "Choose a password", with: "short" click_signup_button expect(page).to have_content "too short" end it "Failing to sign up because email is already registered" do - fill_in "Email", with: user.email + fill_in "Your email", with: user.email fill_in "Choose a password", with: "foobarino" click_signup_button expect(page).to have_content "There's already an account for this email." end it "Failing to sign up because password confirmation doesn't match or is blank" do - fill_in "Email", with: user.email + fill_in "Your email", with: user.email fill_in "Choose a password", with: "ForgotToRetype" click_signup_button expect(page).to have_content "doesn't match" end it "Signing up successfully" do - performing_deliveries do - setup_email - fill_in "Email", with: "test@foo.com" - fill_in "Choose a password", with: "test12345" - fill_in "Confirm password", with: "test12345" + fill_in "Your email", with: "test@foo.com" + fill_in "Choose a password", with: "test12345" + fill_in "Confirm password", with: "test12345" - expect do - click_signup_button - expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') - end.to enqueue_job ActionMailer::MailDeliveryJob - end + expect do + click_signup_button + expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') + end.to enqueue_job ActionMailer::MailDeliveryJob end end @@ -161,7 +158,7 @@ describe "Authentication", js: true do describe "after following email confirmation link" do it "shows confirmed message in modal" do - visit '/#/login?validation=confirmed' + visit root_path(anchor: "/login", validation: "confirmed") expect(page).to have_login_modal expect(page).to have_content I18n.t('devise.confirmations.confirmed') end diff --git a/spec/system/consumer/user_password_spec.rb b/spec/system/consumer/user_password_spec.rb index 93ff772369..a55140b813 100644 --- a/spec/system/consumer/user_password_spec.rb +++ b/spec/system/consumer/user_password_spec.rb @@ -29,6 +29,20 @@ describe "User password confirm/reset page" do expect(page).to have_no_text "Reset password token has expired" expect(page).to be_logged_in_as user end + + it "shows an error if password is empty" do + visit spree.spree_user_confirmation_path(confirmation_token: user.confirmation_token) + + expect(user.reload.confirmed?).to be true + expect(page).to have_text I18n.t(:change_my_password) + + fill_in "Password", with: "" + fill_in "Password Confirmation", with: "" + click_button + + expect(page).to have_text "User password cannot be blank. Please enter a password." + expect(page).to_not be_logged_in_as user + end end describe "can reset its own password" do