From 54bdd52e7588c163c7ee0b9691357bab86bb32c0 Mon Sep 17 00:00:00 2001 From: Mohammad Kanaan Date: Sun, 31 May 2026 00:27:35 +0300 Subject: [PATCH] feat: add user auth and bcrypt gem with related schema updates --- .idea/price-point-api.iml | 1 + .opencode/memory/2026-05-30.logfmt | 1 + Gemfile | 2 +- Gemfile.lock | 2 ++ app/controllers/application_controller.rb | 13 +++++++++++++ app/models/user.rb | 1 + db/migrate/20260530211142_add_token_to_users.rb | 6 ++++++ 7 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20260530211142_add_token_to_users.rb diff --git a/.idea/price-point-api.iml b/.idea/price-point-api.iml index 7546ea2..a12de13 100644 --- a/.idea/price-point-api.iml +++ b/.idea/price-point-api.iml @@ -42,6 +42,7 @@ + diff --git a/.opencode/memory/2026-05-30.logfmt b/.opencode/memory/2026-05-30.logfmt index d298515..541ae2a 100644 --- a/.opencode/memory/2026-05-30.logfmt +++ b/.opencode/memory/2026-05-30.logfmt @@ -5,3 +5,4 @@ ts=2026-05-30T17:25:34.868Z type=preference scope=developer-profile content="Tea ts=2026-05-30T20:44:39.127Z type=decision scope=price-point-api content="price-point-api: Added Votable concern (app/models/concerns/votable.rb). PriceReport includes Votable. Methods: upvote!(user), downvote!(user) with toggle logic (same direction = destroy vote, opposite direction = switch), upvote_count/downvote_count via query (votes.where query). Rejected counter cache — directional counts (upvotes/downvotes) make Rails' built-in counter_cache unsuitable. Stale upvotes_count/downvotes_count columns need migration to drop." tags=voting,concerns,architecture ts=2026-05-30T20:44:41.808Z type=learning scope=developer-profile content="Learned: ActiveSupport::Concern syntax (extend + included do), find_by(user:) shorthand, ! vs no-! consistency in method calls, counter_cache limitations with polymorphic + directional counts, parentheses optional in Ruby when no args. Built Votable concern from scratch with toggle logic." tags=ruby,rails,concerns,counter-cache ts=2026-05-30T20:45:19.960Z type=preference scope=developer-profile content="Teaching style correction: Don't recommend patterns without first fully analyzing fit. Counter cache example — recommended before realizing directional counts break it. Verify the pattern actually solves the user's concrete problem before suggesting it. If unsure, say so and let the user decide." tags=teaching,style,lessons +ts=2026-05-30T21:26:45.561Z type=preference scope=developer-profile content="Auth style preferences: prefers `unless` over guard-clause-with-return for before_action authentication. Doesn't care about strict \"Bearer\" prefix validation in token extraction — fine with split.last." diff --git a/Gemfile b/Gemfile index 0b95b29..4b161c9 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,7 @@ gem "puma", ">= 5.0" # gem "jbuilder" # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] -# gem "bcrypt", "~> 3.1.7" +gem "bcrypt", "~> 3.1.7" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem "tzinfo-data", platforms: %i[ windows jruby ] diff --git a/Gemfile.lock b/Gemfile.lock index 7a346cd..7c74c6d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,6 +77,7 @@ GEM activesupport (>= 6.0.0) ast (2.4.3) base64 (0.3.0) + bcrypt (3.1.21) bcrypt_pbkdf (1.1.2) benchmark (0.5.0) bigdecimal (4.1.2) @@ -339,6 +340,7 @@ PLATFORMS DEPENDENCIES annotaterb + bcrypt (~> 3.1.7) bootsnap brakeman debug diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4ac8823..c1d2a38 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,15 @@ class ApplicationController < ActionController::API + before_action :authenticate! + + private + def authenticate! + token = request.headers["Authorization"]&.split(" ")&.last + @current_user = User.find_by(token:) + + render json: { error: "Unauthorized" }, status: :unauthorized unless @current_user + end + + def current_user + @current_user + end end diff --git a/app/models/user.rb b/app/models/user.rb index 12a5d4f..39e0d66 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -15,6 +15,7 @@ # index_users_on_email (email) UNIQUE # class User < ApplicationRecord + has_secure_password has_many :price_reports, dependent: :nullify has_many :moderation_logs, foreign_key: :admin_id, dependent: :nullify end diff --git a/db/migrate/20260530211142_add_token_to_users.rb b/db/migrate/20260530211142_add_token_to_users.rb new file mode 100644 index 0000000..ab56502 --- /dev/null +++ b/db/migrate/20260530211142_add_token_to_users.rb @@ -0,0 +1,6 @@ +class AddTokenToUsers < ActiveRecord::Migration[8.0] + def change + add_column :users, :token, :string + add_index :users, :token, unique: true + end +end