From f7b93ac8b576fbf1e83c7c8e9a39e8811544bd66 Mon Sep 17 00:00:00 2001 From: Eugene Burmakin Date: Thu, 4 Apr 2024 20:14:11 +0200 Subject: [PATCH] Add callback to create API key for new users --- app/models/user.rb | 9 +++++++++ app/views/devise/registrations/edit.html.erb | 12 +++++++++++- app/views/devise/shared/_links.html.erb | 14 +++++++------- config/routes.rb | 3 +++ db/migrate/20240404154959_add_api_key_to_users.rb | 5 +++++ db/schema.rb | 3 ++- spec/models/user_spec.rb | 10 ++++++++++ 7 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 db/migrate/20240404154959_add_api_key_to_users.rb diff --git a/app/models/user.rb b/app/models/user.rb index 4d3ae41e..c739f3ac 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,8 @@ class User < ApplicationRecord has_many :points, through: :imports has_many :stats + after_create :create_api_key + def export_data ::ExportSerializer.new(points, self.email).call end @@ -27,4 +29,11 @@ class User < ApplicationRecord def total_reverse_geocoded points.where.not(country: nil, city: nil).count end + + private + + def create_api_key + self.api_key = SecureRandom.hex(16) + save + end end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 00b42ae6..7a2f8630 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -2,7 +2,17 @@

Edit your account!

-

And change this text!

+

+

Use this API key to authenticate your requests.

+ <%= current_user.api_key %> +

+ Usage example: +

<%= api_v1_points_url(api_key: current_user.api_key) %>

+

+

+ <%= link_to "Generate new API key", generate_api_key_path, data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?", turbo_method: :post }, class: 'btn btn-primary' %> +

+

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), class: 'form-body', html: { method: :put }) do |f| %> diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb index 7cea86dc..27ca22e5 100644 --- a/app/views/devise/shared/_links.html.erb +++ b/app/views/devise/shared/_links.html.erb @@ -1,36 +1,36 @@
- <%- if controller_name != 'sessions' %> + <% if !signed_in? %>
<%= link_to "Log in", new_session_path(resource_name) %>
<% end %> - <%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <% if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %>
<% end %> - <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> + <% if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %>
<% end %> - <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <% if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
<% end %> - <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <% if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
<% end %> - <%- if devise_mapping.omniauthable? %> - <%- resource_class.omniauth_providers.each do |provider| %> + <% if devise_mapping.omniauthable? %> + <% resource_class.omniauth_providers.each do |provider| %> <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
<% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 3d95d0df..380db1cf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do get 'export', to: 'export#index' get 'export/download', to: 'export#download' + resources :imports resources :stats, only: :index do collection do @@ -12,6 +13,8 @@ Rails.application.routes.draw do root to: 'home#index' devise_for :users + post 'settings/generate_api_key', to: 'devise/api_keys#create', as: :generate_api_key + get 'points', to: 'points#index' namespace :api do diff --git a/db/migrate/20240404154959_add_api_key_to_users.rb b/db/migrate/20240404154959_add_api_key_to_users.rb new file mode 100644 index 00000000..a2c6a0ad --- /dev/null +++ b/db/migrate/20240404154959_add_api_key_to_users.rb @@ -0,0 +1,5 @@ +class AddApiKeyToUsers < ActiveRecord::Migration[7.1] + def change + add_column :users, :api_key, :string, null: false, default: '' + end +end diff --git a/db/schema.rb b/db/schema.rb index 63e83a12..741b51af 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_03_24_173315) do +ActiveRecord::Schema[7.1].define(version: 2024_04_04_154959) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -116,6 +116,7 @@ ActiveRecord::Schema[7.1].define(version: 2024_03_24_173315) do t.datetime "remember_created_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "api_key", default: "", null: false t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9809ac0a..216ac582 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -7,6 +7,16 @@ RSpec.describe User, type: :model do it { is_expected.to have_many(:stats) } end + describe 'callbacks' do + describe '#create_api_key' do + let(:user) { create(:user) } + + it 'creates api key' do + expect(user.api_key).to be_present + end + end + end + describe 'methods' do let(:user) { create(:user) }