【发布时间】:2018-04-17 14:44:56
【问题描述】:
好的,这里有些东西严重损坏了......
我将 Active Model Serializer 和 Pundit 用于我的 Rails 5 JSONAPI 服务器,将 Ember 用于我的前端应用程序。
我有User 模型和针对用户模型的 Pundit 政策,可防止非作者查看未发布的故事和章节。
目前,我看到一个奇怪的问题是这样的:
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.
这是一些截图:
UserA 创建了 2 个已发布的故事和 2 个未发布的故事
数据库记录显示4个故事属于巨神峰故事
UserA 注销,UserB 登录,查看 Mount Targon 故事
(如您所见,UserB 只看到两个已发布的章节,这是正确的,但是...)
出于某种奇怪的原因,未发布的章节从数据库中删除
查看 Rails 控制台,我在 ChaptersController#show CRUD 操作期间看到 DELETE 查询:
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 显示动作中甚至没有“删除”或“销毁”两个词……那么记录是如何被删除的呢?
# 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
我的章节策略显示方法:
# CHAPTER PUNDIT POLICY
def show?
(@record.published? && @record.story.published?) || (@record.story.user == @user)
end
我的 StoriesController Show 动作如下所示:
# 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。出于某种奇怪的原因,它发生在服务器端 =/
有什么想法吗?
【问题讨论】:
标签: ruby-on-rails ember.js active-model-serializers json-api pundit