Cannot delete data from datastore in aws-amplify - reactjs

I am working with AWS amplify for the first time by following the docs. Everything is working except deletion of the data. Whenever I try to delete data from any of my table it gives the error
DOMException: Failed to execute 'index' on 'IDBObjectStore': The specified index was not found.
at Proxy. (http://localhost:3000/static/js/bundle.js:34280:22)
at IndexedDBAdapter. (http://localhost:3000/static/js/bundle.js:25458:82)
at step (http://localhost:3000/static/js/bundle.js:23678:17)
at Object.next (http://localhost:3000/static/js/bundle.js:23609:14)
at fulfilled (http://localhost:3000/static/js/bundle.js:23563:24)
I have tried using all the ways mentioned in the amplify datastore docs, but I always get this error. Following is my graphql schema
type Profile #model #auth(rules: [{allow: groups, groups: ["SME"], operations: [read]}, {allow: owner}]) {
email: String!
name: String
birthDate: String
photo: String
answers: [Answer!] #hasMany
}
type Questionnaire #model #auth(rules: [{allow: private, operations: [read]}, {allow: groups, groups: ["SME"], operations: [create, read, update, delete]}]) {
detail: String!
fields: [Field!] #hasMany
next: Questionnaire #hasOne
previous: Questionnaire #hasOne
}
type Field #model #auth(rules: [{allow: private, operations: [read]}, {allow: groups, groups: ["SME"], operations: [create, read, update]}]) {
question: Questionnaire! #belongsTo
label: String!
options: [String!]!
units: [Units]
answers: [Answer!] #hasMany
}
type Answer #model #auth(rules: [{allow: groups, groups: ["SME"], operations: [read]}, {allow: owner, operations: [create, read, update]}]) {
field: Field! #belongsTo
answers: [String!]!
unit: Units
}
enum Units {
cm
in
ft
kg
lb
sec
min
hrs
days
weeks
months
}
I have set cognito userpool as default authorization type and conflict resolution to "merge".

Related

React Amplify Appsync One-To-Many Update Mutation

I'm currently working on a react project that uses a one to many relationship for a schema model.
My schema is defined as below for the children field, I want it to be a recursive model that is the same as Response.
type Response #model #auth(rules: [{ allow: owner }]) {
id: ID!
problem: String!
model: String!
basic: String
groupify: String
cognify: String
technify: AWSJSON
temperature: Float!
response: String!
bookmarked: Boolean!
preference: String!
children: [Response] #hasMany(fields: ["id"])
}
I want to update a response with the children and create a new response without any children initially but I'm not entirely sure how to do that.
I'm following documentation via this https://docs.amplify.aws/lib/graphqlapi/mutate-data/q/platform/js/ but I can't find an example for my purpose.

Why is amplify saving username incorrectly?

I have a function to create a vehicle in my amplify project:
const createNewVehicle = async () => {
const { year, make, model, vinNumber } = searchedVehicleInfo || {};
try {
await API.graphql({
query: createVehicle,
variables: { input: { year, make, model, vinNumber } },
authMode: 'AMAZON_COGNITO_USER_POOLS',
});
} catch (err) {
console.log(err);
return null;
}
};
This function creates a vehicle in my dynamoDB table utilizing the API module exposed by amplify. The authMode property saves the Cognito user's username in the API request as well. The vehicle's graphql model looks like this:
type Vehicle
#model
#auth(
rules: [
{
allow: owner
ownerField: "username"
operations: [create, read, update, delete]
}
{ allow: public, operations: [read] }
]
) {
id: ID!
year: Int!
make: String!
model: String!
vinNumber: String!
image: String
username: String
#index(name: "vehiclesByUsername", queryField: "vehiclesByUsername")
receipts: [Receipt] #hasMany(indexName: "byVehicle", fields: ["id"])
}
A team member created his own AWS account and set up his own environment to be used in amplify. This team member created an IAM user and applied the AdminAccess-Amplify role to his user. When he uses this function, the vehicle is created, but it saves the username in a weird way. If his username is test12 it will save the vehicle with a username like this 6e0b3347-5dae-4106-aed6-8ec5c87fde52::test12. So when I try to grab vehicles by username, none come up because his username is test12 and not 6e0b3347-5dae-4106-aed6-8ec5c87fde52::test12.
How can I get it to save just the username and not all the extra information?

"No current user" when making unauth Appsync API call for public DB tables

There really isn't enough documentation on this either in the AWS docs or in the Github, so hopefully someone here has tackled a similar issue.
I have a react app with backend api hosted on AWS, using appsync, dynamoDB, and cognito-user-pools. My IAM policies are set up to allow unauth users read-only permission to some public tables. I tried the public api key but that didn't do anything. I'm trying to get the IAM unauth role permissions set up but even when I experimentally added literally every service and every action to the unauth role, I still get "no current user" when attempting to make the API call without logging in.
Use case is for public author pages, where information about an author along with their currently available books is listed. Users should not have to sign in to see this page, an author should be able to drop a link to the page to anyone, whether they have a login for the app or not.
This is my graphql schema for the relevant types, it gets no errors:
type PublicBook #model #auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
#key(name:"byPublicWorld", fields: ["publicWorldId", "indexOrder"])
#key(name:"byPublicSeries", fields: ["publicSeriesId", "indexOrder"]){
id: ID!
publicWorldId: ID
publicSeriesId: ID
indexOrder: Int!
cover: FileObject #connection
description: String
amazon: String
ibooks: String
smashwords: String
kobo: String
goodreads: String
audible: String
barnesnoble: String
sample: String
}
type PublicSeries #model #auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
#key(name:"byPublicWorld", fields: ["publicWorldId", "indexOrder"]){
id: ID!
publicWorldId: ID!
indexOrder: Int!
logo: FileObject #connection
description: String
genre: String
books: [PublicBook]#connection(keyName:"byPublicSeries", fields: ["id"])
}
type PublicWorld #model #auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
#key(name:"byAuthorPage", fields: ["authorPageId", "indexOrder"]){
id: ID!
authorPageId: ID!
logo: FileObject #connection
description: String
genre: String
indexOrder: Int!
series: [PublicSeries]#connection(keyName:"byPublicWorld", fields: ["id"])
books: [PublicBook]#connection(keyName:"byPublicWorld", fields: ["id"])
}
type AuthorPage #model #auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
#key(name:"byPenName", fields: ["penId"])
#key(name:"byPenDisplayName", fields: ["penDisplayName"], queryField: "authorPageByPen"){
id: ID!
authorName: String
penDisplayName: String
penId: ID!
bio: String
photo: FileObject #connection
logo: FileObject #connection
penFBProfile: String
penFBGroup: String
penFBPage: String
penTwitter: String
penInstagram: String
penAmazon: String
penWebsite: String
penNewsletter: String
penGoodreads: String
penPatreon: String
posts: [AuthorPost]#connection(keyName:"byAuthorPage", fields: ["id"])
worlds: [PublicWorld]#connection(keyName:"byAuthorPage", fields: ["id"])
}
type AuthorPost #model #auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
#key(name:"byAuthorPage", fields: ["authorPageId", "timeCreated"]){
id: ID!
authorPageId: ID!
timeCreated: AWSTimestamp!
content: String!
title: String!
subtitle: String
type: PostType!
}
Each of these types is set to owner/cognito permissions for creating, updating, and deleting, and then there is a public auth using iam to read. Seems straight forward enough.
The main type here is Author page, and I have the query set up to pull all the connected relevant cascading information. When logged in, this works fine and shows an author page with all the bits and bobs:
export const authorPageByPen = /* GraphQL */ `
query AuthorPageByPen(
$penDisplayName: String
$sortDirection: ModelSortDirection
$filter: ModelAuthorPageFilterInput
$limit: Int
$nextToken: String
) {
authorPageByPen(
penDisplayName: $penDisplayName
sortDirection: $sortDirection
filter: $filter
limit: $limit
nextToken: $nextToken
) {
items {
id
authorName
penDisplayName
penId
bio
photo {
location
}
logo {
location
}
penFBProfile
penFBGroup
penFBPage
penTwitter
penInstagram
penAmazon
penWebsite
penNewsletter
penGoodreads
penPatreon
posts {
nextToken
startedAt
}
worlds {
nextToken
startedAt
}
_version
_deleted
_lastChangedAt
createdAt
updatedAt
owner
}
nextToken
startedAt
}
}
`;
On the page itself (although in production this just happens at app.js and persists throughout the app), I'm pulling current credentials and logging them to make sure that some kind of IAM identity is being created, and it appears to be:
accessKeyId: "BUNCHANUMBERSKEY"
authenticated: false
expiration: Thu Mar 04 2021 13:18:04 GMT-0700 (Mountain Standard Time) {}
identityId: "us-west-2:48cd766c-4854-4cc6-811a-f82127670041"
secretAccessKey: "SecretKeyBunchanumbers"
sessionToken:"xxxxxbunchanumbers"
That identityId on line 4 is present in my identity pool as an unauth identity, so it is getting back to the pool, which seems to be what's supposed to happen.
So, this identity pool has two roles associated with it, which is standard: auth and unauth, and my Unauthenticated Identities Setting has the box for Enable Access to Unauthenticated Identities checked.
In my unauth role, I've got the following as the inline policy json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppsyncApiId/types/Mutation/fields/authorPageByPen"
]
}
]
}
I wasn't sure if this needed to be mutation, or query, or what, so I've tried them all. I tried them in combination with 'fields' and with 'index', I've tried writing the JSON, and adding the policies from the inline editor, which gives me the following which also does not work:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "appsync:GraphQL",
"Resource": [
"arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppSyncAPIId/types/AuthorPage/fields/authorPageByPen",
"arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppSyncAPIID"
]
}
]
}
What bit am I missing here? I could understand getting some error about not being allowed to access a resource, but the only error that logs is No Current User, and that happens immediately after the log showing the user.
Update:
Running the query from the Appsync console works fine with IAM and no logged in user. In the page itself, I'm using the following function to call the author page (I'm using routes):
const pullAuthorPage = async () => {
try{
const authorPageData = await API.graphql(graphqlOperation(authorPageByPen, { penDisplayName: props.match.params.id.toLowerCase() }))
console.log(JSON.stringify(authorPageData, null, 2));
setState({...authorPageData.data.authorPageByPen.items[0]})
} catch (error) {
console.log(error);
}
}
What I thought would happen with this is that if there is no authenticated user logged in, this will run using the unauth user credentials. Is that not the case? And if so, how should I change it?

