问题描述
好的,这里的东西严重破了...
Okay, something is seriously broken here...
我将Active Model Serializer和Pundit用于Rails 5 JSONAPI服务器,将Ember用于前端应用程序.
I am using Active Model Serializer and Pundit for my Rails 5 JSONAPI server and Ember for my frontend application.
我有 User
模型和User模型的Pundit策略,可以防止非作者查看未发表的故事和章节.
I have User
model and Pundit policy for User model which prevent non-authors from viewing unpublished stories and chapters.
此刻,我看到一个奇怪的问题,像这样:
At the moment, I am seeing a weird problem which goes like this:
1. UserA creates StoryA, and two published chapters Chapter1 and Chapter2
2. UserA then creates two unpublished chapters Chapter3 and Chapter4
3. UserA logouts
4. UserB logins
5. UserB views the same story created by UserA
6. Server policy kicks in and scope the results to only published chapters since UserB isn't the author.
7. * An SQL DELETE query is sent to delete the two unpublished stories for some odd reason.
以下是一些屏幕截图:
(如您所见,UserB只看到两个正确的发布章节,但是...)
(As you can see, UserB only sees the two published chapters which is correct but...)
在Rails控制台上,我在 ChaptersController#show
CRUD操作期间看到了DELETE查询:
Looking at the Rails console, I see the DELETE query during a ChaptersController#show
CRUD action:
Started GET "/stories/16" for 127.0.0.1 at 2017-11-05 17:02:53 +0800
Processing by StoriesController#show as JSON
Parameters: {"id"=>"16"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Story Load (0.1ms) SELECT "stories".* FROM "stories" WHERE "stories"."id" = ? LIMIT ? [["id", 16], ["LIMIT", 1]]
Chapter Load (0.3ms) SELECT "chapters".* FROM "chapters" INNER JOIN "stories" ON "stories"."id" = "chapters"."story_id" INNER JOIN "users" ON "users"."id" = "stories"."user_id" WHERE "chapters"."story_id" = ? AND ((stories.published = 't' AND chapters.published = 't') OR stories.user_id = 2) [["story_id", 16]]
Chapter Load (0.1ms) SELECT "chapters".* FROM "chapters" WHERE "chapters"."story_id" = ? [["story_id", 16]]
(0.1ms) begin transaction
Started GET "/chapters/26" for 127.0.0.1 at 2017-11-05 17:02:53 +0800
SQL (0.3ms) DELETE FROM "chapters" WHERE "chapters"."id" = ? [["id", 32]]
Started GET "/chapters/27" for 127.0.0.1 at 2017-11-05 17:02:53 +0800
Processing by ChaptersController#show as JSON
SQL (0.1ms) DELETE FROM "chapters" WHERE "chapters"."id" = ? [["id", 33]]
Processing by ChaptersController#show as JSON
Parameters: {"id"=>"26"}
(2.1ms) commit transaction
Parameters: {"id"=>"27"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
[active_model_serializers] User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Chapter Load (0.1ms) SELECT "chapters".* FROM "chapters" WHERE "chapters"."id" = ? LIMIT ? [["id", 26], ["LIMIT", 1]]
[active_model_serializers] Story Load (0.4ms) SELECT "stories".* FROM "stories" WHERE "stories"."user_id" = ? [["user_id", 1]]
Chapter Load (0.2ms) SELECT "chapters".* FROM "chapters" WHERE "chapters"."id" = ? LIMIT ? [["id", 27], ["LIMIT", 1]]
Started GET "/chapters/32" for 127.0.0.1 at 2017-11-05 17:02:53 +0800
Started GET "/chapters/33" for 127.0.0.1 at 2017-11-05 17:02:53 +0800
Story Load (0.2ms) SELECT "stories".* FROM "stories" WHERE "stories"."id" = ? LIMIT ? [["id", 16], ["LIMIT", 1]]
[active_model_serializers] Rendered StorySerializer with ActiveModelSerializers::Adapter::JsonApi (22.64ms)
Story Load (0.1ms) SELECT "stories".* FROM "stories" WHERE "stories"."id" = ? LIMIT ? [["id", 16], ["LIMIT", 1]]
Processing by ChaptersController#show as JSON
Processing by ChaptersController#show as JSON
[active_model_serializers] Rendered ChapterSerializer with ActiveModelSerializers::Adapter::JsonApi (0.82ms)
Completed 200 OK in 43ms (Views: 27.1ms | ActiveRecord: 3.9ms)
我的ChaptersController show动作中甚至没有单词"delete"或"destroy" ...那么如何删除记录?
My ChaptersController show action does not even have the word "delete" or "destroy" in it...so how does the record get deleted?
# CHAPTERS CONTROLLER
def show
chapter = Chapter.find_by(id: params[:id])
if chapter.present?
authorize chapter
render json: chapter, status: :ok
else
skip_authorization
render json: { error: "Chapter not found" }, status: :not_found
end
end
我的章节政策显示方法:
My Chapter Policy show method:
# CHAPTER PUNDIT POLICY
def show?
(@record.published? && @record.story.published?) || (@record.story.user == @user)
end
我的StoriesController Show动作如下:
My StoriesController Show action looks like:
# STORIES CONTROLLER
def show
story = Story.find_by(id: params[:id])
if story.present?
authorize story
story.chapters = policy_scope(story.chapters)
render json: story, include: [:user, :chapters], status: :ok
else
skip_authorization
render json: { errors: "Story not found" }, status: :not_found
end
end
我以为可能是Ember在幕后进行了一些有趣的额外查询,但是我使用Postman Mac应用程序测试了故事的观看过程,而且确实,未发布的章节被删除了,而根本没有经过Ember.发生在服务器端的原因很奇怪=/
I thought it might be Ember doing some funny extra query behind the scenes but I use Postman Mac application to test viewing the story and sure enough, the unpublished chapters are deleted without going through Ember at all. It's happening server side for some odd reason =/
有什么想法吗?
推荐答案
在我看来,这实际上是在StoriesController#show中完成的.您应该再次尝试仅测试此方法(在RSpec或其他方式中),还可以单步执行代码以查明删除发生的确切位置.我的猜测是:
It looks to me like this is actually being done in StoriesController#show. You should try again testing only this method (in RSpec or something), and you can also step through the code to pinpoint exactly where the delete is occurring. My guess is:
story.chapters = policy_scope(story.chapters)
您正在此处更改故事章节.想必您想做类似的事情
You're changing the story chapters here. Presumably you want to do something like
@displayed_chapters = policy_scope(story.chapters)
这篇关于Active Model Serializer和Pundit在Show CRUD操作期间删除记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!