Conflict in type inflection between EmberData and Django REST framework - django

EmberData is POSTing:
{
"data": {
"attributes": {
"name": "The project name",
"description": "The project description",
"price": 123
},
"relationships": {
"onwer": {
"data": null
}
},
"type": "projects"
}
}
And Django (drf I guess) is complaining with a 409 Conflict:
{
"errors": {
"detail": "The resource object's type (projects) is not the type that constitute the collection represented by the endpoint (project)."
}
}
Apparently the JSONApi spec does not enforce an inflection rule. How can I tell drf to accept plurals for the type?

There is a config parameter:
JSON_API_PLURALIZE_RELATION_TYPE = True

You could also explicitly set the resource name:
class CategoryViewSet(viewsets.ModelViewSet):
resource_name = 'categories'
...

Related

List users as non admin with custom fields

As per the documentation, I should be able to get a list of users with a custom schema as long as the field in the schema has a value of ALL_DOMAIN_USERS in the readAccessType property. That is the exact set up I have in the admin console; Moreover, when I perform a get request to the schema get endpoint for the schema in question, I get confirmation that the schema fields are set to ALL_DOMAIN_USERS in the readAccessType property.
The problem is when I perform a users list request, I don't get the custom schema in the response. The request is the following:
GET /admin/directory/v1/users?customer=my_customer&projection=full&query=franc&viewType=domain_public
HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: Bearer fakeTokena0AfH6SMD6jF2DwJbgiDZ
The response I get back is the following:
{
"nextPageToken": "tokenData",
"kind": "admin#directory#users",
"etag": "etagData",
"users": [
{
"externalIds": [
{
"type": "organization",
"value": "value"
}
],
"organizations": [
{
"department": "department",
"customType": "",
"name": "Name",
"title": "Title"
}
],
"kind": "admin#directory#user",
"name": {
"fullName": "Full Name",
"givenName": "Full",
"familyName": "Name"
},
"phones": [
{
"type": "work",
"value": "(999)999-9999"
}
],
"thumbnailPhotoUrl": "https://photolinkurl",
"primaryEmail": "user#domain.com",
"relations": [
{
"type": "manager",
"value": "user#domain.com"
}
],
"emails": [
{
"primary": true,
"address": "user#domain.com"
}
],
"etag": "etagData",
"thumbnailPhotoEtag": "photoEtagData",
"id": "xxxxxxxxxxxxxxxxxx",
"addresses": [
{
"locality": "Locality",
"region": "XX",
"formatted": "999 Some St Some State 99999",
"primary": true,
"streetAddress": "999 Some St",
"postalCode": "99999",
"type": "work"
}
]
}
]
}
However, if I perform the same request with a super admin user, I get an extra property in the response:
"customSchemas": {
"Dir": {
"fieldOne": false,
"fieldTwo": "value",
"fieldThree": value
}
}
My understanding is that I should get the custom schema with a non admin user as long as the custom schema fields are set to be visible by all domain users. This is not happening. I opened a support ticket with G Suite but the guy that provided "support", send me in this direction. I believe this is a bug or maybe I overlooked something.
I contacted G Suite support and in fact, this issue is a domain specific problem.
It took several weeks for the issue to be addressed by the support engineers at Google but it was finally resolved. The behaviour is the intended one now.

How to alias/override the HTTP path of a default remote-method in Loopback

I have a model players which is extended from the base model User.
The player model inherits all the remote-methods from the base model. A new 'User' can be created by a POST /user in the base model.
My custom model player also inherits this method.
In my use-case i want this method to be POST /signup. How could i do this?
"methods": {
"signup": {
"accepts": [],
"returns": [
{
"arg": "user",
"type": "object",
"root": false,
"description": "the data about created user"
}
],
"description": "User signup",
"http": [
{
"path": "/",
"verb": "post"
}, {
"path": "/signup",
"verb": "post"
}
]
}
}
With the snippet above in the model.json file for remote-method i was able to expose two endpoints for user creation. But can i override the path for POST /user to POST /signup?
There is no way in loopback to achieve this. Even if you create a new custom remote method, its endpoint would always be prefixed with /user.

How do I reference one model from another model using aws API Gateway

