How to make a relationship of data from user pool to aws appsync model - amazon-cognito

I am new to amplify and appsync. I am trying to create a Post model that needs to have a relationship of the user who is creating the Post. The problem is my user is from cognito user pool.
What I want is the user from cognito I don't want to create new user table on dynamo db because cognito user pool already has its information I just want to get the user info that is creating that Post if I query the post.
How should I create a relationship of this?
I create amlify api like this
? Please select from one of the below mentioned services: GraphQL
? Choose the default authorization type for the API API key
? Enter a description for the API key:
? After how many days from now the API key should expire (1-365): 7
? Do you want to configure advanced settings for the GraphQL API Yes, I want to make some additional changes.
? Configure additional auth types? Yes
? Choose the additional authorization types you want to configure for the API Amazon Cognito User Pool
Cognito UserPool configuration
Use a Cognito user pool configured as a part of this project.
? Configure conflict detection? No
Here is my current schema.grapql
type Post
#model
#versioned
#aws_cognito_user_pools
#auth(rules: [{ allow: owner, queries: null }, { allow: public }]) {
id: ID!
title: String!
content: String
thumb: String
slug: String!
allow_comments: Boolean
owner: String!
post_type: String!
add_to_nav: Boolean!
version: Int!
comments: [Comment] #connection(name: "PostComments")
}
type Comment
#model
#versioned
#aws_cognito_user_pools
#auth(rules: [{ allow: owner, queries: null }]) {
id: ID!
content: String
version: Int!
post: Post #connection(name: "PostComments")
}
====================================================
EDIT: Added result of data that I want
Here is the query that I want to perform
query ListPost {
listPosts {
items {
title
content
owner{
username
id
email
first_name
last_name
}
}
}
}
}
Result that I want
{
"data": {
"listPosts": {
"items": [
{
"title": "title 1"
"content": "Test long text cotent"
"owner": {
"username": "user1"
"id": "234234234"
"email": "user1#test.com"
"first_name": "John"
"last_name": "Doe"
}
},
{
"title": "title 1"
"content": "Test long text cotent"
"owner": {
"username": "user1"
"id": "234234234"
"email": "user1#test.com"
"first_name": "John"
"last_name": "Doe"
}
},
]
}
}
}
I can't find any documentation how to build something like this.

This should help for anyone else that is looking into doing this:
https://docs.amplify.aws/cli-legacy/graphql-transformer/function/#usage
Scroll to:
Example: Get the logged in user from Amazon Cognito User Pools

Related

How not to expose duplicated (normalize?) nodes via GraphQL?

Given "user has many links" (what means a link was created by a user) DB entities relations, I want to develop API to fetch links along with users so that the returned data does not contain duplicated users.
In other words, instead of this request:
query {
links {
id
user {
id email
}
}
}
that returns the following data:
{
"data": {
"links": [
{
"id": 1,
"user": {
"id": 2,
"email": "user2#example.com"
}
},
{
"id": 2,
"user": {
"id": 2,
"email": "user2#example.com"
}
}
]
}
}
I want to make a request like this (note the "references" column):
query {
links {
id
userId
}
references {
users {
id
email
}
}
}
that returns associated users without duplicates:
{
"data": {
"links": [
{
"id": 1,
"userId": 2
},
{
"id": 2,
"userId": 2
},
],
"references": {
"users": [
{
"id": 2,
"email": "user2#example.com"
}
]
}
}
}
That should reduce amount of data transferred between client and server that adds a bit of speed boost.
Is there ready common implementation on any language of that idea? (Ideally, seeking for Ruby)
It's not a query or server role to normalize data.
there are no such possibilities in GraphQL specs;
server must return all asked fields within queried [response] structure;
... but you can implement some:
standarized (commonly used) pagination (relay style edges/nodes, nodes only or better both);
query [complexity] weights to promote this optimized querying style - separate problem;
reference dictionary field within queried type;
links {
egdes {
node {
id
title
url
authorId
# possible but limited usage with heavy weights
# author {
# id
# email
# }
}
}
pageInfo {
hasNextPages
}
referencedUsers {
id
email
}
}
where:
User has id and email props;
referencedUsers is [User!] type;
node.author is User type;
Normalizing Graphql client, like Apollo, can easily access cached user fields without making separate requests.
You can render (react?) some <User/> component (within <Link /> component) passing node.authorId as an argument like <User id={authorId} />. User component can useQuery hook with cache-only policy to read user props/fields.
See Apollo docs for details. You should implement this for yourself and document this to help/guide API users.

