简体   繁体   English

渲染JSON包含字段上的Rails Pundit policy_scope

[英]Rails Pundit policy_scope on render json include fields

Continuing my previous question at: Active Model Serializer and Pundit deleting records during a Show CRUD action 在以下位置继续我的上一个问题: Active Model Serializer和Pundit在Show CRUD操作期间删除记录

I have a situation where a User should not be able to view another user's unpublished chapters belonging to a Story an author created. 我遇到的情况是, User不应该查看属于作者创建的Story的其他用户未发布的章节。

Eg If UserA creates a story called Targon and provides 2 published chapters and 2 unpublished chapters, then UserB should only see published chapters for Targon story. 例如,如果UserA创建了一个名为Targon的故事,并提供了2个已发布的章节和2个未发布的章节,则UserB应该只看到Targon故事的已发布章节。

Normally with Pundit policy scoping, it scopes the index CRUD action. 通常,在Pundit策略作用域范围内,它对index CRUD操作的作用范围。

What I need to scope however, are Chapters belonging to a Story during the render json line: 但是,我需要确定的范围是在render json行中属于Story Chapters

render json: story, include: [:user, :chapters], status: :ok

I have tried: 我努力了:

# ---------------------------------------------------------------------------
# ActiveRecord auto-save will kick in and delete all unpublished chapters
# ---------------------------------------------------------------------------
story.chapters = policy_scope(story.chapters)

render json: story, include: [:user, :chapters], status: :ok

According to https://gist.github.com/demisx/9896113 (has_many section) the above code will delete all the unpublished chapters belonging to Targon when I reassign story.chapters : 根据https://gist.github.com/demisx/9896113(has_many部分),以上代码将在我重新分配story.chapters时删除属于Targon所有未发布的章节:

story.chapters = policy_scope(story.chapters) # BAD

I am hoping there is some way I can do something like this : 我希望有某种方法可以执行以下操作

render json: story, include: [:user, policy_scope(:chapters)], status: :ok

At the moment, without scoping the story.chapters any users who fetch for Story with ID 16 (Targon) will get back JSONAPI: 目前,在没有对story.chapters进行范围界定的story.chapters任何获取ID为16 (Targon)的Story的用户都将获得JSONAPI:

{
    "data": {
        "id": "16",
        "type": "stories",
        "attributes": {
            "title": "Mount Targon",
            "summary": "Mount Targon is the mightiest peak in Runeterra, a towering peak of sun-baked rock amid a range of summits unmatched in scale anywhere else in the world. Located far from civilization, Mount Targon is utterly remote and all but impossible to reach save by the most determined seeker. Many legends cling to Mount Targon, and, like any place of myth, it is a beacon to dreamers, madmen and questors of adventure. Some of these brave souls attempt to scale the impossible mountain, perhaps seeking wisdom or enlightenment, perhaps chasing glory or some soul-deep yearning to witness its summit. The ascent is all but impossible, and those hardy few who somehow survive to reach the top almost never speak of what they have seen. Some return with a haunted, empty look in their eyes, others changed beyond all recognition, imbued by an Aspect of unearthly, inhuman power with a destiny few mortals can comprehend.",
            "published": true,
            "published-date": "2017-11-02T10:35:33.184Z",
            "created-at": "2017-11-02T10:35:33.184Z",
            "updated-at": "2017-11-04T07:35:04.083Z",
            "cover": {
                "url": "http://res.cloudinary.com/chewedon/image/upload/v1509780931/c8ubn3tfivxziyxwynsa.png",
                "standard": {
                    "url": "http://res.cloudinary.com/chewedon/image/upload/c_fill,g_north,h_300,w_200/c8ubn3tfivxziyxwynsa.png"
                }
            }
        },
        "relationships": {
            "user": {
                "data": {
                    "id": "1",
                    "type": "users"
                }
            },
            "chapters": {
                "data": [{
                    "id": "26",
                    "type": "chapters"
                }, {
                    "id": "27",
                    "type": "chapters"
                }, {
                    "id": "37",
                    "type": "chapters"
                }, {
                    "id": "38",
                    "type": "chapters"
                }]
            }
        }
    },
    "included": [{
        "id": "1",
        "type": "users",
        "attributes": {
            "username": "Chewedon",
            "photo": {
                "url": "http://res.cloudinary.com/chewedon/image/upload/v1509857442/nx1tqlcdxrhz6r3kjx87.jpg",
                "standard": {
                    "url": "http://res.cloudinary.com/chewedon/image/upload/c_fill,g_north,h_150,w_150/nx1tqlcdxrhz6r3kjx87.jpg"
                }
            }
        },
        "relationships": {
            "stories": {
                "data": [{
                    "id": "1",
                    "type": "stories"
                }, {
                    "id": "2",
                    "type": "stories"
                }, {
                    "id": "3",
                    "type": "stories"
                }, {
                    "id": "4",
                    "type": "stories"
                }, {
                    "id": "5",
                    "type": "stories"
                }, {
                    "id": "6",
                    "type": "stories"
                }, {
                    "id": "8",
                    "type": "stories"
                }, {
                    "id": "9",
                    "type": "stories"
                }, {
                    "id": "10",
                    "type": "stories"
                }, {
                    "id": "11",
                    "type": "stories"
                }, {
                    "id": "12",
                    "type": "stories"
                }, {
                    "id": "13",
                    "type": "stories"
                }, {
                    "id": "14",
                    "type": "stories"
                }, {
                    "id": "15",
                    "type": "stories"
                }, {
                    "id": "16",
                    "type": "stories"
                }]
            }
        }
    }]
}

Here in the relationship section, chapters 37 and 38 are unpublished, leading to a 403 Forbidden on my Ember frontend. 在“关系”部分中,第3738章未发布,导致在我的Ember前端上出现403 Forbidden。

Ideally the server should have scoped out these before returning the records but due to the bug I described above and in my previous Stackoverflow question, I am stuck on how to scope included fields with Pundit. 理想情况下,服务器应该在返回记录之前先对它们进行范围划分,但是由于我上面所述的错误以及我之前的Stackoverflow问题中的问题,我一直在限制如何使用Pundit对包含的字段进行范围划分。

Any ideas? 有任何想法吗?

Thanks to user oowowaee from previous linked question, who suggested overriding the Story serializer's chapters field (which I didn't know you could do that), the code is working now and the records don't get deleted from database. 感谢上一个链接问题中的用户oowowaee,他建议覆盖Story序列化程序的“ chapters字段(我不知道您可以做到这一点),代码现在可以正常工作,并且记录也不会从数据库中删除。

class StorySerializer < ActiveModel::Serializer
  include Pundit

  attributes :id, :title, :summary, :published, :published_date, :created_at, :updated_at, :cover

  belongs_to :user
  has_many :chapters

  # ------------------------------------------------------------------------
  # Note: need to use 'object.chapters' not 'self.chapters` below.
  # ------------------------------------------------------------------------
  def chapters
    policy_scope(object.chapters)
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM