Skip to content

Commit

Permalink
Improve sign out, allow account creation
Browse files Browse the repository at this point in the history
  • Loading branch information
renatolond committed Sep 23, 2024
1 parent 391d80e commit c029fc7
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 3 deletions.
19 changes: 19 additions & 0 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,26 @@ def create
render "new", status: :unauthorized
end

def new_account; end

def create_account
@email = params[:email]

if params[:password] == params[:password_confirmation]
authorization_token = RetroMeetClient.create_account(login: params[:email], password: params[:password])
cookies[:Authorization] = authorization_token
redirect_to :root
else
flash.now[:error] = t(".passwords_do_not_match")
render "new_account", status: :bad_request
end
rescue RetroMeetClient::LoginAlreadyTakenError
flash.now[:error] = t(".login_is_already_in_use")
render "new_account", status: :unprocessable_content
end

def destroy
retro_meet_client.sign_out
cookies.delete(:Authorization)
redirect_to :root
end
Expand Down
53 changes: 53 additions & 0 deletions app/objects/retro_meet_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class RetroMeetClient
BadPasswordError = Class.new(UnauthorizedError)
BadLoginError = Class.new(UnauthorizedError)
UnknownError = Class.new(RetroMeetError)
LoginAlreadyTakenError = Class.new(RetroMeetError)

def initialize(authorization_header)
@authorization_header = authorization_header
Expand Down Expand Up @@ -41,7 +42,59 @@ def basic_profile_info
end
end

# Logs out from retromeet-core
# @raise [UnknownError] If an unknown error happens
# @return [void]
def sign_out
return nil if @authorization_header.blank?

Sync do
response = client.post("/logout", headers: base_headers)
case response.status
when 200
@authorization_header = nil
else
raise UnknownError, "An unknown error happened while calling retromeet-core"
end
end
end

class << self
# Tries to create an account in retromeet-core and converts any http errors into Ruby exceptions
# @param login (see .login)
# @param password (see .login)
# @raise [UnknownError] If an unknown error happens
# @return (see .login)
def create_account(login:, password:)
Sync do
body = { login:, password: }.to_json
response = client.post("/create-account", headers: base_headers, body:)
case response.status
when 200
response_headers = response.headers
response_headers["authorization"]
when 422
begin
response_body = JSON.parse(response.read, symbolize_names: true)
field_error = response_body.dig(:"field-error", 0)
field_message = response_body.dig(:"field-error", 1)
rescue
field_error = "unknown field"
end

raise LoginAlreadyTakenError, "This login already exists" if field_error == "login" && field_message["already an account with this login"]
raise BadLoginError, "Invalid login" if field_error == "login"
raise BadPasswordError, "Invalid password" if field_error == "password"

raise UnknownError
else
raise UnknownError, "Something went wrong, code=#{response.status}"
end
ensure
response&.close
end
end

# Tries to login to retromeet-core and converts any http errors into Ruby exceptions
# @param login [String] The login to use in retromeet-core, should be an email
# @param password [String]
Expand Down
2 changes: 1 addition & 1 deletion app/views/application/_header.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%nav.navbar
.container
.navbar-brand
.navbar-item= image_tag("retromeet_long.png", class: %i[image])
.navbar-item= link_to image_tag("retromeet_long.png", class: %i[image]), root_url
.navbar-menu
.navbar-end
.navbar-item Profile
Expand Down
1 change: 1 addition & 0 deletions app/views/sessions/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@
= f.check_box :remember_me
= t(".remember_me")
= f.submit t(".sign_in"), class: 'button is-block is-info is-large is-fullwidth'
= render "sessions/shared/links"
17 changes: 17 additions & 0 deletions app/views/sessions/new_account.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.container.has-text-centered
.columns
.column.is-4.is-offset-4
%h3.title.has-text-grey= t('sessions.sign_up')
.box
= form_with(url: create_account_session_path) do |f|
.field
.control
= f.email_field :email, autofocus: true, autocomplete: 'email', placeholder: '[email protected]', class: 'input is-large', value: @email
.field
.control
= f.password_field :password, autocomplete: "new-password", placeholder: t(".password"), class: 'input is-large'
.field
.control
= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: t(".password_confirmation"), class: 'input is-large'
= f.submit t("sessions.sign_up"), class: 'button is-block is-info is-large is-fullwidth'
= render "sessions/shared/links"
5 changes: 5 additions & 0 deletions app/views/sessions/shared/_links.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
%p.has-text-grey
!= [ |
action_name != "new" ? link_to(t("sessions.sign_in"), new_session_path) : nil, |
action_name != "new_account" ? link_to(t("sessions.sign_up"), new_account_session_path) : nil |
].compact.join("&nbsp;·&nbsp;") |
5 changes: 5 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@
en:
hello: "Hello world"
sessions:
sign_up: "Sign up"
new:
sign_in: "Sign in"
new_account:
password_confirmation: "Password confirmation"
password: "Password"
login_is_already_in_use: "The login is already in use. Maybe try signing in instead?"
bad_login: "Incorrect login. It should be the e-mail you used to sign-in."
bad_password: "Incorrect password."
8 changes: 6 additions & 2 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

