Skip to content

Commit

Permalink
Merge pull request #690 from ShelterTechSF/687-authorization-schema
Browse files Browse the repository at this point in the history
687 authorization schema
  • Loading branch information
schroerbrian authored Aug 23, 2023
2 parents 23a045b + 2cb8a16 commit 11a1901
Show file tree
Hide file tree
Showing 21 changed files with 343 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ group :development, :test do
gem 'rubocop'
end

group :development do
gem 'annotate', require: false
end

group :test do
gem 'rspec-collection_matchers'
end
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ GEM
algoliasearch-rails (2.2.1)
algolia (< 3.0.0)
json (>= 1.5.1)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
ast (2.4.2)
builder (3.2.4)
bullet (6.1.5)
Expand Down Expand Up @@ -315,6 +318,7 @@ PLATFORMS
DEPENDENCIES
airrecord
algoliasearch-rails
annotate
bullet
byebug
dotenv-rails
Expand Down
26 changes: 26 additions & 0 deletions app/models/group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: groups
#
# id :bigint not null, primary key
# name :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_groups_on_name (name) UNIQUE
#

# Groups provide a way to categorize a given group of users and to assign
# specific permissions to said group

class Group < ApplicationRecord
has_and_belongs_to_many(:users,
join_table: "user_groups")

has_and_belongs_to_many(:permissions,
join_table: "group_permissions")
end
18 changes: 18 additions & 0 deletions app/models/group_permission.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: group_permissions
#
# group_id :bigint not null
# permission_id :bigint not null
#
# Indexes
#
# index_group_permissions_on_group_id_and_permission_id (group_id,permission_id)
# index_group_permissions_on_permission_id_and_group_id (permission_id,group_id)
#
class GroupPermission < ApplicationRecord
belongs_to :group
belongs_to :permission
end
31 changes: 31 additions & 0 deletions app/models/permission.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: permissions
#
# id :bigint not null, primary key
# action :integer
# resource_id :bigint
# service_id :bigint
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_permissions_on_resource_id (resource_id)
# index_permissions_on_resource_id_and_action (resource_id,action) UNIQUE
# index_permissions_on_service_id (service_id)
# index_permissions_on_service_id_and_action (service_id,action) UNIQUE
#

# The permissions system provides a way to assign specific permissions
# to a group to view/alter specific objects.

class Permission < ApplicationRecord
enum action: { add: 0, view: 1, edit: 2, remove: 3 }

has_and_belongs_to_many(:groups, join_table: "group_permissions")
belongs_to :resource, optional: true
belongs_to :service, optional: true
end
1 change: 1 addition & 0 deletions app/models/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Resource < ActiveRecord::Base
has_many :change_requests, dependent: :destroy
has_many :programs, dependent: :destroy
has_many :feedbacks, dependent: :destroy
has_many :permissions, dependent: :destroy
has_many :textings

accepts_nested_attributes_for :notes
Expand Down
1 change: 1 addition & 0 deletions app/models/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Service < ActiveRecord::Base
has_many :feedbacks, dependent: :destroy
has_many :textings
has_many :instructions
has_many :permissions, dependent: :destroy
has_one :schedule, dependent: :destroy
has_and_belongs_to_many :categories
has_and_belongs_to_many :eligibilities, dependent: :destroy
Expand Down
9 changes: 9 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# name :string
#
class User < ActiveRecord::Base
has_and_belongs_to_many(:groups,
join_table: "user_groups")
end
18 changes: 18 additions & 0 deletions app/models/user_group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: user_groups
#
# user_id :bigint not null
# group_id :bigint not null
#
# Indexes
#
# index_user_groups_on_group_id (group_id)
# index_user_groups_on_user_id (user_id)
#
class UserGroup < ApplicationRecord
belongs_to :user
belongs_to :groups
end
9 changes: 9 additions & 0 deletions db/migrate/20230427235835_create_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreateGroups < ActiveRecord::Migration[6.1]
def change
create_table :groups do |t|
t.string :name
t.index :name, unique: true
t.timestamps
end
end
end
8 changes: 8 additions & 0 deletions db/migrate/20230428011849_create_join_table_users_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateJoinTableUsersGroups < ActiveRecord::Migration[6.1]
def change
create_join_table :users, :groups, table_name: :user_groups do |t|
t.index :user_id
t.index :group_id
end
end
end
35 changes: 35 additions & 0 deletions db/migrate/20230428215550_create_permissions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class CreatePermissions < ActiveRecord::Migration[6.1]
def change
create_table :permissions do |t|
t.integer :action
t.references :resource, foreign_key: true
t.references :service, foreign_key: true

t.timestamps
end

