Merge branch 'atomaka/feature/authorization' into 'master'
Add authorization via Pundit Also includes some a refactor to null object pattern for guest users. See merge request !24
This commit is contained in:
commit
1f9788309b
31 changed files with 678 additions and 231 deletions
|
@ -4,4 +4,5 @@ test:
|
||||||
- apt-get install -y nodejs libqtwebkit-dev qt4-qmake sqlite3 libsqlite3-dev
|
- apt-get install -y nodejs libqtwebkit-dev qt4-qmake sqlite3 libsqlite3-dev
|
||||||
- bundle install --path /cache
|
- bundle install --path /cache
|
||||||
- bundle exec rake db:create RAILS_ENV=test
|
- bundle exec rake db:create RAILS_ENV=test
|
||||||
|
- bundle exec rake db:test:prepare
|
||||||
- bundle exec rspec
|
- bundle exec rspec
|
||||||
|
|
10
Gemfile
10
Gemfile
|
@ -1,13 +1,5 @@
|
||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
def darwin_only(require_as)
|
|
||||||
RbConfig::CONFIG['host_os'] =~ /darwin/ && require_as
|
|
||||||
end
|
|
||||||
|
|
||||||
def linux_only(require_as)
|
|
||||||
RbConfig::CONFIG['host_os'] =~ /linux/ && require_as
|
|
||||||
end
|
|
||||||
|
|
||||||
gem 'rails', '4.2.3'
|
gem 'rails', '4.2.3'
|
||||||
gem 'sqlite3'
|
gem 'sqlite3'
|
||||||
|
|
||||||
|
@ -25,6 +17,8 @@ gem 'ancestry'
|
||||||
|
|
||||||
gem 'bcrypt'
|
gem 'bcrypt'
|
||||||
|
|
||||||
|
gem 'pundit'
|
||||||
|
|
||||||
gem 'sdoc', '~> 0.4.0', group: :doc
|
gem 'sdoc', '~> 0.4.0', group: :doc
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
|
|
@ -212,6 +212,8 @@ GEM
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
slop (~> 3.4)
|
slop (~> 3.4)
|
||||||
|
pundit (1.0.1)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
quiet_assets (1.1.0)
|
quiet_assets (1.1.0)
|
||||||
railties (>= 3.1, < 5.0)
|
railties (>= 3.1, < 5.0)
|
||||||
rack (1.6.4)
|
rack (1.6.4)
|
||||||
|
@ -387,6 +389,7 @@ DEPENDENCIES
|
||||||
launchy
|
launchy
|
||||||
metric_fu
|
metric_fu
|
||||||
pry
|
pry
|
||||||
|
pundit
|
||||||
quiet_assets
|
quiet_assets
|
||||||
rails (= 4.2.3)
|
rails (= 4.2.3)
|
||||||
rspec-rails
|
rspec-rails
|
||||||
|
@ -403,4 +406,4 @@ DEPENDENCIES
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.10.5
|
1.10.6
|
||||||
|
|
|
@ -6,10 +6,15 @@ class ApplicationController < ActionController::Base
|
||||||
helper_method :current_session
|
helper_method :current_session
|
||||||
helper_method :logged_in?
|
helper_method :logged_in?
|
||||||
|
|
||||||
|
include Pundit
|
||||||
|
|
||||||
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def current_user
|
def current_user
|
||||||
@current_user ||= User.find(current_session[:user_id]) if current_session
|
@current_user ||= User.find(current_session[:user_id]) if current_session
|
||||||
|
@current_user ||= GuestUser.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_session
|
def current_session
|
||||||
|
@ -17,6 +22,11 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def logged_in?
|
def logged_in?
|
||||||
!!current_user
|
current_user.registered?
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_not_authorized
|
||||||
|
flash[:alert] = 'You are not authorized to perform this action.'
|
||||||
|
redirect_to(request.referrer || root_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,22 +3,29 @@ class CommentsController < ApplicationController
|
||||||
before_filter :set_comment, only: [:show, :edit, :update, :destroy]
|
before_filter :set_comment, only: [:show, :edit, :update, :destroy]
|
||||||
before_filter :set_post
|
before_filter :set_post
|
||||||
before_filter :set_subcreddit
|
before_filter :set_subcreddit
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@comments = @comment
|
@comments = @comment
|
||||||
.subtree
|
.subtree
|
||||||
.includes(:post, :user)
|
.includes(:post, :user)
|
||||||
.arrange(order: :created_at)
|
.arrange(order: :created_at)
|
||||||
|
|
||||||
|
authorize @comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@comment = Comment.new(params[:parent_id])
|
@comment = Comment.new(params[:parent_id])
|
||||||
|
|
||||||
|
authorize @comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@comment = @post.comments.build comment_params
|
@comment = @post.comments.build comment_params
|
||||||
@comment.user = current_user
|
@comment.user = current_user
|
||||||
|
|
||||||
|
authorize @comment
|
||||||
|
|
||||||
if @comment.save
|
if @comment.save
|
||||||
flash[:notice] = 'Comment saved'
|
flash[:notice] = 'Comment saved'
|
||||||
else
|
else
|
||||||
|
@ -29,9 +36,12 @@ class CommentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
authorize @comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @comment
|
||||||
|
|
||||||
if @comment.update comment_params
|
if @comment.update comment_params
|
||||||
redirect_to subcreddit_post_path(@subcreddit, @post),
|
redirect_to subcreddit_post_path(@subcreddit, @post),
|
||||||
notice: 'Comment updated'
|
notice: 'Comment updated'
|
||||||
|
@ -41,6 +51,8 @@ class CommentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @comment
|
||||||
|
|
||||||
@comment.destroy
|
@comment.destroy
|
||||||
redirect_to subcreddit_post_path(@subcreddit, @post),
|
redirect_to subcreddit_post_path(@subcreddit, @post),
|
||||||
notice: 'Comment deleted'
|
notice: 'Comment deleted'
|
||||||
|
|
|
@ -2,23 +2,32 @@
|
||||||
class PostsController < ApplicationController
|
class PostsController < ApplicationController
|
||||||
before_filter :set_post, except: [:index, :new, :create]
|
before_filter :set_post, except: [:index, :new, :create]
|
||||||
before_filter :set_subcreddit
|
before_filter :set_subcreddit
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@posts = Post.includes(:subcreddit, :user).all
|
@posts = Post.includes(:subcreddit, :user).all
|
||||||
|
|
||||||
|
authorize Post
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@comments = @post.comments.includes(:user).arrange(order: :created_at)
|
@comments = @post.comments.includes(:user).arrange(order: :created_at)
|
||||||
|
|
||||||
|
authorize @post
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@post = Post.new
|
@post = Post.new
|
||||||
|
|
||||||
|
authorize @post
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@post = @subcreddit.posts.build(post_params)
|
@post = @subcreddit.posts.build(post_params)
|
||||||
@post.user = current_user
|
@post.user = current_user
|
||||||
|
|
||||||
|
authorize @post
|
||||||
|
|
||||||
if @post.save
|
if @post.save
|
||||||
redirect_to subcreddit_post_path(@subcreddit, @post),
|
redirect_to subcreddit_post_path(@subcreddit, @post),
|
||||||
notice: 'Post created'
|
notice: 'Post created'
|
||||||
|
@ -28,9 +37,12 @@ class PostsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
authorize @post
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @post
|
||||||
|
|
||||||
if @post.update(post_params)
|
if @post.update(post_params)
|
||||||
redirect_to subcreddit_post_path(@subcreddit, @post),
|
redirect_to subcreddit_post_path(@subcreddit, @post),
|
||||||
notice: 'Post was updated'
|
notice: 'Post was updated'
|
||||||
|
@ -40,6 +52,8 @@ class PostsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @post
|
||||||
|
|
||||||
@post.destroy
|
@post.destroy
|
||||||
|
|
||||||
redirect_to subcreddits_path(@subcreddit), notice: 'Post was deleted'
|
redirect_to subcreddits_path(@subcreddit), notice: 'Post was deleted'
|
||||||
|
|
|
@ -1,23 +1,32 @@
|
||||||
# controllers/subcreddits_controller.rb
|
# controllers/subcreddits_controller.rb
|
||||||
class SubcredditsController < ApplicationController
|
class SubcredditsController < ApplicationController
|
||||||
before_filter :set_subcreddit, only: [:show, :edit, :update]
|
before_filter :set_subcreddit, only: [:show, :edit, :update]
|
||||||
|
after_action :verify_authorized
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@subcreddits = Subcreddit.all
|
@subcreddits = Subcreddit.all
|
||||||
|
|
||||||
|
authorize Subcreddit
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@posts = @subcreddit.posts
|
@posts = @subcreddit.posts
|
||||||
|
|
||||||
|
authorize @subcreddit
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@subcreddit = Subcreddit.new
|
@subcreddit = Subcreddit.new
|
||||||
|
|
||||||
|
authorize @subcreddit
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@subcreddit = Subcreddit.new(create_subcreddit_params)
|
@subcreddit = Subcreddit.new(create_subcreddit_params)
|
||||||
@subcreddit.owner = current_user
|
@subcreddit.owner = current_user
|
||||||
|
|
||||||
|
authorize @subcreddit
|
||||||
|
|
||||||
if @subcreddit.save
|
if @subcreddit.save
|
||||||
redirect_to @subcreddit, notice: 'Subcreddit was created!'
|
redirect_to @subcreddit, notice: 'Subcreddit was created!'
|
||||||
else
|
else
|
||||||
|
@ -26,9 +35,12 @@ class SubcredditsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
authorize @subcreddit
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
authorize @subcreddit
|
||||||
|
|
||||||
if @subcreddit.update(update_subcreddit_params)
|
if @subcreddit.update(update_subcreddit_params)
|
||||||
redirect_to @subcreddit, notice: 'Subcreddit was updated!'
|
redirect_to @subcreddit, notice: 'Subcreddit was updated!'
|
||||||
else
|
else
|
||||||
|
|
6
app/models/guest_user.rb
Normal file
6
app/models/guest_user.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# models/guest_user.rb
|
||||||
|
class GuestUser
|
||||||
|
def registered?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,6 +15,10 @@ class User < ActiveRecord::Base
|
||||||
validates :username, presence: true, uniqueness: true, sluguuidless: true
|
validates :username, presence: true, uniqueness: true, sluguuidless: true
|
||||||
validates :password, length: { minimum: 8 }
|
validates :password, length: { minimum: 8 }
|
||||||
|
|
||||||
|
def registered?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def downcase_email
|
def downcase_email
|
||||||
|
|
37
app/policies/application_policy.rb
Normal file
37
app/policies/application_policy.rb
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# policies/application_policy.rb
|
||||||
|
class ApplicationPolicy
|
||||||
|
attr_reader :user, :record
|
||||||
|
|
||||||
|
def initialize(user, record)
|
||||||
|
@user = user
|
||||||
|
@record = record
|
||||||
|
end
|
||||||
|
|
||||||
|
def index?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def new?
|
||||||
|
create?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit?
|
||||||
|
update?
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
22
app/policies/comment_policy.rb
Normal file
22
app/policies/comment_policy.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# policies/comment_policy.rb
|
||||||
|
class CommentPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.registered?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user
|
||||||
|
end
|
||||||
|
end
|
22
app/policies/post_policy.rb
Normal file
22
app/policies/post_policy.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# policies/post_policy.rb
|
||||||
|
class PostPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.registered?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
record.user == user
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy?
|
||||||
|
record.user == user
|
||||||
|
end
|
||||||
|
end
|
18
app/policies/subcreddit_policy.rb
Normal file
18
app/policies/subcreddit_policy.rb
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# policies/subcreddit_policy.rb
|
||||||
|
class SubcredditPolicy < ApplicationPolicy
|
||||||
|
def index?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def show?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def create?
|
||||||
|
user.registered?
|
||||||
|
end
|
||||||
|
|
||||||
|
def update?
|
||||||
|
record.owner == user
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,12 +5,14 @@
|
||||||
button.btn.btn-default type="button"
|
button.btn.btn-default type="button"
|
||||||
span.glyphicon.glyphicon-search aria-hidden="true"
|
span.glyphicon.glyphicon-search aria-hidden="true"
|
||||||
|
|
||||||
|
- if policy(:post).new?
|
||||||
- if @subcreddit && @subcreddit.id
|
- if @subcreddit && @subcreddit.id
|
||||||
= link_to 'Submit a new link', new_subcreddit_post_path(@subcreddit), class: 'button btn btn-primary btn-block'
|
= link_to 'Submit a new link', new_subcreddit_post_path(@subcreddit), class: 'button btn btn-primary btn-block'
|
||||||
= link_to 'Submit a new text post', new_subcreddit_post_path(@subcreddit), class: 'button btn btn-primary btn-block'
|
= link_to 'Submit a new text post', new_subcreddit_post_path(@subcreddit), class: 'button btn btn-primary btn-block'
|
||||||
|
- if policy(:subcreddit).new?
|
||||||
= link_to 'Create your own subcreddit', new_subcreddit_path, class: 'button btn btn-primary btn-block'
|
= link_to 'Create your own subcreddit', new_subcreddit_path, class: 'button btn btn-primary btn-block'
|
||||||
|
|
||||||
- if @subcreddit && @subcreddit.id
|
- if @subcreddit && @subcreddit.id && policy(@subcreddit).edit?
|
||||||
.title Moderation Tools
|
.title Moderation Tools
|
||||||
.box
|
.box
|
||||||
ul
|
ul
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
.alert.alert-info.in-page
|
.alert.alert-info.in-page
|
||||||
p you are viewing a single comment's thread.
|
p you are viewing a single comment's thread.
|
||||||
p #{link_to 'view the rest of the comments', subcreddit_post_path(@subcreddit, @post)} →
|
p #{link_to 'view the rest of the comments', subcreddit_post_path(@subcreddit, @post)} →
|
||||||
= "Commenting as: #{current_user.username}"
|
- if policy(:comment).new?
|
||||||
== render 'comments/form', subcreddit: @subcreddit, post: @post, comment: @post.comments.build, parent: @comment
|
= "Commenting as: #{current_user.username}"
|
||||||
|
== render 'comments/form', subcreddit: @subcreddit, post: @post, comment: @post.comments.build, parent: @comment
|
||||||
.comments.contents
|
.comments.contents
|
||||||
== nested_comments(@comments)
|
== nested_comments(@comments)
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
.title= "all #{@post.comments_count} comments"
|
.title= "all #{@post.comments_count} comments"
|
||||||
- else
|
- else
|
||||||
.title= "no comments (yet)"
|
.title= "no comments (yet)"
|
||||||
= "Commenting as: #{current_user.username}"
|
- if policy(:comment).new?
|
||||||
== render 'comments/form', subcreddit: @subcreddit, post: @post, comment: @post.comments.build, parent: nil
|
= "Commenting as: #{current_user.username}"
|
||||||
|
== render 'comments/form', subcreddit: @subcreddit, post: @post, comment: @post.comments.build, parent: nil
|
||||||
.comments.contents
|
.comments.contents
|
||||||
== nested_comments(@comments)
|
== nested_comments(@comments)
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe ApplicationController, type: :controller do
|
||||||
|
|
||||||
context 'when not logged in' do
|
context 'when not logged in' do
|
||||||
it 'should return nil' do
|
it 'should return nil' do
|
||||||
expect(controller.send(:current_user)).to be_nil
|
expect(controller.send(:current_user)).to be_a(GuestUser)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -99,7 +99,8 @@ describe CommentsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#edit' do
|
describe '#edit' do
|
||||||
let!(:comment) { create(:comment) }
|
context 'when owner' do
|
||||||
|
let!(:comment) { create(:comment, user: user) }
|
||||||
before(:each) do
|
before(:each) do
|
||||||
get :edit,
|
get :edit,
|
||||||
id: comment,
|
id: comment,
|
||||||
|
@ -117,12 +118,15 @@ describe CommentsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context '#update' do
|
context '#update' do
|
||||||
let!(:comment) { create(:comment) }
|
|
||||||
let(:data) { { content: 'Some edited comment content goes here' } }
|
let(:data) { { content: 'Some edited comment content goes here' } }
|
||||||
|
|
||||||
context 'with valid data' do
|
context 'with valid data' do
|
||||||
|
let!(:comment) { create(:comment, user: user) }
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
put :update,
|
put :update,
|
||||||
id: comment,
|
id: comment,
|
||||||
|
@ -166,9 +170,11 @@ describe CommentsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context '#destroy' do
|
context '#destroy' do
|
||||||
let!(:comment) { create(:comment) }
|
context 'when owner' do
|
||||||
|
let!(:comment) { create(:comment, user: user) }
|
||||||
|
|
||||||
it 'should delete the post' do
|
it 'should delete the post' do
|
||||||
delete :destroy,
|
delete :destroy,
|
||||||
|
@ -186,7 +192,8 @@ describe CommentsController, type: :controller do
|
||||||
post_id: comment.post,
|
post_id: comment.post,
|
||||||
subcreddit_id: comment.post.subcreddit
|
subcreddit_id: comment.post.subcreddit
|
||||||
|
|
||||||
expect(response).to redirect_to(subcreddit_post_path(assigns(:subcreddit),
|
expect(response)
|
||||||
|
.to redirect_to(subcreddit_post_path(assigns(:subcreddit),
|
||||||
assigns(:post)))
|
assigns(:post)))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -198,4 +205,5 @@ describe CommentsController, type: :controller do
|
||||||
expect(flash[:notice]).to be_present
|
expect(flash[:notice]).to be_present
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -94,7 +94,8 @@ describe PostsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context '#edit' do
|
context '#edit' do
|
||||||
let!(:post) { create(:post) }
|
context 'when owner' do
|
||||||
|
let!(:post) { create(:post, user: user) }
|
||||||
before(:each) { get :edit, id: post, subcreddit_id: post.subcreddit }
|
before(:each) { get :edit, id: post, subcreddit_id: post.subcreddit }
|
||||||
|
|
||||||
context 'with valid post' do
|
context 'with valid post' do
|
||||||
|
@ -107,9 +108,9 @@ describe PostsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context '#update' do
|
context '#update' do
|
||||||
let!(:post) { create(:post) }
|
|
||||||
let(:data) do
|
let(:data) do
|
||||||
{
|
{
|
||||||
title: 'New title',
|
title: 'New title',
|
||||||
|
@ -117,6 +118,9 @@ describe PostsController, type: :controller do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let!(:post) { create(:post, user: user) }
|
||||||
|
|
||||||
context 'with valid data' do
|
context 'with valid data' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
put :update, id: post, subcreddit_id: post.subcreddit, post: data
|
put :update, id: post, subcreddit_id: post.subcreddit, post: data
|
||||||
|
@ -154,9 +158,11 @@ describe PostsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context '#destroy' do
|
context '#destroy' do
|
||||||
let!(:post) { create(:post, subcreddit: subcreddit) }
|
context 'when owner' do
|
||||||
|
let!(:post) { create(:post, user: user, subcreddit: subcreddit) }
|
||||||
|
|
||||||
it 'should delete the post' do
|
it 'should delete the post' do
|
||||||
expect { delete :destroy, subcreddit_id: subcreddit, id: post }
|
expect { delete :destroy, subcreddit_id: subcreddit, id: post }
|
||||||
|
@ -174,4 +180,5 @@ describe PostsController, type: :controller do
|
||||||
expect(flash[:notice]).to be_present
|
expect(flash[:notice]).to be_present
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,7 +97,8 @@ describe SubcredditsController, type: :controller do
|
||||||
|
|
||||||
describe '#edit' do
|
describe '#edit' do
|
||||||
context 'with valid subcreddit' do
|
context 'with valid subcreddit' do
|
||||||
let(:subcreddit) { create(:subcreddit) }
|
context 'when owner' do
|
||||||
|
let(:subcreddit) { create(:subcreddit, owner: user) }
|
||||||
|
|
||||||
it 'should assign @subcreddit to the existing subcreddit' do
|
it 'should assign @subcreddit to the existing subcreddit' do
|
||||||
get :edit, id: subcreddit
|
get :edit, id: subcreddit
|
||||||
|
@ -112,9 +113,9 @@ describe SubcredditsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#update' do
|
describe '#update' do
|
||||||
let(:subcreddit) { create(:subcreddit) }
|
|
||||||
let(:data) do
|
let(:data) do
|
||||||
{
|
{
|
||||||
closed: '1'
|
closed: '1'
|
||||||
|
@ -122,6 +123,9 @@ describe SubcredditsController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'wth valid data' do
|
context 'wth valid data' do
|
||||||
|
context 'when owner' do
|
||||||
|
let(:subcreddit) { create(:subcreddit, owner: user) }
|
||||||
|
|
||||||
it 'should assign @subcreddit to the existing subcreddit' do
|
it 'should assign @subcreddit to the existing subcreddit' do
|
||||||
put :update, id: subcreddit, subcreddit: data
|
put :update, id: subcreddit, subcreddit: data
|
||||||
|
|
||||||
|
@ -146,7 +150,6 @@ describe SubcredditsController, type: :controller do
|
||||||
|
|
||||||
expect(flash[:notice]).to be_present
|
expect(flash[:notice]).to be_present
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
context 'with invalid data' do
|
context 'with invalid data' do
|
||||||
before(:each) { data[:closed] = 'bad' }
|
before(:each) { data[:closed] = 'bad' }
|
||||||
|
@ -158,4 +161,6 @@ describe SubcredditsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,15 +3,20 @@ require 'rails_helper'
|
||||||
describe 'Edit Comment', type: :feature do
|
describe 'Edit Comment', type: :feature do
|
||||||
let!(:user) { create(:user) }
|
let!(:user) { create(:user) }
|
||||||
let!(:post) { create(:post) }
|
let!(:post) { create(:post) }
|
||||||
let!(:comment) { create(:comment, post: post, user: user) }
|
|
||||||
|
|
||||||
context 'when signed in' do
|
context 'when signed in' do
|
||||||
let(:content) { 'Some different data' }
|
let!(:comment) { create(:comment, post: post, user: user) }
|
||||||
|
|
||||||
before(:each) { signin(user: user) }
|
before(:each) { signin(user: user) }
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let(:content) { 'Some different data' }
|
||||||
|
|
||||||
context 'with valid data' do
|
context 'with valid data' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
visit edit_subcreddit_post_comment_path(post.subcreddit, post, comment)
|
visit edit_subcreddit_post_comment_path(post.subcreddit,
|
||||||
|
post,
|
||||||
|
comment)
|
||||||
|
|
||||||
fill_in :comment_content, with: content
|
fill_in :comment_content, with: content
|
||||||
|
|
||||||
|
@ -27,4 +32,25 @@ describe 'Edit Comment', type: :feature do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let!(:comment) { create(:comment, post: post) }
|
||||||
|
|
||||||
|
it 'should not allow editing of comment' do
|
||||||
|
visit edit_subcreddit_post_comment_path(post.subcreddit, post, comment)
|
||||||
|
|
||||||
|
expect(page).to have_content('not authorized')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not signed in' do
|
||||||
|
let!(:comment) { create(:comment, post: post) }
|
||||||
|
|
||||||
|
it 'should not allow editing of comment' do
|
||||||
|
visit edit_subcreddit_post_comment_path(post.subcreddit, post, comment)
|
||||||
|
|
||||||
|
expect(page).to have_content('not authorized')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe 'Edit Post', type: :feature do
|
describe 'Edit Post', type: :feature do
|
||||||
|
let!(:subcreddit) { create(:subcreddit) }
|
||||||
|
|
||||||
context 'when signed in' do
|
context 'when signed in' do
|
||||||
let!(:user) { create(:user) }
|
let!(:user) { create(:user) }
|
||||||
let!(:subcreddit) { create(:subcreddit) }
|
|
||||||
let!(:post) { create(:post, subcreddit: subcreddit, user: user) }
|
|
||||||
let(:new_post) { build_stubbed(:post) }
|
let(:new_post) { build_stubbed(:post) }
|
||||||
|
|
||||||
before(:each) { signin(user: user) }
|
before(:each) { signin(user: user) }
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let!(:post) { create(:post, subcreddit: subcreddit, user: user) }
|
||||||
|
|
||||||
context 'with valid data' do
|
context 'with valid data' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
visit edit_subcreddit_post_path(subcreddit, post)
|
visit edit_subcreddit_post_path(subcreddit, post)
|
||||||
|
@ -30,4 +33,26 @@ describe 'Edit Post', type: :feature do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let!(:post) { create(:post, subcreddit: subcreddit) }
|
||||||
|
|
||||||
|
it 'should notify user that they cannot edit' do
|
||||||
|
visit edit_subcreddit_post_path(subcreddit, post)
|
||||||
|
|
||||||
|
expect(page).to have_content 'not authorized'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not signed in' do
|
||||||
|
let!(:user) { GuestUser.new }
|
||||||
|
let!(:post) { create(:post, subcreddit: subcreddit) }
|
||||||
|
|
||||||
|
it 'should notify user they cannot edit' do
|
||||||
|
visit edit_subcreddit_post_path(subcreddit, post)
|
||||||
|
|
||||||
|
expect(page).to have_content 'not authorized'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe 'New Post', type: :feature do
|
describe 'New Post', type: :feature do
|
||||||
|
let!(:subcreddit) { create(:subcreddit) }
|
||||||
|
|
||||||
context 'when signed in' do
|
context 'when signed in' do
|
||||||
let!(:user) { create(:user) }
|
let!(:user) { create(:user) }
|
||||||
let!(:subcreddit) { create(:subcreddit) }
|
|
||||||
let!(:post) { build(:post, subcreddit: subcreddit) }
|
let!(:post) { build(:post, subcreddit: subcreddit) }
|
||||||
|
|
||||||
before(:each) { signin(user: user) }
|
before(:each) { signin(user: user) }
|
||||||
|
@ -46,4 +47,15 @@ describe 'New Post', type: :feature do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when not signed in' do
|
||||||
|
let!(:user) { GuestUser.new }
|
||||||
|
let!(:post) { create(:post, subcreddit: subcreddit) }
|
||||||
|
|
||||||
|
it 'should notify user they cannot create' do
|
||||||
|
visit new_subcreddit_post_path(subcreddit)
|
||||||
|
|
||||||
|
expect(page).to have_content 'not authorized'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,8 +4,13 @@ describe 'Edit Subcreddit', type: :feature do
|
||||||
before(:each) { signout }
|
before(:each) { signout }
|
||||||
|
|
||||||
context 'when logged in' do
|
context 'when logged in' do
|
||||||
|
let!(:user) { create(:user) }
|
||||||
|
before(:each) { signin(user: user) }
|
||||||
|
|
||||||
|
context 'when user is owner' do
|
||||||
|
let!(:subcreddit) { create(:subcreddit, owner: user) }
|
||||||
|
|
||||||
context 'when board is open' do
|
context 'when board is open' do
|
||||||
let!(:subcreddit) { create(:subcreddit) }
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
visit subcreddits_path
|
visit subcreddits_path
|
||||||
click_link 'Edit'
|
click_link 'Edit'
|
||||||
|
@ -23,7 +28,10 @@ describe 'Edit Subcreddit', type: :feature do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when board is closed' do
|
context 'when board is closed' do
|
||||||
let!(:subcreddit) { create(:subcreddit, closed_at: Time.now) }
|
let!(:subcreddit) do
|
||||||
|
create(:subcreddit, owner: user, closed_at: Time.now)
|
||||||
|
end
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
visit subcreddits_path
|
visit subcreddits_path
|
||||||
click_link 'Edit'
|
click_link 'Edit'
|
||||||
|
@ -36,4 +44,20 @@ describe 'Edit Subcreddit', type: :feature do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let!(:subcreddit) { create(:subcreddit) }
|
||||||
|
|
||||||
|
it 'should not allow editing of subcreddit' do
|
||||||
|
visit subcreddits_path
|
||||||
|
click_link 'Edit'
|
||||||
|
|
||||||
|
expect(page).to have_content('not authorized')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when not logged in' do
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,11 @@ describe 'New Subcreddit', type: :feature do
|
||||||
before(:each) { signout }
|
before(:each) { signout }
|
||||||
|
|
||||||
context 'when not signed in' do
|
context 'when not signed in' do
|
||||||
it 'should not be able to create a new subcreddit'
|
it 'should not be able to create a new subcreddit' do
|
||||||
|
visit new_subcreddit_path
|
||||||
|
|
||||||
|
expect(page).to have_content('not authorized')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when signed in' do
|
context 'when signed in' do
|
||||||
|
|
15
spec/policies/application_policy_spec.rb
Normal file
15
spec/policies/application_policy_spec.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe ApplicationPolicy do
|
||||||
|
subject { ApplicationPolicy.new(user, object) }
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:object) { double('Object') }
|
||||||
|
|
||||||
|
it { should_not grant(:index) }
|
||||||
|
it { should_not grant(:show) }
|
||||||
|
it { should_not grant(:new) }
|
||||||
|
it { should_not grant(:create) }
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
48
spec/policies/comment_policy_spec.rb
Normal file
48
spec/policies/comment_policy_spec.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe CommentPolicy do
|
||||||
|
subject { CommentPolicy.new(user, comment) }
|
||||||
|
|
||||||
|
context 'when user is a guest' do
|
||||||
|
let(:comment) { create(:comment) }
|
||||||
|
let(:user) { GuestUser.new }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
|
||||||
|
it { should_not grant(:new) }
|
||||||
|
it { should_not grant(:create) }
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is registered' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let(:comment) { create(:comment) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let(:comment) { create(:comment, user: user) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
it { should grant(:edit) }
|
||||||
|
it { should grant(:update) }
|
||||||
|
it { should grant(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
48
spec/policies/post_policy_spec.rb
Normal file
48
spec/policies/post_policy_spec.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe PostPolicy do
|
||||||
|
subject { PostPolicy.new(user, post) }
|
||||||
|
|
||||||
|
context 'when user is a guest' do
|
||||||
|
let(:post) { create(:post) }
|
||||||
|
let(:user) { GuestUser.new }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
|
||||||
|
it { should_not grant(:new) }
|
||||||
|
it { should_not grant(:create) }
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is registered' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let(:post) { create(:post) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let(:post) { create(:post, user: user) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
it { should grant(:edit) }
|
||||||
|
it { should grant(:update) }
|
||||||
|
it { should grant(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
49
spec/policies/subcreddit_policy_spec.rb
Normal file
49
spec/policies/subcreddit_policy_spec.rb
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe SubcredditPolicy do
|
||||||
|
subject { SubcredditPolicy.new(user, subcreddit) }
|
||||||
|
|
||||||
|
context 'when user is a guest' do
|
||||||
|
let(:subcreddit) { create(:subcreddit) }
|
||||||
|
let(:user) { GuestUser.new }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
|
||||||
|
it { should_not grant(:new) }
|
||||||
|
it { should_not grant(:create) }
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is registered' do
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
context 'when not owner' do
|
||||||
|
let(:subcreddit) { create(:subcreddit) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
|
||||||
|
it { should_not grant(:edit) }
|
||||||
|
it { should_not grant(:update) }
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when owner' do
|
||||||
|
let(:subcreddit) { create(:subcreddit, owner: user) }
|
||||||
|
|
||||||
|
it { should grant(:index) }
|
||||||
|
it { should grant(:show) }
|
||||||
|
it { should grant(:new) }
|
||||||
|
it { should grant(:create) }
|
||||||
|
it { should grant(:edit) }
|
||||||
|
it { should grant(:update) }
|
||||||
|
|
||||||
|
it { should_not grant(:destroy) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,11 +12,13 @@ require 'rspec/rails'
|
||||||
require 'shoulda/matchers'
|
require 'shoulda/matchers'
|
||||||
require 'capybara/rails'
|
require 'capybara/rails'
|
||||||
require 'capybara/rspec'
|
require 'capybara/rspec'
|
||||||
|
require 'pundit/rspec'
|
||||||
|
|
||||||
require 'support/capybara'
|
require 'support/capybara'
|
||||||
require 'support/database_cleaner'
|
require 'support/database_cleaner'
|
||||||
require 'support/factory_girl'
|
require 'support/factory_girl'
|
||||||
require 'support/helpers'
|
require 'support/helpers'
|
||||||
|
require 'support/pundit_matcher'
|
||||||
|
|
||||||
ActiveRecord::Migration.maintain_test_schema!
|
ActiveRecord::Migration.maintain_test_schema!
|
||||||
|
|
||||||
|
|
15
spec/support/pundit_matcher.rb
Normal file
15
spec/support/pundit_matcher.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
RSpec::Matchers.define :grant do |action|
|
||||||
|
match do |policy|
|
||||||
|
policy.public_send("#{action}?")
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message do |policy|
|
||||||
|
"#{policy.class} does not permit #{action} on #{policy.record} "
|
||||||
|
+ "for #{policy.user.inspect}."
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message_when_negated do |policy|
|
||||||
|
"#{policy.class} does not forbid #{action} on #{policy.record} "
|
||||||
|
+ "for #{policy.user.inspect}."
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue