AWS Amplify / GraphQl - How to limit auth user api calls based on #auth owner field pointing at a many to many relationship? - amazon-web-services

Which Category is your question related to?
GraphQL Api
Amplify CLI Version
10.5.1
What AWS Services are you utilizing?
AWS, Amplify, Cognito User Pools
I am trying to figure out how to limit an authorized user that is signed into to only be able to make queries like accounts they are assigned to. I do not want a auth user to be able to query accounts they are not associated with if they somehow have their account id.
So the modals I am working with are Account and User and they should have a many to many relationship. I am also using the version of amplify that uses the transformer v2 version for the graphql schema. So I cannot use the V1 setup that most documentation out there uses.
Current Schema
type Account #model #auth(rules: [
{allow: groups, groups: ["Admin"], operations: [read, create, update, delete]}
{allow: owner, ownerField: "users", operations: [read]}
]) {
id: ID!
account_name: String
products: AWSJSON
users: [User] #manyToMany(relationName: "AccountUser")
}
type User #model #auth(rules: [
{allow: groups, groups: ["Admin"], operations: [read, create, update, delete]},
{allow: owner, ownerField: "accounts", operations: [read]}
]) {
id: ID!
last_name: String
first_name: String
accounts: [Account] #manyToMany(relationName: "AccountUser")
email: AWSEmail
}
To break down what is going on the #manyToMany relationship creates a join table called AccountUser.
So the approach I was trying to go with was the multi-owner approach by setting the ownerFields. But the API throws errors like "Validation error of type FieldUndefined: Field 'accounts' in type 'AccountUser' is undefined # 'accountUsersByAccountId/items/accounts'"
I am guessing that this is because I set the ownerFields to data that at some point could have no data in it. This error showed up when I called a join table api endpoint called accountUsersByAccountId. Before I added the ownerField auth rule everything worked just fine but any auth user could query any account if they had the information.
Conclusion
I dont think I am on the right track here. I know the issue of limiting a user's ability to query certain data is a common usecase but I cannot find any examples for what I am trying to do.
From the examples I have looked at they would have me do the following. But there is no relationship for accounts and I dont think that is going to go over well if an account is deleted but the ID still exists in the user.
type User #model
#auth(rules: [
# Authorize the update mutation and both queries.
{ allow: owner, ownerField: "accounts", operations: [read] },
# Admin users can access any operation.
{ allow: groups, groups: ["Admin"] }
]) {
id: ID!
last_name: String
first_name: String
accounts: [String]
email: AWSEmail
}
I also cannot do groups cause I know there is a limit to the number of groups cognito allows and isnt sailable friendly.
Am I going about this the wrong way, can anyone let me know how they handled API limitations based on a users relationship to an account.

Related

How to Follow Users for Social App in AWS? Data Modelling Scenario

I am just gathering ideas on how to approach a certain scenario for an application that I am building in AWS Amplify. The platform is a social platform where you can have followers and follow people (just like every other social platform). The scenario is as follow:
You (USER A) sign in to the platform and decide to follow someone else (USER B).
After you click the 'follow user' button USER B data (e.g. userid, ursername, bio) needs to be added to USER A 'FOLLOWING' information that has data on other users that you are following.
USER A (e.g. userid, ursername, bio) data needs to be added to USER A 'FOLLOWER' information that has data of other users that follow this user.
What is the best way to do this? The current data schema that I have is as shown below but I am considering to have 2 tables (one for followers and one for following) and relate them to the user table. Either that or utilise AWS Lambda functions or other better alternatives suggested. Thanks!!!
type AmplifyUser #model #auth(rules: [
{allow: owner},
{allow: private, provider: userPools, operations: [read]}
]) {
userid: ID!
username: String!
firstName: String!
lastName: String!
bio: String
followers: [AWSJSON]
following: [AWSJSON]
}
*Followers and Following fields should both have userid, username and bio info

Can I implement fields as a set (non-duplicated list) in AWS Amplify Datastore?

I'm a beginner at AWS Amplify and GraphQL.
I came here because I couldn't find it no matter how hard I looked.
My GraphQL code is as follows:
type User #model #auth(rules: [{ allow: owner }]) {
id: ID!
assets: [Asset]! #hasMany
}
I don't want 'Asset' model to be duplicated.
So I thought to make 'assets' as a set (non-duplicated list).
But is that possible to implement?

AWS Amplify AppSync GraphQL #Auth directive: How can I forbid to list of elements for public user

