diff --git a/app/controllers/api/v1/companies_controller.rb b/app/controllers/api/v1/companies_controller.rb index 33fa4c6..8a2dceb 100644 --- a/app/controllers/api/v1/companies_controller.rb +++ b/app/controllers/api/v1/companies_controller.rb @@ -4,8 +4,8 @@ class CompaniesController < ApplicationController before_action :authenticate_user def index - companies = @current_user.companies - + companies = policy_scope(@current_user.companies) + authorize companies if companies.empty? render json: { data: [], message: "No companies found" } else @@ -14,6 +14,7 @@ def index end def create + authorize Company company = @current_user.companies.build(company_params) if company.save render json: CompanySerializer.new(company), status: :created @@ -27,6 +28,8 @@ def create def company_params params.permit(:name, :website, :street_address, :city, :state, :zip_code, :notes) end + + end end end \ No newline at end of file diff --git a/app/models/company.rb b/app/models/company.rb index 381123d..79927bd 100644 --- a/app/models/company.rb +++ b/app/models/company.rb @@ -1,4 +1,5 @@ class Company < ApplicationRecord + rolify strict: true belongs_to :user validates :name, presence: true validates :website, presence: true diff --git a/app/policies/company_policy.rb b/app/policies/company_policy.rb index aa512b2..b1aabbd 100644 --- a/app/policies/company_policy.rb +++ b/app/policies/company_policy.rb @@ -1,14 +1,21 @@ class CompanyPolicy < ApplicationPolicy - # NOTE: Up to Pundit v2.3.1, the inheritance was declared as - # `Scope < Scope` rather than `Scope < ApplicationPolicy::Scope`. - # In most cases the behavior will be identical, but if updating existing - # code, beware of possible changes to the ancestors: - # https://gist.github.com/Burgestrand/4b4bc22f31c8a95c425fc0e30d7ef1f5 + def create? + user.present? + end + + def index? + admin? || user? + end class Scope < ApplicationPolicy::Scope - # NOTE: Be explicit about which records you allow access to! - # def resolve - # scope.all - # end + def resolve + return scope.none unless user + + if admin? + scope.all + else + scope.where(user_id: user.id) + end + end end end diff --git a/db/schema.rb b/db/schema.rb index 11174c1..e9f0af7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. - ActiveRecord::Schema[7.1].define(version: 2024_12_07_034959) do - # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -45,17 +43,6 @@ t.index ["user_id"], name: "index_contacts_on_user_id" end - - create_table "roles", force: :cascade do |t| - t.string "name" - t.string "resource_type" - t.bigint "resource_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" - t.index ["resource_type", "resource_id"], name: "index_roles_on_resource" - end - create_table "job_applications", force: :cascade do |t| t.string "position_title" t.date "date_applied" @@ -70,7 +57,16 @@ t.bigint "user_id", null: false t.index ["company_id"], name: "index_job_applications_on_company_id" t.index ["user_id"], name: "index_job_applications_on_user_id" + end + create_table "roles", force: :cascade do |t| + t.string "name" + t.string "resource_type" + t.bigint "resource_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" + t.index ["resource_type", "resource_id"], name: "index_roles_on_resource" end create_table "users", force: :cascade do |t| @@ -92,7 +88,6 @@ add_foreign_key "companies", "users" add_foreign_key "contacts", "companies" add_foreign_key "contacts", "users" - add_foreign_key "job_applications", "companies" add_foreign_key "job_applications", "users" -end \ No newline at end of file +end diff --git a/spec/policies/company_policy_spec.rb b/spec/policies/company_policy_spec.rb index 23b05c6..bf6cfd9 100644 --- a/spec/policies/company_policy_spec.rb +++ b/spec/policies/company_policy_spec.rb @@ -1,27 +1,90 @@ require 'rails_helper' RSpec.describe CompanyPolicy, type: :policy do - let(:user) { User.new } - subject { described_class } - permissions ".scope" do - pending "add some examples to (or delete) #{__FILE__}" + let(:user) { User.create!(name: "user", email: "user@email.com", password: "123") } + let(:other_user) { User.create!(name: "other_user", email: "other_user@email.com", password: "234") } + let(:admin) { User.create!(name: "admin", email: "admin@email.com", password: "456") } + + let(:company) do + Company.create!( + name: "Test Company", + website: "https://testcompany.com", + street_address: "123 Main St", + city: "Testville", + state: "TS", + zip_code: "12345", + notes: "A test company", + user: user + ) + end + + let(:other_company) do + Company.create!( + name: "Other Company", + website: "https://othercompany.com", + street_address: "456 Elm St", + city: "Othertown", + state: "OT", + zip_code: "67890", + notes: "Another test company", + user: other_user + ) end - permissions :show? do - pending "add some examples to (or delete) #{__FILE__}" + before(:each) do + admin.set_role(:admin) end permissions :create? do - pending "add some examples to (or delete) #{__FILE__}" - end + it "allows any logged-in user to create a company" do + expect(subject).to permit(user, Company.new) + expect(subject).to permit(admin, Company.new) + end - permissions :update? do - pending "add some examples to (or delete) #{__FILE__}" + it "does not allow guests to create a company" do + expect(subject).not_to permit(nil, Company.new) + end end - permissions :destroy? do - pending "add some examples to (or delete) #{__FILE__}" + permissions ".scope" do + let(:scope) { Pundit.policy_scope!(current_user, Company) } + + context "when the user is an admin" do + let(:current_user) { admin } + + it "returns all companies" do + company + other_company + expect(scope).to match_array(Company.all) + end + end + + context "when the user is a regular user" do + let(:current_user) { user } + + it "returns only the user's companies" do + company + other_company + expect(scope).to match_array([company]) + end + + it "does not return other users' companies" do + company + other_company + expect(scope).not_to include(other_company) + end + end + + context "when no user is logged in" do + let(:current_user) { nil } + + it "returns an empty relation" do + company + other_company + expect(scope).to match_array([]) + end + end end end