diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 320ff2f..061ff0b 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -1,4 +1,6 @@ class AccountsController < ApplicationController + layout "anonymous", except: [:edit, :destroy, :update] + before_action :authenticate_user!, only: [:edit, :destroy, :update] before_action :redirect_if_authenticated, only: [:create, :new] diff --git a/app/controllers/api/v1/api_keys_controller.rb b/app/controllers/api/v1/api_keys_controller.rb new file mode 100644 index 0000000..ec82166 --- /dev/null +++ b/app/controllers/api/v1/api_keys_controller.rb @@ -0,0 +1,28 @@ +class Api::V1::ApiKeysController < Api::V1::BaseController + # Require API key authentication + prepend_before_action :authenticate_with_api_key!, only: %i[index destroy] + + def index + render json: current_bearer.api_keys + end + + def create + authenticate_with_http_basic do |email, password| + user = User.find_by email: email + + if user&.authenticate(password) + api_key = user.api_keys.create! token: SecureRandom.hex + + render json: api_key, status: :created and return + end + end + + render status: :unauthorized + end + + def destroy + api_key = current_bearer.api_keys.find(params[:id]) + + api_key.destroy + end + end \ No newline at end of file diff --git a/app/controllers/concerns/basic_authentication.rb b/app/controllers/concerns/basic_authentication.rb index 35c21ac..b2b14cf 100644 --- a/app/controllers/concerns/basic_authentication.rb +++ b/app/controllers/concerns/basic_authentication.rb @@ -30,7 +30,7 @@ module BasicAuthentication end def redirect_if_authenticated - redirect_to root_path, alert: "You are already logged in." if user_signed_in? + redirect_to checks_path, alert: "You are already logged in." if user_signed_in? end def remember(user) diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index b92d37c..b26b9cc 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -1,4 +1,5 @@ class ConfirmationsController < ApplicationController + layout "anonymous" def create @user = User.find_by(email: params[:user][:email].downcase) diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index abb6576..86c65d0 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,4 +1,6 @@ class PasswordsController < ApplicationController + layout "anonymous" + before_action :redirect_if_authenticated def create diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 59bd8ad..edac46a 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,4 +1,6 @@ class SessionsController < ApplicationController + layout "anonymous" + before_action :redirect_if_authenticated, only: [:create, :new] before_action :authenticate_user!, only: [:destroy] diff --git a/app/views/accounts/new.html.erb b/app/views/accounts/new.html.erb index 23c0a30..eb5cb2e 100644 --- a/app/views/accounts/new.html.erb +++ b/app/views/accounts/new.html.erb @@ -1,20 +1,57 @@ -<%= form_with model: @user, url: sign_up_path do |form| %> - <%= render partial: "shared/form_errors", locals: { object: form.object } %> -
- <%= form.label :email %> - <%= form.text_field :email, required: true, autofocus: true, autocomplete: "email" %> +
+
+

+ Sign up for an account +

+

+ Or + <%= link_to "sign in to your account", login_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +

-
- <%= form.label :name %> - <%= form.text_field :name, autocomplete: "name" %> + +
+
+ <%= form_with model: @user, url: sign_up_path, class: "space-y-6" do |form| %> + <%= render partial: "shared/form_errors", locals: { object: form.object } %> +
+ <%= form.label :email, class: "block text-sm font-medium text-gray-700" do %> + Email address + <% end %> +
+ <%= form.text_field :email, required: true, autofocus: true, autocomplete: "email", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+
+ <%= form.label :name, class: "block text-sm font-medium text-gray-700" do %> + Your name + <% end %> +
+ <%= form.text_field :name, autocomplete: "name", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.label :password, class: "block text-sm font-medium text-gray-700" do %> + Password + <% end %> +
+ <%= form.password_field :password, required: true, autocomplete: "new-password", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.label :password_confirmation, class: "block text-sm font-medium text-gray-700" do %> + Password confirmation + <% end %> +
+ <%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.submit "Sign Up", class: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %> +
+ <% end %> +
-
- <%= form.label :password %> - <%= form.password_field :password, required: true, autocomplete: "new-password" %> -
-
- <%= form.label :password_confirmation %> - <%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %> -
- <%= form.submit "Sign Up" %> -<% end %> \ No newline at end of file +
\ No newline at end of file diff --git a/app/views/checks/index.html.erb b/app/views/checks/index.html.erb index 0a8822b..b77655b 100644 --- a/app/views/checks/index.html.erb +++ b/app/views/checks/index.html.erb @@ -2,7 +2,6 @@

Checks

- <%= link_to 'New check', new_check_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
@@ -23,7 +22,7 @@ Description - Edit + Actions @@ -41,7 +40,6 @@ <%= link_to "Show", check, class: "text-indigo-600 hover:text-indigo-900" %> - <%= link_to 'Edit', edit_check_path(check), class: "text-indigo-600 hover:text-indigo-900" %> <% end %> diff --git a/app/views/confirmations/new.html.erb b/app/views/confirmations/new.html.erb index 527670c..aa89c1d 100644 --- a/app/views/confirmations/new.html.erb +++ b/app/views/confirmations/new.html.erb @@ -1,4 +1,30 @@ -<%= form_with model: @user, url: confirmations_path do |form| %> - <%= form.email_field :email, required: true %> - <%= form.submit "Confirm Email" %> -<% end %> \ No newline at end of file +
+
+

+ Resend instructions +

+

+ Or + <%= link_to "back to sign-in", login_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +

+
+ +
+
+ <%= form_with model: @user, url: confirmations_path, class: "space-y-6" do |form| %> +
+ <%= form.label :email, class: "block text-sm font-medium text-gray-700" do %> + Email address + <% end %> +
+ <%= form.text_field :email, required: true, autocomplete: "email", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.submit "Confirm Email", class: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %> +
+ <% end %> +
+
+
\ No newline at end of file diff --git a/app/views/layouts/anonymous.html.erb b/app/views/layouts/anonymous.html.erb new file mode 100644 index 0000000..a7aab91 --- /dev/null +++ b/app/views/layouts/anonymous.html.erb @@ -0,0 +1,73 @@ + + + + Evocheck + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_importmap_tags %> + + + +
+
+
+
+ <% if notice.present? %> + +
+
+
+ <%= heroicon "check-circle", variant: :solid, options: { class: "h-5 w-5 text-yellow-400" } %> +
+
+

+ <%= notice %> +

+
+
+
+ +
+
+
+
+ <% end %> + <% if alert.present? %> + +
+
+
+ <%= heroicon "check-circle", variant: :solid, options: { class: "h-5 w-5 text-red-400" } %> +
+
+

+ <%= alert %> +

+
+
+
+ +
+
+
+
+ <% end %> + + <%= yield %> + +
+
+
+
+ + \ No newline at end of file diff --git a/app/views/passwords/new.html.erb b/app/views/passwords/new.html.erb index 0bf321a..9cb8e99 100644 --- a/app/views/passwords/new.html.erb +++ b/app/views/passwords/new.html.erb @@ -1,4 +1,30 @@ -<%= form_with url: passwords_path, scope: :user do |form| %> - <%= form.email_field :email, required: true %> - <%= form.submit "Reset Password" %> -<% end %> \ No newline at end of file +
+
+

+ Forgot your password? +

+

+ Or + <%= link_to "back to sign-in", login_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +

+
+ +
+
+ <%= form_with url: passwords_path, scope: :user, class: "space-y-6" do |form| %> +
+ <%= form.label :email, class: "block text-sm font-medium text-gray-700" do %> + Email address + <% end %> +
+ <%= form.text_field :email, required: true, autocomplete: "email", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.submit "Reset Password", class: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %> +
+ <% end %> +
+
+
\ No newline at end of file diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index 627acd4..5d7b442 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,15 +1,70 @@ -<%= form_with url: login_path, scope: :user do |form| %> -
- <%= form.label :email %> - <%= form.text_field :email, required: true %> +
+
+