I am creating an React App with Amplify backend. So far that is working great but I want to forbid that certain user can list some Elements. Let me give an example graphql definition:
type Customer #model
#auth(rules: [
{allow: public, , operations: [read,create,update]},
{allow: groups, groups: ["admin","partner"] }])
{
id: ID!
firstName: String
lastName: String
email: String
phone: String
}
We have Customers that are not logged in so they are public. They know their id (because it is in the url after they created the Customer Entry) and they should be able to update, read and create their own user. Thats working good.
Unfortunately they can also use the listCustomers query. So they can see all the other entries. Can I forbid this in some way? As I understand the operation "read" means "get" and "list".
The same should be for cognito groups. "admin" should be able to do everything including "list" and "partner" should only be able to "get".
Does anyone has an idea? I have read the docs and googled it but seems like I do not find an answer.
Best regards
To answer my question:
You can add { allow: public, queries: [get, list], mutations: [create,update]} for authorization rules. Unfortunately this is deprecated. I have no idea if there will be sth similar in the futur.
See: https://docs.amplify.aws/cli/graphql-transformer/auth/#definition
type Customer #model #auth(rules: [
{ allow: public, queries: [get], mutations: [create,update]},
{ allow: groups, groups: ["admin"] },
{ allow: groups, groups: ["partner"], queries: [get], mutations: []}])
{
id: ID!
firstName: String
lastName: String
email: String
phone: String
request: [Request] #connection(keyName: "byCustomer", fields: ["id"])
}

aws mock api able to query but unable to delete entries

shown below is the graphql Schema.
#auth(rules: [{ allow: owner,operations: [create, delete ] ,ownerField: "user"}])
{
id: ID!
videoKey: String!
videoThumbnailKey :String!
videoTitle:String!
videoDescription:String!
channelName:String!
videoLikes: Int
videoDislikes: Int
comments: [Comment] #connection(keyName: "byVideo", fields: ["id"])
user: String
}
type Comment #model
#auth(rules: [{ allow: owner,operations: [create,delete] ,ownerField: "user"}])
#key(name: "byVideo", fields: ["videoID", "comment"]) {
id: ID!
videoID: ID!
comment: String!
video: Video #connection(fields: ["videoID"])
user: String
}
type LikedVideos #model
{
id:ID!
video:[Video]#connection
}
this is the query for listing videos
and these are the results
this is the query for getting a video
and these are the results
all of these works fine, but when I try to delete it I get error.
this is the mutation query
and this is the error response i got
Seems like you have not added sort key in dynamo db table and the other items have the same primary key as of first item. I faced similar issue and worked after adding sort key.
This seems to be another bug in AWS Amplify or local DynamoDB.
I am using the same schema - when I add even just a space to schema.grapql, first delete operation works. The delete operations executed after are not working.
Also, it seems like something is throttling query response (I am using amplify mock command):
E.g. I have 7 items in the database and when I am trying to list all of them, I got responses with 1, 2, or even zero items, multiple times - when I would expect, that they will be loaded in 1 request, at the same time.
I am using AWS Amplify
"aws-amplify": "^3.1.1",
"aws-amplify-react-native": "^4.2.5",
Even if you modify schema.graphql, it's still unreliable.

In an AppSync GraphQL transform, can I set an #auth rule AuthStrategy based on a field in the table?

Is there a way to conditionally set more than one AuthStrategy depending on a field in the table?
Let's say I have a blog Post type:
type Post
#model
#auth(rules: [
{ allow: owner, operations: [read, update, delete] },
])
{
id: ID!
owner: String!
visibility: Visibility!
title: String!
body: String!
whitelist: [String!]
}
enum Visibility {
PUBLIC,
PRIVATE,
PROTECTED,
SECRET
}
I want the creator to be able to set whether the Post is:
Public: anyone can see it, logged in or not.
Private: any logged-in user can see it.
Protected: this array of users can see it.
Secret: only the creator can see it.
I know how to hardcode each of these. But programmatically...
Is this even possible, or are AppSync transforms just too basic, and I need to use a custom resolver?
It turns out, this does require a custom resolver—or custom, nested resolver—which is pretty easy.
The official docs on this authorization scenario: https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html.
And a great Hacker Noon article on this authorization scenario: https://hackernoon.com/graphql-authorization-with-multiple-data-sources-using-aws-appsync-dfae2e350bf2.