Is something like this possible? How is this supposed to be designed for this use case? Do I have to add a lambda function that adds the user (owner) to the post when it is created?
Can anyone help me to accomplish that .. Thanks!
This is Post schema:
type Post
#model
#key(name: "byClub", fields: ["clubId"])
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
content: String!
upVotes: Int!
downVotes: Int!
image: String
clubId: ID!
comments: [Comment] #connection(keyName: "byPost", fields: ["id"])
}
And when I fetch the post, this is what I got:
{
"id": "xxxxxxx",
"content": "xxxxx!",
"upVotes": 0,
"downVotes": 0,
"image": null,
"clubId": "xxxxxx",
"comments": {
"nextToken": null
},
"createdAt": "2021-12-05T10:46:59.797Z",
"updatedAt": "2021-12-05T10:46:59.797Z",
"owner": "moneebalalfi#gmail.com"
}
I want something like this:
{
"id": "xxxxx",
"content": "xxxxxxx",
"upVotes": 0,
"downVotes": 0,
"image": null,
"clubId": "xxxxxxxx",
"comments": {
"nextToken": null
},
"createdAt": "2021-12-05T10:46:59.797Z",
"updatedAt": "2021-12-05T10:46:59.797Z",
"owner": {
name: "xxxxx",
email: "xxxx#gmail.com",
image: "xxxxxx",
// and so on ...
}
}
owner field is only used for checking if the requested user is the owner of the data.
Owner authorization specifies whether a user can access or operate against an object. To do so, each object will get an ownerField field (by default owner will be added to the object if not specified) that stores ownership information and is verified in various ways during resolver execution.
from Amplify Docs
To be able to make a connection with the user you need to create another GraphQL Type.
type User
#model
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
email: String!
image: String
}
type Post
#model
#key(name: "byClub", fields: ["clubId"])
#auth(
rules: [
{ allow: owner, operations: [create, update, delete, read] }
{ allow: private, operations: [read] }
]
) {
id: ID!
content: String!
upVotes: Int!
downVotes: Int!
image: String
clubId: ID!
owner: ID
user: User #connection(fields: ["owner"])
comments: [Comment] #connection(keyName: "byPost", fields: ["id"])
}
You might need to configure amplify codegen to increase the max-depth, if it's not showing.
$ amplify configure codegen
$ amplify codegen
Related
Running into a problem with the API generated with aws amplify.
Basically, I keep getting the following warning whenever I try to create one entity and it is not being persisted in DynamoDB.
Variable 'input' has coerced Null value for NonNull type 'String!
The following are the pertinent parts of the Graphql schema I used to create the backend.
enum EntityStatus {
ACTIVE
INACTIVE
ARCHIVED
}
type Address {
streetAddress1: String!
streetAddress2: String
city: String!
state: String!
zipCode: String!
country: String!
location: Location!
}
type Location {
lat: Float
lng: Float
}
type Tenant
#model
#auth(
rules: [
{ allow: groups, groups: ["Admin", "Coordinator", "Employees"], operations }
{ allow: groups, groups: ["Auditor"], operations: [read] }
]
) {
id: ID!
name: String!
address: Address!
phone: AWSPhone!
email: AWSEmail!
status: EntityStatus!
locale: String!
}
The code to create one of the Tenant entities is a simple call
try {
return await DataStore.save(new Tenant({ ...values }));
} catch (error) {
console.error(error);
}
The payload going sent by Datastore is as follows:
{
"name": "Tenant 1",
"phone": "1234567890",
"email": "tenant#tenant.com",
"status": "ACTIVE",
"address": {
"city": "Anytown",
"state": "TAB",
"zipCode": "12345",
"country": "US",
"location": { "lat": 123.12, "lng": 123.12 }
},
"locale": "en-US",
"id": "f8be53bd-b1cb-4cbd-9b64-01fdf930da8a"
}
Here is the full Warning message
[WARN] 40:26.787 DataStore
Object { localModel: {…}, message: "Variable 'input' has coerced Null value for NonNull type 'String!'", operation: "Create", errorType: undefined, errorInfo: undefined, remoteModel: null }
errorInfo: undefined
errorType: undefined
localModel: Object { id: "f8be53bd-b1cb-4cbd-9b64-01fdf930da8a", name: "Tenant 1", phone: "1234567890", … }
_deleted: undefined
_lastChangedAt: undefined
_version: undefined
address: Object { city: "Anytown", state: "TAB", zipCode: "12345", … }
createdAt: undefined
email: "tenant#tenant.com"
id: "f8be53bd-b1cb-4cbd-9b64-01fdf930da8a"
locale: "en-US"
name: "Tenant 1"
phone: "1234567890"
status: "ACTIVE"
updatedAt: undefined
<prototype>: Object { … }
message: "Variable 'input' has coerced Null value for NonNull type 'String!'"
operation: "Create"
remoteModel: null
<prototype>: Object { … }
react_devtools_backend.js:3973:25
Figured it out. My payload was missing 2 fields.
Wish that the error messages would be more helpful.
I've read documention typeorm, but un didn't find the solution of my problem.
Neither in the forum, somme guys describe suquery, but it's not works with leftJoinAndSelect.
If someone can help thanks a lot
I've Article entity
#Entity('article')
export class Article extends BaseEntity{
#PrimaryGeneratedColumn()
id: number;
#Column()
title: string;
#Column({type: "longtext"})
content: string;
#Column({ default: false })
is_published: boolean;
#CreateDateColumn({ type: "timestamp", default: () => 'CURRENT_TIMESTAMP' })
createDateTime: Date;
#ManyToOne(type => User, user => user.articles)
user:User;
}
and User entity
#Entity()
export class User extends BaseEntity{
#PrimaryGeneratedColumn()
id: number;
#Column()
username: string;
#Column()
password: string;
#Column({ default: true })
isActive: boolean;
#Column({default: 'contrinutor'})
role: string
#OneToMany(()=> Article, article => article.user)
articles: Article[];
}
I want to get one article and join the user associate to the article, BUT only retrieve data for the article and the username , NOT all info data.
Currently i 've tried this:
const article = await this.articleRepository
.createQueryBuilder('article')
.where({id: id})
.leftJoinAndSelect("article.user","user")
.getOne();
And result :
{
"id": 1,
"title": "My super Title",
"content": "My super content",
"is_published": false,
"createDateTime": "2021-01-21T13:37:15.894Z",
"user": {
"id": 1,
"username": "admin",
"password": "admin",
"isActive": true,
"role": "contributor"
}
}
and that i would wish:
{
"id": 1,
"title": "My super Title",
"content": "My super content",
"is_published": false,
"createDateTime": "2021-01-21T13:37:15.894Z",
"user": {
"username": "admin",
"role": "contrinutor"
}
}
Thanks for help 😁
You can Archive the result by using select,leftJoin and AddSelect :
const article = await this.articleRepository
.createQueryBuilder('article')
.where({id: id})
.leftJoin("article.user","user")
.select(['article'])
.addSelect(['user.username','user.role'])
.getOne();
I have a simple full-stack amplify app.
Here is my model:
type Note #model #auth(rules: [{allow: public}]) {
id: ID!
name: String!
description: String
image: String
NoteType: NoteType #connection
}
type NoteType #model #auth(rules: [{allow: public}]) {
id: ID!
name: String!
}
I'm trying to delete a Note with the following payload:
{
"query": "mutation DeleteNote($input: DeleteNoteInput!, $condition: ModelNoteConditionInput) {↵ deleteNote(input: $input, condition: $condition) {↵ id↵ name↵ description↵ image↵ createdAt↵ updatedAt↵ NoteType {↵ id↵ name↵ createdAt↵ updatedAt↵ }↵ }↵}↵",
"variables": {"input": {"id": "0c5e3ced-ffa3-4de8-9010-40b67d5bab68"}}
}
What I see in the response is the following json:
{
"data": {
"deleteNote": null
},
"errors": [
{
"path": [
"deleteNote"
],
"data": {
"id": "0c5e3ced-ffa3-4de8-9010-40b67d5bab68",
"name": "bb",
"description": "bb",
"image": "icon.png",
"createdAt": "2020-12-21T12:00:26.743Z",
"updatedAt": "2020-12-21T12:00:26.743Z"
},
"errorType": "ConflictUnhandled",
"errorInfo": null,
"locations": [
{
"line": 1,
"column": 88,
"sourceName": null
}
],
"message": "Conflict resolver rejects mutation."
}
]
}
The code was working until I tried to add the NoteType! Is there any conflict regarding the foreign-key here?
When using ConflictResolution you also need to include the _version field.
{
"query": "mutation DeleteNote($input: DeleteNoteInput!, $condition: ModelNoteConditionInput) {↵ deleteNote(input: $input, condition: $condition) {↵ id↵ name↵ description↵ image↵ createdAt↵ updatedAt↵ NoteType {↵ id↵ name↵ createdAt↵ updatedAt↵ }↵ }↵}↵",
"variables": {"input": {"id": "0c5e3ced-ffa3-4de8-9010-40b67d5bab68", "_version": "_version value of your note object"}}
}
I also noticed that after deleting elements that are using ConflictResolution, they are not immediately deleted from the database. Instead, two flags are being added: _deleted is set to true and _ttl is set to expire the object in 30 days.
I need to lock a text channel, so #everyone cannot see that, but message.author can. I have this code, but everyone can see the channel (and in the channel properties everyone hasn't got permission for send messages or send TTS messages, but above that everything is [/])
message.guild.channels.create(desc, {
type: 'text',
permissionOverwrites: [
{
id: message.guild.roles.everyone,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},
{
id: message.author.id,
allow: ['VIEW_CHANNEL'],
},
],
})
The PermissionOverwrites typedef requires a Snowflake (in this case, a role or user ID). However, RoleManager.everyone returns a Role. There are two ways to solve this issue:
Simply just use the id property of the role
{
id: message.guild.roles.everyone.id,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},
Use message.guild.id. Fun fact, the #everyone role shares the same ID as the guild it's in
{
id: message.guild.id,
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES'],
},
The example from docs about many-to-many relationship supposes that companies would be added after the person was already created.
However, what if the person data comes from server with a list of companies (companies' ids) already?
Is it possible to modify the example so that the following code (or smt. similar) would be possible:
// somewhere before we have a collection of companies defined like this:
// [{id: 1, name: 'ibm'}, {id: 2, name: 'apple'}]
// and than we do:
paul = new Person({
name: 'Paul',
jobs: [1, 2]
})
paul.get('jobs').at(0).get('name') // 'ibm'
When trying to achieve this the same way I'd do with one-to-many relations, I fail:
Companies = Backbone.Collection.extend({model: Company})
companies = new Companies([{id: 1, name: 'ibm'}, {id: 2, name: 'apple'}])
john = new Person({
name: 'John',
jobs: [1]
})
john.get('jobs').toJSON() // []
companies.get(1).get('employees').toJSON() // []
Here's the fiddle you can play with: http://jsfiddle.net/ymr5Z/
Your MAIN problem is that you are trying to add Jobs by ID. You never created any job object though let alone set their id! You only created the companies.
A better way to go about adding jobs is to have an addJob() function which you give a company ID (or company) and it creates the Job model for you.
Full Code to fit your example
and specifically:
var Person = Backbone.RelationalModel.extend({
relations: [{
type: 'HasMany',
key: 'jobs',
relatedModel: Job,
reverseRelation: {
key: 'person'
//includeInJSON: false //if you don't want to show person
}
}],
addJob: function (company) {
this.get('jobs').add(new Job({
company: company
}));
}
});
paul.addJob(1);
paul.addJob(2);
Works perfectly. You might also want to set an includeInJSON to false for your reverse relationship on the Job to exclude the person!
[{
"company": {
"id": 1,
"name": "ibm",
"employees": [null]
},
"person": {
"name": "Paul",
"jobs": [null, {
"company": {
"id": 2,
"name": "apple",
"employees": [null]
}
}]
}
}, {
"company": {
"id": 2,
"name": "apple",
"employees": [null]
},
"person": {
"name": "Paul",
"jobs": [{
"company": {
"id": 1,
"name": "ibm",
"employees": [null]
}
},
null]
}
}]