From f43dd5b0cd3ac1d2db8dbf519d2fd5bf380e9cdf Mon Sep 17 00:00:00 2001 From: Kaio Magalhaes Date: Wed, 5 Jun 2024 18:29:47 -0300 Subject: [PATCH] add project auth --- app/controllers/application_controller.rb | 28 ++++++++++++--- app/controllers/projects_controller.rb | 2 +- app/models/project_auth.rb | 35 +++++++++++++++++++ .../20240605183622_create_project_auths.rb | 12 +++++++ db/schema.rb | 11 +++++- spec/factories/project_auths.rb | 26 ++++++++++++++ spec/models/project_auth_spec.rb | 25 +++++++++++++ 7 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 app/models/project_auth.rb create mode 100644 db/migrate/20240605183622_create_project_auths.rb create mode 100644 spec/factories/project_auths.rb create mode 100644 spec/models/project_auth_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0ea58e9..17bbeda 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,11 +3,21 @@ class ApplicationController < ActionController::API before_action :set_default_response_format before_action :authenticate - attr_reader :current_user + attr_reader :current_user, :current_project def authenticate - return user_invalid! unless authorization_header + if authorization_header + authenticate_user + elsif project_auth_key + authenticate_project + else + user_invalid! + end + end + + private + def authenticate_user user = User.find_or_initialize_by({ email: user_auth_params['email'], google_id: user_auth_params['google_id'] @@ -15,10 +25,16 @@ def authenticate return user_invalid! unless user.valid? save_user!(user) - @current_user = user end + def authenticate_project + project_auth = ProjectAuth.find_by(key: project_auth_key) + return user_invalid! unless project_auth + + @current_project = project_auth.project + end + def save_user!(user) if user.new_record? user.first_name = user_auth_params['first_name'] @@ -29,7 +45,7 @@ def save_user!(user) end def user_invalid! - render_error('Invalid user', :unauthorized) + render_error('Invalid user or project', :unauthorized) end def render_error(message, status) @@ -45,6 +61,10 @@ def authorization_header request.headers['Authorization'] end + def project_auth_key + request.headers['Project-Auth-Key'] + end + def user_auth_params return @user_auth_params if @user_auth_params diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 550df62..a172011 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -36,7 +36,7 @@ def destroy private def set_project - @project = Project.friendly.find(params[:id]) + @project = @current_project || Project.friendly.find(params[:id]) end def project_params diff --git a/app/models/project_auth.rb b/app/models/project_auth.rb new file mode 100644 index 0000000..b1c25ca --- /dev/null +++ b/app/models/project_auth.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: project_auths +# +# id :bigint not null, primary key +# key :string +# created_at :datetime not null +# updated_at :datetime not null +# project_id :bigint not null +# +# Indexes +# +# index_project_auths_on_project_id (project_id) +# +# Foreign Keys +# +# fk_rails_... (project_id => projects.id) +# +class ProjectAuth < ApplicationRecord + belongs_to :project + + before_create :generate_key, unless: :key_present? + + private + + def generate_key + self.key = SecureRandom.hex(10) # Generates a random hex string of 20 characters + end + + def key_present? + key.present? + end +end diff --git a/db/migrate/20240605183622_create_project_auths.rb b/db/migrate/20240605183622_create_project_auths.rb new file mode 100644 index 0000000..fd6f50c --- /dev/null +++ b/db/migrate/20240605183622_create_project_auths.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class CreateProjectAuths < ActiveRecord::Migration[7.0] + def change + create_table :project_auths do |t| + t.references :project, null: false, foreign_key: true + t.string :key + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index f6045a1..353da98 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.0].define(version: 2024_05_15_131152) do +ActiveRecord::Schema[7.0].define(version: 2024_06_05_183622) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "plpgsql" @@ -169,6 +169,14 @@ t.datetime "updated_at", null: false end + create_table "project_auths", force: :cascade do |t| + t.bigint "project_id", null: false + t.string "key" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["project_id"], name: "index_project_auths_on_project_id" + end + create_table "projects", force: :cascade do |t| t.string "name" t.bigint "customer_id", null: false @@ -357,6 +365,7 @@ add_foreign_key "dynamic_datasets", "projects" add_foreign_key "issues", "projects" add_foreign_key "payments", "statement_of_works" + add_foreign_key "project_auths", "projects" add_foreign_key "projects", "customers" add_foreign_key "requirements", "professions" add_foreign_key "requirements", "statement_of_works" diff --git a/spec/factories/project_auths.rb b/spec/factories/project_auths.rb new file mode 100644 index 0000000..3f9e516 --- /dev/null +++ b/spec/factories/project_auths.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: project_auths +# +# id :bigint not null, primary key +# key :string +# created_at :datetime not null +# updated_at :datetime not null +# project_id :bigint not null +# +# Indexes +# +# index_project_auths_on_project_id (project_id) +# +# Foreign Keys +# +# fk_rails_... (project_id => projects.id) +# +FactoryBot.define do + factory :project_auth do + project { nil } + key { 'MyString' } + end +end diff --git a/spec/models/project_auth_spec.rb b/spec/models/project_auth_spec.rb new file mode 100644 index 0000000..4f5b1ab --- /dev/null +++ b/spec/models/project_auth_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: project_auths +# +# id :bigint not null, primary key +# key :string +# created_at :datetime not null +# updated_at :datetime not null +# project_id :bigint not null +# +# Indexes +# +# index_project_auths_on_project_id (project_id) +# +# Foreign Keys +# +# fk_rails_... (project_id => projects.id) +# +require 'rails_helper' + +RSpec.describe ProjectAuth, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end