Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add basic library permissions #32

Merged
merged 3 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/controllers/libraries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@ def edit

# GET /libraries/1 or /libraries/1.json
def show; end

def users
@library = Library.find(params[:id])
@users = @library.users

respond_to do |format|
format.html # renders users.html.erb
format.json { render json: @users }
end
end
end
3 changes: 3 additions & 0 deletions app/models/library.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ class Library < ApplicationRecord
has_many :documents
validates :name, presence: true
belongs_to :user

has_many :library_users
has_many :users, through: :library_users
end
6 changes: 6 additions & 0 deletions app/models/library_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class LibraryUser < ApplicationRecord
belongs_to :user
belongs_to :library

enum role: { admin: 0, editor: 1 }
end
3 changes: 3 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ class User < ApplicationRecord
has_secure_password validations: false
validate :password_strength

has_many :library_users
has_many :libraries, through: :library_users

private

def password_strength
Expand Down
11 changes: 9 additions & 2 deletions app/policies/document_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ def initialize(user, document)
end

def create?
user.admin? || document.library.user_id == user.id
user.admin? || document.library.user_id == user.id || user_is_editor?
end

def update?
user.admin? || document.library.user_id == user.id
user.admin? || document.library.user_id == user.id || user_is_editor?
end

private

def user_is_editor?
library_user = LibraryUser.find_by(user: user, library: document.library)
library_user&.editor?
end
end
9 changes: 8 additions & 1 deletion app/policies/library_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ def create?
end

def update?
user.admin? || library.user_id == user.id
user.admin? || user_is_editor? || library.user_id == user.id
end

private

def user_is_editor?
library_user = LibraryUser.find_by(user: user, library: library)
library_user&.editor?
end
end
3 changes: 2 additions & 1 deletion app/views/libraries/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<div class="flex space-x-2">
<% if policy(@library).edit? %>
<%= link_to 'New Document', new_document_path(library_id: @library.id), class: "rounded-lg p-2 bg-sky-600 text-white" %>
<%= link_to 'Edit', edit_library_path(@library), class: "rounded-lg p-2 bg-sky-600 text-white" %>
<%= link_to 'Edit', edit_library_path(@library), title: "Edit Library", class: "rounded-lg p-2 bg-sky-600 text-white" %>
<%= link_to 'Users', users_library_path(@library), class: "rounded-lg p-2 bg-sky-600 text-white" %>
<% end %>
</div>
</div>
Expand Down
17 changes: 17 additions & 0 deletions app/views/libraries/users.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- app/views/libraries/users.html.erb -->

<h1 class="text-3xl font-semibold text-stone-900 mb-6"><span class="text-sky-500"><%= link_to @library.name, library_path(@library) %> </span> > Users </h1>

<div class="bg-white shadow-md rounded-lg overflow-hidden">
<div class="grid grid-cols-3 gap-4 p-4 bg-gray-200 font-semibold">
<div>Email</div>
<div>Role</div>
</div>

<% @users.each do |user| %>
<div class="grid grid-cols-3 gap-4 p-4 border-b border-gray-200">
<div><%= user.email %></div>
<div><%= user.library_users.find_by(library: @library).role.capitalize %></div>
</div>
<% end %>
</div>
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
# Nested Resources
resources :libraries do
resources :documents
member do
get 'users'
end
end

resources :delayed_jobs, only: %i[index destroy]
Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20240514224325_create_library_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateLibraryUsers < ActiveRecord::Migration[6.1]
def change
create_table :library_users do |t|
t.references :user, null: false, foreign_key: true
t.references :library, null: false, foreign_key: true
t.integer :role, null: false, default: 0

t.timestamps
end

add_index :library_users, [:user_id, :library_id], unique: true
end
end
16 changes: 15 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 39 additions & 2 deletions spec/controllers/libraries_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
RSpec.describe LibrariesController, type: :controller do
let(:user) { User.create!(email: '[email protected]', password: 'Password1!') }
let(:admin) { User.create!(email: '[email protected]', password: 'Password1!', admin: true) }
let(:editor) { User.create!(email: '[email protected]', password: 'Password1!') }
let(:library) { Library.create!(name: 'Library', user: admin) }
let!(:library_user) { LibraryUser.create!(user: editor, library: library, role: :editor) }
let(:valid_attributes) { { name: 'Library', user: admin } }

context 'as an admin user' do
Expand All @@ -21,10 +24,10 @@
end

describe 'POST #create' do
it 'does create a new Library' do
it 'creates a new Library' do
expect do
post :create, params: { library: valid_attributes }
end.to change(Library, :count)
end.to change(Library, :count).by(1)
end
end
end
Expand Down Expand Up @@ -55,4 +58,38 @@
end
end
end

context 'as an editor user' do
before do
allow_any_instance_of(LibrariesController).to receive(:current_user).and_return(editor)
end

describe 'GET #index' do
it 'returns a success response' do
get :index
expect(response).to be_successful
end
end

describe 'POST #create' do
it 'does not create a new Library' do
expect do
post :create, params: { library: valid_attributes }
end.to_not change(Library, :count)
end

it 'redirects to a certain page or renders an error' do
post :create, params: { library: valid_attributes }
expect(response).to redirect_to(root_path)
end
end

describe 'PUT #update' do
it 'allows the editor to update the library' do
put :update, params: { id: library.id, library: { name: 'Updated Library' } }
library.reload
expect(library.name).to eq('Updated Library')
end
end
end
end
Loading