Andy Beatson
Andy Beatson

Reputation: 66

Writing a custom resolver for appsync query

I want to add a layer of security to my app (Amplify using appsync) so that only contacts who are part of a specific company can see cases that are a part of that company. My idea is that I query the case table by company to return all the cases, but I need to do a query that checks the contacts company first.

I have the following graphql schema:

type Case @model @auth(rules: [{ allow: public }, { allow: private }]) {
  id: ID! @primaryKey(sortKeyFields: ["company"])
  internal_id: String
  case_number: Int
  created_date: String
  end_date: String
  last_message_date: String
  depot: String
  project: Boolean
  title: String
  project_id: String
  email: String
  product: String
  module: String
  sla: String
  priority: String
  asset_type: String
  truck_reg: String
  failure_reason: String
  software_issue: String
  assigned: String
  solution_id: String
  status: String
  stage: String
  routine_maintenance_case: Boolean
  subcategory: String
  category: String
  description: String
  availability: String
  subsidiary: String
  search_title: String
  search_depot: String
  escalated: Boolean
  company: String! @index(name: "company")
}

type Company @model @auth(rules: [{ allow: public }, { allow: private }]) {
  id: ID
  internal_id: String! @primaryKey
  name: String
  cases: [Case] @hasMany(indexName: "company", fields: ["internal_id"])
  contact: [Contact] @hasMany(indexName: "company", fields: ["internal_id"])
}

type Contact @model @auth(rules: [{ allow: public }, { allow: private }]) {
  id: ID
  internal_id: String! @primaryKey(sortKeyFields: ["company"])
  salutation: String
  first_name: String
  middle_name: String
  last_name: String
  email: String
  phone: String
  mobile_phone: String
  office_phone: String
  home_phone: String
  is_internal: Boolean
  first_login: Boolean
  language: Int
  communication_preference: Int
  contact_role: String
  company: String! @index(name: "company")
}

Im trying to use the autogenerated casesByCompany(company: "") query but include the contact internal_id so that only contacts who are part of the company have access to that case.

for example: casesByCompany(company: "", contact = "") where contact is the contact internal id, then it will run a test that the contact internal_id matches the company passed up.

the auto created resolver is:

## [Start] Set query expression for key **
#if( !$util.isNull($ctx.args.sortDirection) )
  $util.error("sortDirection is not supported for List operations without a Sort key defined.", "InvalidArgumentsError")
#end
#set( $modelQueryExpression = {} )
#if( !$util.isNull($ctx.args.company) )
  #set( $modelQueryExpression.expression = "#company = :company" )
  #set( $modelQueryExpression.expressionNames = {
  "#company": "company"
} )
  #set( $modelQueryExpression.expressionValues = {
  ":company": {
      "S": "$ctx.args.company"
  }
} )
#end
## [End] Set query expression for key **
#set( $limit = $util.defaultIfNull($context.args.limit, 100) )
#set( $QueryRequest = {
  "version": "2018-05-29",
  "operation": "Query",
  "limit": $limit,
  "query": $modelQueryExpression,
  "index": "company"
} )
#if( !$util.isNull($ctx.args.sortDirection)
                      && $ctx.args.sortDirection == "DESC" )
  #set( $QueryRequest.scanIndexForward = false )
#else
  #set( $QueryRequest.scanIndexForward = true )
#end
#if( $context.args.nextToken ) #set( $QueryRequest.nextToken = $context.args.nextToken ) #end
#if( !$util.isNullOrEmpty($ctx.stash.authFilter) )
  #set( $filter = $ctx.stash.authFilter )
  #if( !$util.isNullOrEmpty($ctx.args.filter) )
    #set( $filter = {
  "and":   [$filter, $ctx.args.filter]
} )
  #end
#else
  #if( !$util.isNullOrEmpty($ctx.args.filter) )
    #set( $filter = $ctx.args.filter )
  #end
#end
#if( !$util.isNullOrEmpty($filter) )
  #set( $filterExpression = $util.parseJson($util.transform.toDynamoDBFilterExpression($filter)) )
  #if( $util.isNullOrEmpty($filterExpression) )
    $util.error("Unable to process the filter expression", "Unrecognized Filter")
  #end
  #if( !$util.isNullOrBlank($filterExpression.expression) )
    #if( $filterExpression.expressionValues.size() == 0 )
      $util.qr($filterExpression.remove("expressionValues"))
    #end
    #set( $QueryRequest.filter = $filterExpression )
  #end
#end
$util.toJson($QueryRequest)

what is the best solution to add in the contact id? If it requires a custom query how can i create a resolver that allows me to have that check in place.

The reason I have had to do this is because im using cognito users to allow access to the site, but anyone can take the given token and copy the graphql query in the request sent up and put it into postman and edit the details to pull back other companies information.

Please let me know if any other information is needed.

Thanks

Upvotes: 1

Views: 220

Answers (0)

Related Questions