Skip to content
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
20 changes: 15 additions & 5 deletions lib/jsonapi/authorization/authorizing_operations_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,29 @@ def operation_resource_id
end
end

def resource_class_for_relationship(assoc_name)
@operation.resource_klass._relationship(assoc_name).resource_klass
end

def model_class_for_relationship(assoc_name)
@operation.resource_klass._relationship(assoc_name).resource_klass._model_class
resource_class_for_relationship(assoc_name)._model_class
end

def related_models
data = @operation.options[:data]
return [] if data.nil?

[:to_one, :to_many].flat_map do |rel_type|
data[rel_type].flat_map do |assoc_name, assoc_ids|
assoc_klass = model_class_for_relationship(assoc_name)
# TODO: find_by_key?
assoc_klass.find(assoc_ids)
data[rel_type].flat_map do |assoc_name, assoc_value|
case assoc_value
when Hash # polymorphic relationship
resource_class = @operation.resource_klass.resource_for(assoc_value[:type].to_s)
resource_class.find_by_key(assoc_value[:id], context: @operation.options[:context])._model
else
resource_class = resource_class_for_relationship(assoc_name)
primary_key = resource_class._primary_key
resource_class._model_class.where(primary_key => assoc_value)
end
end
end
end
Expand Down
23 changes: 23 additions & 0 deletions spec/dummy/app/controllers/tags_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class TagsController < ActionController::Base
include JSONAPI::ActsAsResourceController
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

private

def context
{user: nil}
end

# https://github.com/cerebris/jsonapi-resources/pull/573
def handle_exceptions(e)
if JSONAPI.configuration.exception_class_whitelist.any? { |k| e.class.ancestors.include?(k) }
raise e
else
super
end
end

def user_not_authorized
head :forbidden
end
end
5 changes: 5 additions & 0 deletions spec/dummy/app/models/article.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
class Article < ActiveRecord::Base
has_many :comments
has_many :tags, as: :taggable
belongs_to :author, class_name: 'User'

def to_param
external_id
end
end
1 change: 1 addition & 0 deletions spec/dummy/app/models/comment.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class Comment < ActiveRecord::Base
has_many :tags, as: :taggable
belongs_to :article
end
3 changes: 3 additions & 0 deletions spec/dummy/app/models/tag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Tag < ActiveRecord::Base
belongs_to :taggable, polymorphic: true
end
34 changes: 34 additions & 0 deletions spec/dummy/app/policies/tag_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class TagPolicy
class Scope < Struct.new(:user, :scope)
def resolve
raise NotImplementedError
end
end

attr_reader :user, :record

def initialize(user, record)
@user = user
@record = record
end

def index?
raise NotImplementedError
end

def show?
raise NotImplementedError
end

def create?
raise NotImplementedError
end

def update?
raise NotImplementedError
end

def destroy?
raise NotImplementedError
end
end
11 changes: 11 additions & 0 deletions spec/dummy/app/resources/article_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,16 @@ class ArticleResource < JSONAPI::Resource
include JSONAPI::Authorization::PunditScopedResource

has_many :comments, acts_as_set: true
has_many :tags
has_one :author, class_name: 'User'

primary_key :external_id

def self.verify_key(key, _context = nil)
key && String(key)
end

def id=(external_id)
_model.external_id = external_id
end
end
3 changes: 3 additions & 0 deletions spec/dummy/app/resources/comment_resource.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
class CommentResource < JSONAPI::Resource
include JSONAPI::Authorization::PunditScopedResource

has_many :tags
has_one :article
end
5 changes: 5 additions & 0 deletions spec/dummy/app/resources/tag_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class TagResource < JSONAPI::Resource
include JSONAPI::Authorization::PunditScopedResource

has_one :taggable, polymorphic: true
end
4 changes: 4 additions & 0 deletions spec/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
jsonapi_resources :articles do
jsonapi_relationships
end
jsonapi_resources :comments do
jsonapi_relationships
end
jsonapi_resources :tags
end
5 changes: 5 additions & 0 deletions spec/dummy/db/migrate/20160125083537_create_models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ def change
end

create_table :articles do |t|
t.string :external_id, null: false
t.references :author
end

create_table :tags do |t|
t.references :taggable, polymorphic: true
end
end
end
6 changes: 6 additions & 0 deletions spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@
ActiveRecord::Schema.define(version: 20160125083537) do

create_table "articles", force: :cascade do |t|
t.string "external_id", null: false
t.integer "author_id"
end

create_table "comments", force: :cascade do |t|
t.integer "article_id"
end

create_table "tags", force: :cascade do |t|
t.integer "taggable_id"
t.string "taggable_type"
end

create_table "users", force: :cascade do |t|
end

Expand Down
8 changes: 6 additions & 2 deletions spec/fixtures/articles.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
---
article_with_comments: {}
article_without_comments: {}
article_with_comments:
external_id: 1
article_without_comments:
external_id: 2
article_with_author:
external_id: 3
author: user_1
article_without_author:
external_id: 4
author: ~
9 changes: 9 additions & 0 deletions spec/fixtures/tags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
tag_1:
taggable: comment_1
tag_2:
taggable: comment_1
tag_3:
taggable: article_with_comments
tag_4:
taggable: article_with_comments
4 changes: 2 additions & 2 deletions spec/requests/related_resources_operations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
end

describe 'GET /articles/:id/comments' do
subject(:last_response) { get("/articles/#{article.id}/comments") }
subject(:last_response) { get("/articles/#{article.external_id}/comments") }
let(:article) { articles(:article_with_comments) }

let(:policy_scope) { Article.all }
Expand Down Expand Up @@ -54,7 +54,7 @@
end

describe 'GET /articles/:id/author' do
subject(:last_response) { get("/articles/#{article.id}/author") }
subject(:last_response) { get("/articles/#{article.external_id}/author") }
let(:article) { articles(:article_with_author) }
let(:policy_scope) { Article.all }

Expand Down
14 changes: 7 additions & 7 deletions spec/requests/relationship_operations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
before do
allow_any_instance_of(CommentPolicy::Scope).to receive(:resolve).and_return(comments_policy_scope)
end
subject(:last_response) { get("/articles/#{article.id}/relationships/comments") }
subject(:last_response) { get("/articles/#{article.external_id}/relationships/comments") }

context 'unauthorized for show_relationship' do
before { disallow_operation('show_relationship', article, nil) }
Expand All @@ -52,7 +52,7 @@
end

describe 'GET /articles/:id/relationships/author' do
subject(:last_response) { get("/articles/#{article.id}/relationships/author") }
subject(:last_response) { get("/articles/#{article.external_id}/relationships/author") }

let(:article) { articles(:article_with_author) }
let(:policy_scope) { Article.all }
Expand Down Expand Up @@ -87,7 +87,7 @@
}
EOS
end
subject(:last_response) { post("/articles/#{article.id}/relationships/comments", json) }
subject(:last_response) { post("/articles/#{article.external_id}/relationships/comments", json) }
let(:policy_scope) { Article.all }
let(:comments_scope) { Comment.all }

Expand Down Expand Up @@ -133,7 +133,7 @@
}
EOS
end
subject(:last_response) { patch("/articles/#{article.id}/relationships/comments", json) }
subject(:last_response) { patch("/articles/#{article.external_id}/relationships/comments", json) }
let(:policy_scope) { Article.all }
let(:comments_scope) { Comment.all }

Expand Down Expand Up @@ -180,7 +180,7 @@
end

describe 'PATCH /articles/:id/relationships/author' do
subject(:last_response) { patch("/articles/#{article.id}/relationships/author", json) }
subject(:last_response) { patch("/articles/#{article.external_id}/relationships/author", json) }

let(:article) { articles(:article_with_author) }
let!(:old_author) { article.author }
Expand Down Expand Up @@ -271,7 +271,7 @@
}
EOS
end
subject(:last_response) { delete("/articles/#{article.id}/relationships/comments", json) }
subject(:last_response) { delete("/articles/#{article.external_id}/relationships/comments", json) }
let(:policy_scope) { Article.all }
let(:comments_scope) { Comment.all }

Expand Down Expand Up @@ -321,7 +321,7 @@
end

describe 'DELETE /articles/:id/relationships/author' do
subject(:last_response) { delete("/articles/#{article.id}/relationships/author") }
subject(:last_response) { delete("/articles/#{article.external_id}/relationships/author") }

let(:article) { articles(:article_with_author) }
let(:policy_scope) { Article.all }
Expand Down
22 changes: 16 additions & 6 deletions spec/requests/resource_operations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@

it 'returns results limited by policy scope' do
expect(json_data.length).to eq(1)
expect(json_data.first["id"]).to eq(article.id.to_s)
expect(json_data.first["id"]).to eq(article.external_id)
end
end
end

describe 'GET /articles/:id' do
subject(:last_response) { get("/articles/#{article.id}") }
subject(:last_response) { get("/articles/#{article.external_id}") }
let(:policy_scope) { Article.all }

context 'unauthorized for show' do
Expand Down Expand Up @@ -70,7 +70,17 @@
end

describe 'POST /articles' do
subject(:last_response) { post("/articles", '{ "data": { "type": "articles" } }') }
subject(:last_response) { post("/articles", json) }
let(:json) do
<<-EOS.strip_heredoc
{
"data": {
"id": "external_id",
"type": "articles"
}
}
EOS
end

context 'unauthorized for create_resource' do
before { disallow_operation('create_resource', Article, []) }
Expand All @@ -88,14 +98,14 @@
<<-EOS.strip_heredoc
{
"data": {
"id": "#{article.id}",
"id": "#{article.external_id}",
"type": "articles"
}
}
EOS
end

subject(:last_response) { patch("/articles/#{article.id}", json) }
subject(:last_response) { patch("/articles/#{article.external_id}", json) }
let(:policy_scope) { Article.all }

context 'authorized for replace_fields' do
Expand All @@ -120,7 +130,7 @@
end

describe 'DELETE /articles/:id' do
subject(:last_response) { delete("/articles/#{article.id}") }
subject(:last_response) { delete("/articles/#{article.external_id}") }
let(:policy_scope) { Article.all }

context 'unauthorized for remove_resource' do
Expand Down
Loading