require 'test_helper' # was the web request successful? # was the user redirected to the right page? # was the user successfully authenticated? # was the correct object stored in the response? # was the appropriate message delivered in the json payload? class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTest describe DeviseTokenAuth::RegistrationsController do describe 'Validate non-empty body' do before do # need to post empty data post '/auth', {} @resource = assigns(:resource) @data = JSON.parse(response.body) end test 'request should fail' do assert_equal 422, response.status end test 'returns error message' do assert_not_empty @data['errors'] end test 'return error status' do assert_equal 'error', @data['status'] end test 'user should not have been saved' do assert @resource.nil? end end describe "Successful registration" do before do @mails_sent = ActionMailer::Base.deliveries.count post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url, unpermitted_param: '(x_x)' } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last end test "request should be successful" do assert_equal 200, response.status end test "user should have been created" do assert @resource.id end test "user should not be confirmed" do assert_nil @resource.confirmed_at end test "new user data should be returned as json" do assert @data['data']['email'] end test "new user should receive confirmation email" do assert_equal @resource.email, @mail['to'].to_s end test "new user password should not be returned" do assert_nil @data['data']['password'] end test "only one email was sent" do assert_equal @mails_sent + 1, ActionMailer::Base.deliveries.count end end describe 'using "+" in email' do test 'can use + sign in email addresses' do @plus_email = 'ak+testing@gmail.com' post '/auth', { email: @plus_email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) assert_equal @plus_email, @resource.email end end describe 'Using redirect_whitelist' do before do @good_redirect_url = Faker::Internet.url @bad_redirect_url = Faker::Internet.url DeviseTokenAuth.redirect_whitelist = [@good_redirect_url] end teardown do DeviseTokenAuth.redirect_whitelist = nil end test "request to whitelisted redirect should be successful" do post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: @good_redirect_url, unpermitted_param: '(x_x)' } assert_equal 200, response.status end test "request to non-whitelisted redirect should fail" do post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: @bad_redirect_url, unpermitted_param: '(x_x)' } @data = JSON.parse(response.body) assert_equal 403, response.status assert @data["errors"] assert_equal @data["errors"], [I18n.t("devise_token_auth.registrations.redirect_url_not_allowed", redirect_url: @bad_redirect_url)] end end describe 'failure if not redirecturl' do test "request should fail if not redirect_url" do post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", unpermitted_param: '(x_x)' } assert_equal 403, response.status end test "request to non-whitelisted redirect should fail" do post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", unpermitted_param: '(x_x)' } @data = JSON.parse(response.body) assert @data["errors"] assert_equal @data["errors"], [I18n.t("devise_token_auth.registrations.missing_confirm_success_url")] end end describe 'Using default_confirm_success_url' do before do @mails_sent = ActionMailer::Base.deliveries.count @redirect_url = Faker::Internet.url DeviseTokenAuth.default_confirm_success_url = @redirect_url post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", unpermitted_param: '(x_x)' } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last @sent_redirect_url = URI.decode(@mail.body.match(/redirect_url=([^&]*)(&|\")/)[1]) end teardown do DeviseTokenAuth.default_confirm_success_url = nil end test "request should be successful" do assert_equal 200, response.status end test "the email was sent" do assert_equal @mails_sent + 1, ActionMailer::Base.deliveries.count end test 'email contains the default redirect url' do assert_equal @redirect_url, @sent_redirect_url end end describe 'using namespaces' do before do @mails_sent = ActionMailer::Base.deliveries.count post '/api/v1/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url, unpermitted_param: '(x_x)' } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last end test "request should be successful" do assert_equal 200, response.status end test "user should have been created" do assert @resource.id end end describe "case-insensitive email" do before do @resource_class = User @request_params = { email: "AlternatingCase@example.com", password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } end test "success should downcase uid if configured" do @resource_class.case_insensitive_keys = [:email] post '/auth', @request_params assert_equal 200, response.status @data = JSON.parse(response.body) assert_equal "alternatingcase@example.com", @data['data']['uid'] end test "request should not downcase uid if not configured" do @resource_class.case_insensitive_keys = [] post '/auth', @request_params assert_equal 200, response.status @data = JSON.parse(response.body) assert_equal "AlternatingCase@example.com", @data['data']['uid'] end end describe "Adding extra params" do before do @redirect_url = Faker::Internet.url @operating_thetan = 2 post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: @redirect_url, favorite_color: @fav_color, operating_thetan: @operating_thetan } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last @mail_reset_token = @mail.body.match(/confirmation_token=([^&]*)&/)[1] @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=(.*)\"/)[1]) @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1]) end test 'redirect_url is included as param in email' do assert_equal @redirect_url, @mail_redirect_url end test "additional sign_up params should be considered" do assert_equal @operating_thetan, @resource.operating_thetan end test 'config_name param is included in the confirmation email link' do assert @mail_config_name end test "client config name falls back to 'default'" do assert_equal "default", @mail_config_name end end describe 'bad email' do before do post '/auth', { email: "false_email@", password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) end test "request should not be successful" do assert_equal 403, response.status end test "user should not have been created" do assert_nil @resource.id end test "error should be returned in the response" do assert @data['errors'].length end test "full_messages should be included in error hash" do assert @data['errors']['full_messages'].length end end describe 'missing email' do before do post '/auth', { password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) end test "request should not be successful" do assert_equal 403, response.status end test "user should not have been created" do assert_nil @resource.id end test "error should be returned in the response" do assert @data['errors'].length end test "full_messages should be included in error hash" do assert @data['errors']['full_messages'].length end end describe "Mismatched passwords" do before do post '/auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "bogus", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) end test "request should not be successful" do assert_equal 403, response.status end test "user should have been created" do assert_nil @resource.id end test "error should be returned in the response" do assert @data['errors'].length end test "full_messages should be included in error hash" do assert @data['errors']['full_messages'].length end end describe "Existing users" do before do @existing_user = users(:confirmed_email_user) post "/auth", { email: @existing_user.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) end test "request should not be successful" do assert_equal 403, response.status end test "user should have been created" do assert_nil @resource.id end test "error should be returned in the response" do assert @data['errors'].length end end describe "Destroy user account" do describe "success" do before do @existing_user = users(:confirmed_email_user) @auth_headers = @existing_user.create_new_auth_token @client_id = @auth_headers['client'] # ensure request is not treated as batch request age_token(@existing_user, @client_id) delete "/auth", {}, @auth_headers @data = JSON.parse(response.body) end test 'request is successful' do assert_equal 200, response.status end test "message should be returned" do assert @data["message"] assert_equal @data["message"], I18n.t("devise_token_auth.registrations.account_with_uid_destroyed", uid: @existing_user.uid) end test "existing user should be deleted" do refute User.where(id: @existing_user.id).first end end describe 'failure: no auth headers' do before do delete "/auth" @data = JSON.parse(response.body) end test 'request returns 404 (not found) status' do assert_equal 404, response.status end test 'error should be returned' do assert @data['errors'].length assert_equal @data['errors'], [I18n.t("devise_token_auth.registrations.account_to_destroy_not_found")] end end end describe "Update user account" do describe "existing user" do before do @existing_user = users(:confirmed_email_user) @auth_headers = @existing_user.create_new_auth_token @client_id = @auth_headers['client'] # ensure request is not treated as batch request age_token(@existing_user, @client_id) end describe "without password check" do describe "success" do before do # test valid update param @resource_class = User @new_operating_thetan = 1000000 @email = "AlternatingCase2@example.com" @request_params = { operating_thetan: @new_operating_thetan, email: @email } end test "Request was successful" do put "/auth", @request_params, @auth_headers assert_equal 200, response.status end test "Case sensitive attributes update" do @resource_class.case_insensitive_keys = [] put "/auth", @request_params, @auth_headers @data = JSON.parse(response.body) @existing_user.reload assert_equal @new_operating_thetan, @existing_user.operating_thetan assert_equal @email, @existing_user.email assert_equal @email, @existing_user.uid end test "Case insensitive attributes update" do @resource_class.case_insensitive_keys = [:email] put "/auth", @request_params, @auth_headers @data = JSON.parse(response.body) @existing_user.reload assert_equal @new_operating_thetan, @existing_user.operating_thetan assert_equal @email.downcase, @existing_user.email assert_equal @email.downcase, @existing_user.uid end test "Supply current password" do @request_params.merge!( current_password: "secret123", email: "new.email@example.com", ) put "/auth", @request_params, @auth_headers @data = JSON.parse(response.body) @existing_user.reload assert_equal @existing_user.email, "new.email@example.com" end end describe 'validate non-empty body' do before do # get the email so we can check it wasn't updated @email = @existing_user.email put '/auth', {}, @auth_headers @data = JSON.parse(response.body) @existing_user.reload end test 'request should fail' do assert_equal 422, response.status end test 'returns error message' do assert_not_empty @data['errors'] end test 'return error status' do assert_equal 'error', @data['status'] end test 'user should not have been saved' do assert_equal @email, @existing_user.email end end describe "error" do before do # test invalid update param @new_operating_thetan = "blegh" put "/auth", { operating_thetan: @new_operating_thetan }, @auth_headers @data = JSON.parse(response.body) @existing_user.reload end test "Request was NOT successful" do assert_equal 403, response.status end test "Errors were provided with response" do assert @data["errors"].length end end end describe "with password check for password update only" do before do DeviseTokenAuth.check_current_password_before_update = :password end after do DeviseTokenAuth.check_current_password_before_update = false end describe "success without password update" do before do # test valid update param @resource_class = User @new_operating_thetan = 1000000 @email = "AlternatingCase2@example.com" @request_params = { operating_thetan: @new_operating_thetan, email: @email } end test "Request was successful" do put "/auth", @request_params, @auth_headers assert_equal 200, response.status end end describe "success with password update" do before do @existing_user.update password: 'secret123', password_confirmation: 'secret123' @request_params = { password: 'the_new_secret456', password_confirmation: 'the_new_secret456', current_password: 'secret123' } end test "Request was successful" do put "/auth", @request_params, @auth_headers assert_equal 200, response.status end end describe "error with password mismatch" do before do @existing_user.update password: 'secret123', password_confirmation: 'secret123' @request_params = { password: 'the_new_secret456', password_confirmation: 'the_new_secret456', current_password: 'not_so_secret321' } end test "Request was NOT successful" do put "/auth", @request_params, @auth_headers assert_equal 403, response.status end end end describe "with password check for all attributes" do before do DeviseTokenAuth.check_current_password_before_update = :password @new_operating_thetan = 1000000 @email = "AlternatingCase2@example.com" end after do DeviseTokenAuth.check_current_password_before_update = false end describe "success with password update" do before do @existing_user.update password: 'secret123', password_confirmation: 'secret123' @request_params = { operating_thetan: @new_operating_thetan, email: @email, current_password: 'secret123' } end test "Request was successful" do put "/auth", @request_params, @auth_headers assert_equal 200, response.status end end describe "error with password mismatch" do before do @existing_user.update password: 'secret123', password_confirmation: 'secret123' @request_params = { operating_thetan: @new_operating_thetan, email: @email, current_password: 'not_so_secret321' } end test "Request was NOT successful" do put "/auth", @request_params, @auth_headers assert_equal 403, response.status end end end end describe "invalid user" do before do @existing_user = users(:confirmed_email_user) @auth_headers = @existing_user.create_new_auth_token @client_id = @auth_headers['client'] # ensure request is not treated as batch request expire_token(@existing_user, @client_id) # test valid update param @new_operating_thetan = 3 put "/auth", { operating_thetan: @new_operating_thetan }, @auth_headers @data = JSON.parse(response.body) @existing_user.reload end test "Response should return 404 status" do assert_equal 404, response.status end test "error should be returned" do assert @data["errors"].length assert_equal @data["errors"], [I18n.t("devise_token_auth.registrations.user_not_found")] end test "User should not be updated" do refute_equal @new_operating_thetan, @existing_user.operating_thetan end end end describe "Ouath user has existing email" do before do @existing_user = users(:duplicate_email_facebook_user) post "/auth", { email: @existing_user.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) end test "request should be successful" do assert_equal 200, response.status end test "user should have been created" do assert @resource.id end test "new user data should be returned as json" do assert @data['data']['email'] end end describe "Alternate user class" do before do post "/mangs", { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last end test "request should be successful" do assert_equal 200, response.status end test "use should be a Mang" do assert_equal "Mang", @resource.class.name end test "Mang should be destroyed" do @auth_headers = @resource.create_new_auth_token @client_id = @auth_headers['client'] # ensure request is not treated as batch request age_token(@resource, @client_id) delete "/mangs", {}, @auth_headers assert_equal 200, response.status refute Mang.where(id: @resource.id).first end end describe "Passing client config name" do before do @config_name = 'altUser' post "/mangs", { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url, config_name: @config_name } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last @resource.reload @mail_reset_token = @mail.body.match(/confirmation_token=([^&]*)&/)[1] @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=(.*)\"/)[1]) @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1]) end test 'config_name param is included in the confirmation email link' do assert_equal @config_name, @mail_config_name end end describe 'Excluded :registrations module' do test 'UnregisterableUser should not be able to access registration routes' do assert_raises(ActionController::RoutingError) { post '/unregisterable_user_auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } } end end describe "Skipped confirmation" do setup do User.set_callback(:create, :before, :skip_confirmation!) post "/auth", { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url } @resource = assigns(:resource) @token = response.headers["access-token"] @client_id = response.headers["client"] end teardown do User.skip_callback(:create, :before, :skip_confirmation!) end test "user was created" do assert @resource end test "user was confirmed" do assert @resource.confirmed? end test "auth headers were returned in response" do assert response.headers["access-token"] assert response.headers["token-type"] assert response.headers["client"] assert response.headers["expiry"] assert response.headers["uid"] end test "response token is valid" do assert @resource.valid_token?(@token, @client_id) end end describe 'User with only :database_authenticatable and :registerable included' do setup do @mails_sent = ActionMailer::Base.deliveries.count post '/only_email_auth', { email: Faker::Internet.email, password: "secret123", password_confirmation: "secret123", confirm_success_url: Faker::Internet.url, unpermitted_param: '(x_x)' } @resource = assigns(:resource) @data = JSON.parse(response.body) @mail = ActionMailer::Base.deliveries.last end test 'user was created' do assert @resource.id end test 'email confirmation was not sent' do assert_equal @mails_sent, ActionMailer::Base.deliveries.count end test 'user is confirmed' do assert @resource.confirmed? end end end end