How to enable public query appsync amplify

I am using AWS Amplify with Appsync. I want to add a public query listproducts and it is giving me the hardest time. Based on my understanding, I know that public access needs to be given using apiKey or iam. The trouble is that my mutation enroll lambda function internally makes a create mutation and it is using iam permissions to create those records. I have enabled allowUnauthenticatedIdentities=true but I keep getting access denied for the listproducts query when using iam permissions. I need to make sure that if I go with the iam method, that I have a way to distinguish between the public iam and the private iam that is doing the administrative work in my enroll call and I don't see a way to dictate whether I'd want to use an authenticated vs unauthenticated iam role.
type Product #aws_iam {
id: ID!
}
type UserCourse
#model
#auth(
rules: [
{ allow: groups, groups: ["Admin"] }
{ allow: owner, operations: [read] }
{ allow: private, provider: iam, operations: [create, read] }
]
) {
id: ID!
courseId: String
invoice: String
}
type Query {
listproducts: [Product]
#function(name: "listproducts-${env}")
#auth(rules: [{ allow: public, provider: iam }])
}
type Mutation {
enroll(courseId: String, priceId: String, source: String): UserCourse
#function(name: "coursesenroll-${env}")
}
What am I missing here? I am connecting using Gatsby and AWSAppSyncClient. Is there some trivial way of doing this that I'm just missing? My ideal world would be that I could run an unauthenticated query with cognito pools and it would return so I didn't have to deal with instantiating different appsyncclient's based on whether I'm logged in or not. I tried manually adding permissions to the unauth role and I'm not sure if that's the right approach but I'd be happy to go this route too if I can't do unauth out of the box with amplify.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:eu-central-1:SOME_LONG_STRING:apis/SOME_LONG_STRING/types/Query/fields/listproducts"
]
}
]
}

Doctrine/Symfony losing M:N relationships on save

I have what I assume is a configuration problem with my Doctrine schema.yml, but I can't see to strike the right answer here.
I have two tables, BetaMeeting and ProjectTester, that form a many-to-many relationship through BetaMeetingAttendee. Everything works fine, and I can edit a beta meeting for example to include several project testers, and the relationships are all saved correctly. However, when I edit a project tester that already has existing relationships with a beta meeting(s), upon save the M:N relationships are lost. Using Symfony 1.4.13 and the admin generator, and Doctrine 1.2, and the edit page for a project tester makes no mention of the many-to-many relationships, no hidden fields, etc. Could this be the reason, the data's not there so Doctrine removes it? I didn't think it would be necessary to include it.
My schema.yml is as follows, with irrelevant details removed.
BetaMeeting:
connection: doctrine
tableName: BetaMeeting
columns:
id: { type: integer(4), primary: true, autoincrement: true }
project_id: { type: integer(4) }
date: { type: date }
relations:
Project:
local: project_id
foreign: id
foreignAlias: BetaMeetings
ProjectTester:
class: ProjectTester
refClass: BetaMeetingAttendee
foreignAlias: BetaMeetings
BetaMeetingAttendee:
connection: doctrine
tableName: BetaMeetingAttendee
columns:
beta_meeting_id: { type: integer(4), primary: true, autoincrement: false }
project_tester_id: { type: integer(4), primary: true, autoincrement: false }
relations:
BetaMeeting:
foreignAlias: BetaMeetingAttendees
ProjectTester:
foreignAlias: BetaMeetingAttendees
ProjectTester:
connection: doctrine
tableName: ProjectTester
columns:
id: { type: integer(4), primary: true, autoincrement: true }
tester_id: { type: integer(4) }
project_id: { type: integer(4) }
relations:
Tester:
local: tester_id
foreign: id
foreignAlias: Projects
Project:
local: project_id
foreign: id
foreignAlias: ProjectTesters
Any clue as to why the relationships get cleared out after an edit which is concerned only with the immediate attributes of the ProjectTester object?
If you have a field defined in the Form but you excluded it from the generator.yml it's like submitting an empty field and therefore it clears the relations.
You have to unset that field in the Form.class so the field retains the current values.
public function configure()
{
unset($this['beta_meeting_list']); // or the correct value
}

Resources