Say I have a Model:
"Pet":{
"type": "object"
"properties": {
"name":{"type":"integer"},
"age":{"type":"integer"}
}
}
And another model:
"Human":{
"type": "object"
"properties": {
"name":{"type":"integer"},
"age":{"type":"integer"},
"pets":{
"type":"array"
"items": {
<This is where my question is>
}
}
}
}
How can I reference the Pet model in my human model?
With swagger I was able to say:
"$ref": "#/definitions/Pet"
but API Gateway seems to not allow it.
If you mean reference model outside swagger, you can do that by specifying the model with an absolute url like below
{"type":"array","items":{"$ref":"https://apigateway.amazonaws.com/restapis/<rest_api_id>/models/Pet"}}
For swagger, this example from open api specification shows how to reference models within swagger - https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/json/petstore.json
"Pets": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
Note that api gateway does not support 'default' response, so if you are trying to import the above petstore.json example, you need to remove the "default" fields.
If you just want single values (not arrays), this works:
..
"properties": {
"id": {
"$ref": "https://apigateway.amazonaws.com/restapis/abcd1234/models/UserId"
},
..
(It would be nice if this could be a relative URL rather than absolute, but I haven't found any mention of how to do this yet)

Display JSON Api conform errors

I receive JSON Api conform errors from the backend:
{
"errors": [
{
"status": "400",
"source": {
"pointer": "/data/attributes/description"
},
"detail": "This field may not be null."
},
{
"status": "400",
"source": {
"pointer": "/data/attributes/due-date"
},
"detail": "This field may not be null."
},
{
"status": "400",
"source": {
"pointer": "/data/attributes/extra-comments"
},
"detail": "This field may not be null."
},
{
"status": "400",
"source": {
"pointer": "/data/attributes/name"
},
"detail": "This field may not be null."
},
{
"status": "400",
"source": {
"pointer": "/data/attributes/payment-type"
},
"detail": "This field may not be null."
},
{
"status": "400",
"source": {
"pointer": "/data/attributes/price"
},
"detail": "This field may not be null."
}
]
}
I try to show them in my template, as described in the EmberData documentation:
{{#each model.errors.messages as |message|}}
<div class="error">
{{message}}
</div>
{{/each}}
Nothing is shown. I would say the .errors in the model are not populated, but I am not sure how to check this. How can I:
display the received ajax reply?
make sure that EmberData is processing the reply and populating model.errors?
Show the processed model.errors in the console?
Show the model and all properties?
In general, I am experiencing that new versions of Ember are very hard to debug. Whenever I show any Ember object in the console, I just see some Computed properties which are not expanded whenever I try to peek into them.
My backend is:
Django 1.9
with django-rest-framework
django-rest-framework-json-api
EDIT
This is the data that I am POSTing to the backend (JSONAPi conform):
{
"data": {
"attributes": {
"name": null,
"description": null,
"extra-comments": null,
"min-price": 30,
"max-price": 3000,
"price-step": 10,
"price": null,
"payment-type": null,
"due-date": null
},
"relationships": {
"seller": {
"data": null
},
"artist": {
"data": null
},
"subcategory": {
"data": null
}
},
"type": "projects"
}
}
The backend is ok with this, detects the errors, and provides a JSON APi conform errors reply, as specified above.
I think I know what's happening (as it happened to me as well).
Change the HTTP error code from 400 to 422 (Unprocessable Entity) and check if it fixes the problem.
Also, looking at the source code for the JSONAPIAdapter (which extends from the RestAdapter) I think I'm right.
isInvalid: function(status, headers, payload) {
return status === 422;
},
This can be changed to (adapters/application.js):
import DS from 'ember-data';
import config from '../config/environment';
export default DS.JSONAPIAdapter.extend(DataAdapterMixin, {
host: config.API_HOST,
namespace: config.API_NAMESPACE,
isInvalid: function(status, headers, payload) {
return status === 400 || status === 422;
},
});
For reference, I have done this on the django side:
from rest_framework_json_api.exceptions import exception_handler
def custom_exception_handler(exc, context):
# DRF returns 400, but EmberData wants 422. I will force a 422, always.
# Call the rest_framework_json_api's exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# TODO: is this correct? 422 in all exception cases?!
response.status_code = 422
return response

Where/when should I remove the relationship type to avoid an unknown keys warning?

I'm using Ember Data with a server application that follows the json:api standard. When I normalize the response from the server, I'm adding a relationshipType attribute from the links so that Ember Data knows what type of model to build when the relationship is polymorphic.
For example, here's the response from the server:
{
"members": {
"id": "1",
"created_at": "2014-10-15T18:35:00.000Z",
"updated_at": "2014-10-15T18:35:00.000Z",
"links": {
"user": {
"id": "1",
"type": "users",
"href": "http://test.host/api/v1/users/1"
},
"organization": {
"id": "2",
"type": "customers",
"href": "http://test.host/api/v1/customers/2"
}
}
}
}
The organization relationship is polymorphic, and the type in this instance is customers.
In the Ember application, I'm normalizing the response into following (which follows the RESTSerializer convention):
{
"members": {
"id": "1",
"created_at": "2014-10-15T18:35:00.000Z",
"updated_at": "2014-10-15T18:35:00.000Z",
"user": "1",
"userType": "users",
"organization": "2",
"organizationType": "customers"
}
}
This works, and Ember Data builds the correct user relationship and organization relationship (using the Customer model).
But, I'm receiving the following warning:
WARNING: The payload for '(subclass of DS.Model)' contains these unknown keys:
[userType,organizationType]. Make sure they've been defined in your model.
I'd like to remove these relationshipType keys and their values after they've been used.
Where should I do this?
Have you tried using https://github.com/kurko/ember-json-api? I may have some other overrides in my app to handle polymorphism but hopefully the package will get you closer.
Also see my pending PR.