-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Before opening, please confirm:
- I have searched for duplicate or closed issues.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
- I have removed any sensitive information from my code snippets and submission.
App Id
i-use-amplify-studio-i-dont-know-which-of-all-arn-to-put-here-sorry
Region
us-east-1
Environment name
Amplify
Figma File Version (if applicable)
No response
Amplify CLI Version
No response
If applicable, what version of Node.js are you using?
No response
What operating system are you using?
No response
Browser type?
No response
Describe the bug
Hi !
How can I make "DataStore" framework insert the user.attribute.sub or user.username into the "owner" field of a GraphQL type?
This guys did that: https://youtu.be/D8gSc7wDRic?si=tmF1f7j-hr5RkJx_
I see that they only used "datastore.save" command, and as you can see, they didnt filled "owner" inside the app. Also, they make the React app compare the user.attributes.sub with the post.owner field and the app automatically recognized that they were the same.
I used that datasore.save command but the "owner" field is "null". I even tryed to set it manually, but it simply doesnt recieve the ID.
My code actually creates the post, but the "owner" field is empty. My process was: I created the Schema in my Code Editor, then I push it to Amplify Studio. It created the types in the "data" section. After that, I enabled the "Enable owner authorization" in Amplify Studio in the "Post" type.
The "Post" type has this Authorization Rules: Authenticated and unauthenticated scopes: Anyone authenticated with API Key can Create, Read, Update, and Delete Product
The "Post" type has: Owner-based scopes:
Enable owner authorization (yes, enabled) Owner-based authorization allows you to tie a data record to a user. Owners can read, create, update, and delete the record.
Allow the owner to perform these operations on their own records: Create, Read, Update, Delete
After that, the "Post" type got an additional field called "owner". Once I pulled the changes to my code editor, there schema.graphql file didnt got the "owner" field, but you can see it in AWS AppSync.
It would be wonderfull if you could help me by telling me where can I add a "console.log" to check or see what is allowing to enter the new "post" but is preventing to put the "user ID" into the "owner" field. Or you can tell me if there is a Hub function, or DataStore.suscribe or similar to identify that. It can be an option if you tell me if the error can be identified with CluodWatch or any other service that reads every answer received and answered by the server.
In the "schema" section of the AWS AppSync console, I clicked on "pipeline" of the "owner" property of the "Product" type. There is this code:
$util.qr($ctx.stash.put("typeName", "Post"))
$util.qr($ctx.stash.put("fieldName", "owner"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "NONE"))
$util.qr($ctx.stash.metadata.put("apiId", "somecode"))
$util.qr($ctx.stash.put("connectionAttributes", {}))
"user" is generating a big JSON object that has the next properties: Session, attributes, authenticationFlowType, client, keyPrefix, pool, preferredMFA, signInUserSession, storage, userDataKey and username", it doesn't have an "isAuthenticated" property.
It has this object (I replaced every sensitive code with "...". If there is no three points "..." its because there wasnt any code or numer)
Session: null
attributes: {sub: '…', email_verified: true, name: '….', phone_number_verified: false, phone_number: '…', …}
authenticationFlowType: "USER_SRP_AUTH"
client: e {endpoint: 'https://cognito-idp.us-....amazonaws.com/', fetchOptions: {…}}
keyPrefix: "CognitoIdentityServiceProvider…."
pool: e {userPoolId: 'us-east-1_...', clientId: '….', client: e, advancedSecurityDataCollectionFlag: true, storage: Storage, …}
preferredMFA: "NOMFA"
signInUserSession: e {idToken: r, refreshToken: e, accessToken: r, clockDrift: 0}accessToken: r {jwtToken: '…', payload: {…}}clockDrift: 0idToken: r {jwtToken: '…', payload: {…}}refreshToken: e {token: '…'}[[Prototype]]: Object
storage: Storage {CognitoIdentityServiceProvider…..LastAuthUser: '…', CognitoIdentityServiceProvider…..idToken: '…', CognitoIdentityServiceProvider…..userData: '{"UserAttributes":[{"Name":"sub","Value":"……Username":"…"}', amplify-signin-with-hostedUI: 'false', ab.storage.messagingSessionStart….: '{"v":…}', …}
userDataKey: "CognitoIdentityServiceProvider…..userData"
username: "…""
That was a sumary of the "user" JSON object, in which I replaced every code with "..."
Would this make more clear what is blocking the fulfillment of the "owner" property? Take into account that the item is succesfully being created, with the version and time filled automatically.
{
"channel": "datastore",
"payload": {
"event": "nonApplicableDataReceived",
"data": {
"errors": [
{
"path": [
"syncUsers",
"items",
0,
"_version"
],
"locations": null,
"message": "Cannot return null for non-nullable type: 'Int' within parent 'User' (/syncUsers/items[0]/_version)"
},
{
"path": [
"syncUsers",
"items",
0,
"_lastChangedAt"
],
"locations": null,
"message": "Cannot return null for non-nullable type: 'AWSTimestamp' within parent 'User' (/syncUsers/items[0]/_lastChangedAt)"
}
],
"modelName": "User"
}
},
"source": "",
"patternInfo": []
}
This is the Schema:
type Post @model @auth(rules: [{allow: public}, {allow: owner}]) {
id: ID!
content: String!
blogID: ID @index(name: "byBlog")
blog: Blog @belongsTo(fields: ["blogID"])
owner: String # This one was added lately, and it allows me to insert the "owner" value "manually" (I mean, with the Javascript form in the app), but it keeps being "null" if don´t set it manually.
}
type Blog @model @auth(rules: [{allow: public}, {allow: owner}]) {
id: ID!
blog: String!
posts: [Post] @hasMany(indexName: "byBlog", fields: ["id"])
}
This is my package.json:
{
"name": "mega-blog",
"version": "0.1.0",
"private": true,
"dependencies": {
"@aws-amplify/interactions": "^5.2.3",
"@aws-amplify/ui-react": "^5.0.1",
"@aws-amplify/ui-react-v1": "npm:@aws-amplify/[email protected]",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"aws-amplify": "^5.3.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.9.0",
"react-router-dom": "^6.13.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
This is the code of the two files, "index.js" and "App.js":
index.js
import { Amplify, API, graphqlOperation, Interactions, Auth, AuthModeStrategyType } from 'aws-amplify';
import { withAuthenticator } from '@aws-amplify/ui-react';
import awsconfig from './aws-exports';
Amplify.configure({
...awsconfig,
DataStore: {
authModeStrategyType: AuthModeStrategyType.MULTI_AUTH
}
});
App.js
import { Amplify, API, graphqlOperation, Auth } from 'aws-amplify';
import { withAuthenticator } from '@aws-amplify/ui-react';
import { DataStore } from '@aws-amplify/datastore';
import { Post, Blog } from './models';
const App = ({ signOut, user }) => {
const [post, setPost] = useState('');
const [blogID, setBlogID] = useState('');
// AWS Video
const [currentUser, setCurrentUser] = useState();
const handleSubmit = async (e) => {
e.preventDefault();
async function checkLoginState() {
try {
const currentUser = await Auth.currentAuthenticatedUser();
if (currentUser) {
console.log('Usuario autenticado con Auth:', currentUser);
setCurrentUser(currentUser);
}
} catch(err) {
console.log('No se pudo atenticar el usuario:', err);
}
};
checkLoginState(); // It succesfully brings the user JSON object from Cognito
// Create a new post
const post = new Post({
content,
blogID,
});
// Save the post to the DataStore
await DataStore.save(product);
// Reset the form inputs
setPost('');
setBlogID('');
// Display a success message
alert('Posted successfully');
};
..
return..
<div className="add-post-form">
<h2>Agregar Post</h2>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="post-post">Post</label>
<TextField
id="post-post"
style={styles.input}
value={post}
onChange={(e) => setPost(e.target.value)}
placeholder="What do you want to share..."
required
/>
</div>
<button type="submit">Add Post</button>
</form>
</div>
...
export default withAuthenticator(App);
Expected behavior
The "owner" field of the GraphQL type "Post" should be filled.
Reproduction steps
- I activate the form
- The form activates the function "handleSubmit"
- The function has been tested in two configurations: a) without the "owner" field specified, and b) specifiyng the "owner" field. This is in the variable "post" that is inside the "handleSubmit" function.
- The system actually fill the GraphQL Type, but the "owner" field still "null". I checked that in AppSync.
Project Identifier
No response
Additional information
I created the app with the amplify command to create ReactJS apps.
I am using Cloud9
The app is hosted in Amplify
I am using GraphQL shcema
The authetication is with Cognito, and it has activated the "users" section inside the Amplify App.
Actually I dont know which arn do you need from all of that. Sorry for the answer in the arn section.