Has the google oauth API response changed for email scope? The type of email has changed from 'account' to 'ACCOUNT'

We are using google login in our website and spring social library to implement oAuth 2. After getting accessToken , with scope as userInfo.email, we are trying to retrieve accountEmail. spring-social-google(version 1.0.0) is looking for key "account" in the emails property of the reponse. Below is code block from spring-social-sources org.springframework.social.google.api.plus.Person.class
public String getAccountEmail() {
if (emails != null) {
for (Entry<String, String> entry : emails.entrySet()) {
if (entry.getValue().equals("account")) {
return entry.getKey();
}
}
}
return null;
}
From Oct 27, google is responding with email map as "ACCOUNT" instead of "account"
Expert from logs before 27th - getEmails :: {xxxxxxx#gmail.com=account}
Expert from logs after 27th - getEmails :: {xxxxxxx#gmail.com=ACCOUNT}
I could not find any documentmentation from google regarding the change or reponse format. When i use API playground, i can see the type is coming as 'ACCOUNT'.
"image": {
"url": "....photo.jpg",
"isDefault": true },
"etag": "xxx",
"id": "xxx",
"kind": "plus#person",
"emails": [
{
"type": "ACCOUNT",
"value": "xxxx#gmail.com"
}
]
}
I just wanted to check if any one else faced the issue or if anyone has a documentation from google, which explains why the change happened.

How to get credential information of object storage through Softlayer API?

How can I get credential information that includes public host, private host, username, and password of the ordered object storage?
Softlayer control site uses the api below to get the information.
POST https://control.softlayer.com/storage/objectstorage/getclusterinfo
This request may help you:
https://[username]:[apikey]#api.softlayer.com/rest/v3/SoftLayer_Account/getHubNetworkStorage?objectMask=mask[id,username,serviceResource[name,datacenter,frontendIpAddress,backendIpAddress]]
Method: GET
The result will display something like this:
{
"id": 4309678
"username": "SLOS112233-11"
"serviceResource": {
"backendIpAddress": "https://dal05.objectstorage.service.networklayer.com/auth/v1.0/"
"frontendIpAddress": "https://dal05.objectstorage.softlayer.net/auth/v1.0/"
"name": "OBJECT_STORAGE_DAL05"
"datacenter": {
"id": 123456
"longName": "Dallas 5"
"name": "dal05"
"statusId": 2
}-
}-
}
If you want got information of a specific item, please apply a filter:
https://[username]:[apikey]#api.softlayer.com/rest/v3/SoftLayer_Account/getHubNetworkStorage?objectFilter={ "hubNetworkStorage": { "username": { "operation": "SLOS334455-10" } } }
Method: GET
Some references can help you:
http://sldn.softlayer.com/reference/services/SoftLayer_Account/getHubNetworkStorage
https://sldn.softlayer.com/reference/Object-Storage-CDN/Set-Time-Live-TTL
https://sldn.softlayer.com/blog/waelriac/Managing-SoftLayer-Object-Storage-Through-REST-APIs

How to manage fine grain permissions in Elasticsearch?

I need to store in a consistent way the role/groups that can access the information but I'm not sure what's the best way to do it.
Summary: I have 2 kinds of docs "tweet" and "blog":
At tweet level, I store the group name allowed to access the information
blog is more complex, there are metadata (title, description, nature, ...) but some of those informations can be restricted to some groups of user (only admin, or logged_in users)
What the best way to map this with Elasticsearch ?
As of today, I end up with documents like:
/tweet/455
{
id: 112,
ugroups: [ "restricted_user", "admin" ],
description: "foo",
},
{
id: 113,
ugroups: [ "anonymous" ]
description: "foo",
}
and
/blog/500
{
id: 5,
fields: [
{
"nature": {
"value": "foo",
"ugroup": [ "admin" ]
}
}
]
}
{
id: 6,
fields: [
{
"comment": {
"value": "foo",
"ugroup": [ "anonymous" ]
}
}
]
}
When user want to search in tweet, that's easy, I build a term query with words submitted by the user and I append the groups the user belongs to this query.
But how to make a query that will take this "ugroup" thing at various level ?
Ideally I could issue a query like:
search in tweet with tweet.ugroup: "anonymous" and in blog with blog.fields.*.ugroup: "anonymous"
Is there a way to write such a query ?

EmberJS Data hasMany sideloading with ActiveModelSerializers

I'm using Ember Data canary build: 1.0.0-beta.8+canary.267214b9 together with a rails back-end and ActiveModelSerializer. My configuration on ember side looks like this:
App.ApplicationSerializer = DS.ActiveModelSerializer.extend()
App.ApplicationAdapter = DS.ActiveModelAdapter.extend
namespace: "api/v1"
App.Authentication = DS.Model.extend
provider: DS.attr('string')
user: DS.belongsTo('user')
App.User = DS.Model.extend
username: DS.attr('string')
email: DS.attr('string')
authentications: DS.hasMany('authentication')
I have working hasMany and belongsTo relation for a model that isn't side loaded. The JSON for the relation look like this:
{
objectA: {
property1: 'prop1',
property2: 'prop2',
objectB_ids: ['1','2']
}
}
At the moment I try to get a user model with multiple authentications to work. But there the authentications should be side loaded. It doesn't work for the following JSON:
JSON - not working
{
authentications: [{ id:1, provider:"google" }],
user: {
id: '1',
username: 'max',
email: 'max#examle.com',
authentication_ids:[1],
}
}
But it does work for this:
JSON - working
{
authentications: [{ id:1, provider:"google" }],
user: {
id: '1',
username: 'max',
email: 'max#examle.com',
authentications:[1],
}
}
The only useful information I found on the web is this SO question:
Serialising async hasMany relationships
Is this a bug in the DS.ActiveModelSerializer or did I miss some configuration?
EDIT 1:
In the docs of DS.ActiveModelSerializer you can find the following:
It has been designed to work out of the box with the activemodelserializers Ruby gem.
And the version with authentication_ids:[...] is the way, how the ActiveModelSerializers Ruby gem does it out of the box. So maybe it should be added?
I think you're confusing what ActiveModelSerializer does with other conventions of Ember Data. You're working second example is correct. This section describes the current expectation of JSON layout. The _ids is not present.
{
"post": {
"id": 1,
"title": "Rails is omakase",
"comments": ["1", "2"],
"user" : "dhh"
},
"comments": [{
"id": "1",
"body": "Rails is unagi"
}, {
"id": "2",
"body": "Omakase O_o"
}]
}
The ActiveModelSerializer adapter allows you to pass underscored keys in your JSON instead of camelcased keys. For example, if your user had a camelcased name:
App.User = DS.Model.extend
firstName: DS.attr()
Your JSON should look like this:
{
"user": {
"first_name": "kunerd"
}
}
Solved my issue and DS.ActiveModelSerializer works as expected and did accept _ids array for side loaded models.
My problem was, that I had overwritten my App.UserSerializer with that:
App.UserSerializer = DS.RESTSerializer.extend
# some custom logic
,but it has to be:
App.UserSerializer = App.ApplicationSerializer.extend
# some custom logic
Maybe someone has similar problems after changing from DS.RESTSerializer to DS.ActiveModelSerializer`