Expand All @@ -9,8 +11,10 @@
root "profile#index"

resource :session, only: [], path: :auth do
get :new, path: :sign_in, as: "new"
post :create, path: :sign_in
get :new, path: :sign_in, as: :new
post :create, path: :sign_in
get :new_account, path: :sign_up
post :create_account, path: :sign_up
match :destroy, path: :sign_out, as: "destroy", via: :delete
end
end
44 changes: 44 additions & 0 deletions test/objects/retro_meet_client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,48 @@ class RetroMeetClientTest < ActiveSupport::TestCase
end
assert_requested(:post, "http://localhost:3000/login")
end

test "calls the create_account method with good params and get an auth token" do
login = "[email protected]"
password = "bar"
stub_request(:post, "http://localhost:3000/create-account").with(headers: { "Content-Type" => "application/json" })
.to_return(webfixture_json_file("create_account_ok"))

expected_response = "eyJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjoxNCwiYXV0aGVudGljYXRlZF9ieSI6WyJhdXRvbG9naW4iXSwiYXV0b2xvZ2luX3R5cGUiOiJjcmVhdGVfYWNjb3VudCJ9.Fo5ZXDASNTcea-V4KlX8JjWy7XQOcPHDFcjET0HeIsw"
assert_equal expected_response, RetroMeetClient.create_account(login:, password:)
assert_requested(:post, "http://localhost:3000/create-account")
end
test "calls the create_account method with good params but already used login and gets the proper error" do
login = "[email protected]"
password = "bar"
stub_request(:post, "http://localhost:3000/create-account").with(headers: { "Content-Type" => "application/json" })
.to_return(webfixture_json_file("create_account_existing"))

assert_raises RetroMeetClient::LoginAlreadyTakenError do
RetroMeetClient.create_account(login:, password:)
end
assert_requested(:post, "http://localhost:3000/create-account")
end
test "calls the create_account method with a bad password and gets an error" do
login = "[email protected]"
password = ""
stub_request(:post, "http://localhost:3000/create-account").with(headers: { "Content-Type" => "application/json" })
.to_return(webfixture_json_file("create_account_bad_password"))

assert_raises RetroMeetClient::BadPasswordError do
RetroMeetClient.create_account(login:, password:)
end
assert_requested(:post, "http://localhost:3000/create-account")
end
test "calls the create_account method with a bad login and gets an error" do
login = "bad_login"
password = "bad_password"
stub_request(:post, "http://localhost:3000/create-account").with(headers: { "Content-Type" => "application/json" })
.to_return(webfixture_json_file("create_account_bad_login"))

assert_raises RetroMeetClient::BadLoginError do
RetroMeetClient.create_account(login:, password:)
end
assert_requested(:post, "http://localhost:3000/create-account")
end
end
7 changes: 7 additions & 0 deletions test/webfixtures/create_account_bad_login.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
HTTP/1.1 422 Unprocessable Entity
authorization: eyJhbGciOiJIUzI1NiJ9.e30.7k-y2TFPta8oQgUMssFXSdaS8XEogkVljv1-STmDjgk
content-type: application/json
vary: accept-encoding
content-length: 119

{"field-error":["login","invalid login, not a valid email address"],"error":"There was an error creating your account"}
7 changes: 7 additions & 0 deletions test/webfixtures/create_account_bad_password.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
HTTP/1.1 422 Unprocessable Entity
authorization: eyJhbGciOiJIUzI1NiJ9.e30.7k-y2TFPta8oQgUMssFXSdaS8XEogkVljv1-STmDjgk
content-type: application/json
vary: accept-encoding
content-length: 149

{"field-error":["password","invalid password, does not meet requirements (minimum 6 characters)"],"error":"There was an error creating your account"}
7 changes: 7 additions & 0 deletions test/webfixtures/create_account_existing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
HTTP/1.1 422 Unprocessable Entity
authorization: eyJhbGciOiJIUzI1NiJ9.e30.7k-y2TFPta8oQgUMssFXSdaS8XEogkVljv1-STmDjgk
content-type: application/json
vary: accept-encoding
content-length: 128

{"field-error":["login","invalid login, already an account with this login"],"error":"There was an error creating your account"}
7 changes: 7 additions & 0 deletions test/webfixtures/create_account_ok.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
HTTP/1.1 200 OK
authorization: eyJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjoxNCwiYXV0aGVudGljYXRlZF9ieSI6WyJhdXRvbG9naW4iXSwiYXV0b2xvZ2luX3R5cGUiOiJjcmVhdGVfYWNjb3VudCJ9.Fo5ZXDASNTcea-V4KlX8JjWy7XQOcPHDFcjET0HeIsw
content-type: application/json
vary: accept-encoding
content-length: 43

{"success":"Your account has been created"}

0 comments on commit c029fc7

Please sign in to comment.