+ Sign in to your account +

+

+ Or + <%= link_to "sign up for an account", sign_up_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +

-
- <%= form.label :password %> - <%= form.password_field :password, required: true %> + +
+
+ <%= form_with url: login_path, scope: :user, class: "space-y-6" do |form| %> +
+ <%= form.label :email, class: "block text-sm font-medium text-gray-700" do %> + Email address + <% end %> +
+ <%= form.text_field :email, required: true, autocomplete: "email", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+ <%= form.label :password, class: "block text-sm font-medium text-gray-700" do %> + Password + <% end %> +
+ <%= form.password_field :password, required: true, autocomplete: "password", class: "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" %> +
+
+ +
+
+ <%= form.check_box :remember_me, class: "h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded" %> + <%= form.label :remember_me, class: "ml-2 block text-sm text-gray-900" do %> + Remember me + <% end %> +
+
+ +
+ <%= form.submit "Sign In", class: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %> +
+ <% end %> +
+
+
+
+
+
+ + Something wrong? + +
+
+
+
+ <%= link_to "I forgot my password!", new_password_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +
+
+ <%= link_to "I didn't receive confirmation instructions!", new_confirmation_path, class: "font-medium text-indigo-600 hover:text-indigo-500" %> +
+
+
+
-
- <%= form.label :remember_me %> - <%= form.check_box :remember_me %> -
- <%= form.submit "Sign In" %> -<% end %> \ No newline at end of file +
+ + diff --git a/app/views/shared/_user_menu.html.erb b/app/views/shared/_user_menu.html.erb index 4902103..8d1f336 100644 --- a/app/views/shared/_user_menu.html.erb +++ b/app/views/shared/_user_menu.html.erb @@ -1,5 +1,2 @@ -<%= link_to "Your Profile", account_path, class: common_classes + " " + active_classes %> -<%= link_to "Settings", "#", class: common_classes + " " + active_classes %> -
- <%= button_to "Sign out", logout_path, method: :delete, class: common_classes + " " + active_classes + " inline" %> -
\ No newline at end of file +<%= link_to "Your Profile", account_path, class: common_classes + " " + active_classes %> +<%= button_to "Sign out", logout_path, method: :delete, class: common_classes + " " + active_classes + " text-left w-full", data: { 'turbo-confirm': "Are you sure?" } %> \ No newline at end of file diff --git a/app/views/static_pages/home.html.erb b/app/views/static_pages/home.html.erb index 96be373..b545508 100644 --- a/app/views/static_pages/home.html.erb +++ b/app/views/static_pages/home.html.erb @@ -1,14 +1,12 @@

Rails Authentication From Scratch

- - -
    - <% if user_signed_in? %> -
  • <%= link_to "My Acount", account_path %>
  • -
  • <%= button_to "Logout", logout_path, method: :delete %>
  • - <% else %> -
  • <%= link_to "Login", login_path %>
  • -
  • <%= link_to "Sign Up", sign_up_path %>
  • -
  • <%= link_to "Forgot my password", new_password_path %>
  • -
  • <%= link_to "Didn't receive confirmation instructions", new_confirmation_path %>
  • - <% end %> -
\ No newline at end of file +
    + <% if user_signed_in? %> +
  • <%= link_to "My Acount", account_path %>
  • +
  • <%= button_to "Logout", logout_path, method: :delete %>
  • + <% else %> +
  • <%= link_to "Login", login_path %>
  • +
  • <%= link_to "Sign Up", sign_up_path %>
  • +
  • <%= link_to "Forgot my password", new_password_path %>
  • +
  • <%= link_to "Didn't receive confirmation instructions", new_confirmation_path %>
  • + <% end %> +
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index d4591f0..881d8bd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,7 @@ Rails.application.routes.draw do end # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html - root "static_pages#home" + root "sessions#new" post "sign_up", to: "accounts#create" get "sign_up", to: "accounts#new"