add_index :permissions, [:service_id, :action], unique: true
add_index :permissions, [:resource_id, :action], unique: true

reversible do |dir|
dir.up do
execute <<-SQL
ALTER TABLE permissions
ADD CONSTRAINT resource_xor_service
CHECK (
(resource_id IS NOT NULL AND service_id IS NULL) OR
(resource_id IS NULL AND service_id IS NOT NULL)
)
SQL
end

dir.down do
execute <<-SQL
ALTER TABLE permissions
DROP CONSTRAINT resource_xor_service
SQL
end
end

end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateJoinTableGroupPermissions < ActiveRecord::Migration[6.1]
def change
create_join_table :groups, :permissions, table_name: :group_permissions do |t|
t.index [:group_id, :permission_id]
t.index [:permission_id, :group_id]
end
end
end
36 changes: 36 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@
t.datetime "updated_at", null: false
end

create_table "group_permissions", id: false, force: :cascade do |t|
t.bigint "group_id", null: false
t.bigint "permission_id", null: false
t.index ["group_id", "permission_id"], name: "index_group_permissions_on_group_id_and_permission_id"
t.index ["permission_id", "group_id"], name: "index_group_permissions_on_permission_id_and_group_id"
end

create_table "groups", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["name"], name: "index_groups_on_name", unique: true
end

create_table "instructions", force: :cascade do |t|
t.string "instruction"
t.datetime "created_at", precision: 6, null: false
Expand Down Expand Up @@ -266,6 +280,19 @@
t.index ["service_id"], name: "index_notes_on_service_id"
end

create_table "permissions", force: :cascade do |t|
t.integer "action"
t.bigint "resource_id"
t.bigint "service_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["resource_id", "action"], name: "index_permissions_on_resource_id_and_action", unique: true
t.index ["resource_id"], name: "index_permissions_on_resource_id"
t.index ["service_id", "action"], name: "index_permissions_on_service_id_and_action", unique: true
t.index ["service_id"], name: "index_permissions_on_service_id"
t.check_constraint "((resource_id IS NOT NULL) AND (service_id IS NULL)) OR ((resource_id IS NULL) AND (service_id IS NOT NULL))", name: "resource_xor_service"
end

create_table "phones", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
Expand Down Expand Up @@ -426,6 +453,13 @@
t.check_constraint "((resource_id IS NOT NULL) AND (service_id IS NULL)) OR ((resource_id IS NULL) AND (service_id IS NOT NULL))", name: "resource_xor_service"
end

create_table "user_groups", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "group_id", null: false
t.index ["group_id"], name: "index_user_groups_on_group_id"
t.index ["user_id"], name: "index_user_groups_on_user_id"
end

create_table "users", id: :serial, force: :cascade do |t|
t.string "name"
end
Expand All @@ -451,6 +485,8 @@
add_foreign_key "instructions", "services"
add_foreign_key "notes", "resources"
add_foreign_key "notes", "services"
add_foreign_key "permissions", "resources"
add_foreign_key "permissions", "services"
add_foreign_key "phones", "contacts"
add_foreign_key "phones", "languages"
add_foreign_key "phones", "resources"
Expand Down
20 changes: 20 additions & 0 deletions spec/factories/groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: groups
#
# id :bigint not null, primary key
# name :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_groups_on_name (name) UNIQUE
#
FactoryBot.define do
factory :group do
name { "MyString" }
end
end
24 changes: 24 additions & 0 deletions spec/factories/permissions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: permissions
#
# id :bigint not null, primary key
# action :integer
# resource_id :bigint
# service_id :bigint
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_permissions_on_resource_id (resource_id)
# index_permissions_on_resource_id_and_action (resource_id,action) UNIQUE
# index_permissions_on_service_id (service_id)
# index_permissions_on_service_id_and_action (service_id,action) UNIQUE
#
FactoryBot.define do
factory :permission do
end
end
20 changes: 20 additions & 0 deletions spec/factories/user_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: user_groups
#
# user_id :bigint not null
# group_id :bigint not null
#
# Indexes
#
# index_user_groups_on_group_id (group_id)
# index_user_groups_on_user_id (user_id)
#
FactoryBot.define do
factory :user_group do
user { nil }
groups { nil }
end
end
7 changes: 7 additions & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# name :string
#
FactoryBot.define do
factory :user do
name { Faker::Name.name }
Expand Down
20 changes: 20 additions & 0 deletions spec/models/group_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: groups
#
# id :bigint not null, primary key
# name :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_groups_on_name (name) UNIQUE
#
require 'rails_helper'

RSpec.describe Group, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading

0 comments on commit 11a1901

Please sign in to comment.