这是使用标准 graphql-ruby 设置时发生的数据泄漏的示例。
使用下面的 graphql 嵌套请求,响应返回嵌套在公司 1 下的数据,该数据属于公司 2。我希望响应仅限于属于它嵌套的公司的会计日志。
那样的话,就是在泄露信息。
问题是我们如何修补泄漏,以便响应中返回的唯一数据及其嵌套对象是属于公司的数据(根对象)。
这个查询:
query {
company(id: "1") {
id
name
activityLog {
id
activityAt
accountant {
id
name
}
companyId
}
accountants {
id
name
activityLog {
id
activityAt
companyId
}
}
}
}
返回此响应:
{
"data": {
"company": {
"id": "1",
"name": "AwsomeCo",
"activityLog": [
{
"id": "1",
"activityAt": "2019-10-12 16:40:13 UTC",
"accountant": {
"id": "100",
"name": "Mr Smith",
},
"companyId": "1"
}
],
"accountants": [
{
"id": "100",
"name": "Mr Smith"
"activityLog": [
{
"id": "1",
"activityAt": "2019-10-12 16:40:13 UTC",
"companyId": "1"
},
{
"id": "2",
"activityAt": "2019-10-11 16:40:13 UTC",
"companyId": "2" // OTHER COMPANY, NEED TO PRESERVE PARENT SCOPE
},
],
}
}
}
}
}
在公司 1 的嵌套元素中泄露公司 2 的事务日志数据。
同样,问题是:我们如何保持范围,仅在所显示的公司的上下文中显示数据?
重现代码:
GraphQL 类型(使用 graphql-ruby gem)
#query_type.rb
module Types
class QueryType < Types::BaseObject
# Add root-level fields here.
# They will be entry points for queries on your schema.
field :company_leak, Types::ExampleLeak::CompanyType, null: false do
argument :id, ID, required: true
end
field :companies_leak, [ Types::ExampleLeak::CompanyType ], null: false
def company_leak(id: )
Company.find(id)
end
def companies_leak
Company.all
end
end
end
module Types
module ExampleLeak
class CompanyType < BaseObject
field :id, ID, null: false
field :name, String, null: false
field :transaction_logs, [Types::ExampleLeak::TransactionLogType], null: true
field :accountants, [Types::ExampleLeak::AccountantType], null: true
end
end
end
module Types
module ExampleLeak
class AccountantType < BaseObject
field :id, ID, null: false
field :name, String, null: false
field :transaction_logs, [Types::ExampleLeak::TransactionLogType], null: true
field :companies, [Types::ExampleLeak::CompanyType], null: true
end
end
end
module Types
module ExampleLeak
class TransactionLogType < BaseObject
field :id, ID, null: false
field :activity_at, String, null: false
field :company_id, ID, null: false
field :accountant, Types::ExampleLeak::AccountantType, null: false
end
end
end
楷模
class Company < ApplicationRecord
has_and_belongs_to_many :accountants
has_many :transaction_logs
end
class Accountant < ApplicationRecord
has_and_belongs_to_many :companies
has_many :transaction_logs
end
class TransactionLog < ApplicationRecord
belongs_to :company
belongs_to :accountant
end
种子.rb
awesomeco = Company.create!(name: 'AwesomeCo')
boringco = Company.create!(name: 'BoringCo')
mr_smith = Accountant.create!(name: "Mr. Smith")
awesomeco.accountants << mr_smith
boringco.accountants << mr_smith
mr_smith.transaction_logs.create!(company: awesomeco, activity_at: 1.day.ago)
mr_smith.transaction_logs.create!(company: boringco, activity_at: 2.days.ago)
包含完整代码的公共回购,旨在作为教育资源: