im using Ember Data 1.13.3. and i want to convert my old JSON format to new JSONAPI format using normalizeResponse in JSONAPISerializer.
for example i have my json coming from web service like
{
user: { id: 1, name: 'wecc', accounts: [1, 2] },
accounts: [
{ id: 1, email: 'wecc#sweden.se' },
{ id: 2, email: 'wecc#greece.gr' }
]
}
now in my JSONAPISerializer how can i get the JSONAPI format out of my old json. im getting old format. but i want that format converted automatically into JSONAPI. like below one
{
data: {
id: '1',
type: 'user',
attributes: {
name: 'wecc'
},
relationships: {
accounts: {
data: [
{ id: '1', type: 'account' },
{ id: '2', type: 'account' }
]
}
}
},
included: [{
id: '1',
type: 'account',
attributes: {
email: 'wecc#sweden.se'
}
}, {
id: '2',
type: 'account',
attributes: {
email: 'wecc#greece.gr'
}
}]
}
i found some help from ember itself.
http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html#toc_internal-format-change-to-json-api
they recommand to use normalizeResponse
It won't happen automatically. If you are also in control of your REST API I'd recommend normalizing the data on the server itself. Otherwise as you suggested it will have to happen within normalizeResponse, but with custom code written to match your data format.
Another solution is to keep using the RESTSerializer for now and wait until the JSON API specification gets a bit more popular. Tools will likely be released for most server frameworks to provide standard JSON API payloads in the coming months.
Related
I was implementing a role based authentication using next-auth v4 using CognitoProvider which I modified to add a role but the role attribute is not passed in the final session json
import NextAuth from "next-auth/next";
function CognitoProvider(options) {
return {
id: "cognito",
name: "Cognito",
type: "oauth",
wellKnown: `${options.issuer}/.well-known/openid-configuration`,
idToken: true,
profile(profile) {
console.log(profile);
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
role: profile["cognito:groups"],
};
},
options,
};
}
export default NextAuth({
providers: [
CognitoProvider({
clientId: process.env.COGNITO_CLIENT_ID,
clientSecret: process.env.COGNITO_CLIENT_SECRET,
issuer: process.env.COGNITO_DOAMIN,
}),
],
callbacks: {
session: (props) => {
console.log(props);
return props.session;
},
},
});
Below is the console log of profile object
role: profile["cognito:groups"]
Actual Object
I have added a user to admin group and wanted him to access a specific route in my NextJS app.
Any help would be appreciated.
You need to configure the jwt and session callbacks to include more data in the session.
From Next-Auth docs:
If you want to make something available you added to the token [...] via the jwt() callback, you have to explicitly forward it here [the session() callback] to make it available to the client.
To add the user's role:
export default NextAuth({
// ...
callbacks: {
jwt({ token, account, profile }) {
if (account) {
// modify token
token.role = profile.role;
}
return token;
},
session({ session, token }) {
// Send properties to the client
if (session.user) {
// modify session
session.user.roles = token.role;
}
return session;
},
},
});
Then in your route, you would get the user's role from the session session.user.role
When I push my code to sonar, it mentioned below type of codes not cover by unit tests(Jest JS). How to remove this kind of swagger definition code from code coverage in sonar.
#ApiOperationPost({
description: "Student details",
summary: "Student details",
path: "/student",
security: {
authorization: [],
},
parameters: {},
responses: {
200: {
description: "Student details request",
model: "StudentDetailsRequest",
type: SwaggerDefinitionConstant.Response.Type.ARRAY,
},
400: { description: "Expected Parameters Missing", model: "Problem" },
401: { description: "Unauthorized", model: "Problem" },
500: { description: "Internal Server Error", model: "Problem" },
},
})
Please help me to solve this issue. Any help or workarounds are really appreciated.
I set up a basic model and controller connected to mysql database. Everything looks good and is working.
My Definition Model looks like this.
import { Entity, model, property } from '#loopback/repository';
#model({
settings: {
mysql: {
table: 'definition'
}
}
})
export class Definition extends Entity {
#property({
type: 'number',
id: true,
generated: true,
forceId: true,
required: false,
description: 'The unique identifier for a definition',
})
id: number;
#property({
type: 'string',
required: true,
})
name: string;
#property({
type: 'string',
required: true,
})
process_id: string;
constructor(data?: Partial<Definition>) {
super(data);
}
}
export interface DefinitionRelations {
// describe navigational properties here
}
export type DefinitionWithRelations = Definition & DefinitionRelations;
When I have it up and running and click on the explorer to test it out.
I click on "Try it out" for get /definitions and the only editable field that gets enabled is the filter field.
It is repopulated with a value like this...
{
"where": {},
"fields": {
"id": true,
"name": true,
"process_id": true
},
"offset": 0,
"limit": 0,
"skip": 0,
"order": [
"string"
]
}
I have to clear that to get it to work which is fine. When I run it with no filter it returns these results.
[
{
"id": 10,
"name": "Place Manual Payoff Order Process Config",
"process_id": "Process_PlaceManualPayoffOrderProcessConfig"
},
{
"id": 11,
"name": "test",
"process_id": "Test"
},
{
"id": 12,
"name": "test2",
"process_id": "test2"
}
]
I am trying to use the filter expression to only return ones with a specific process_id field. So I change the filter to look like this.
{
"where": {"process_id": "test2"}
}
And it still returns the same results.
[
{
"id": 10,
"name": "Place Manual Payoff Order Process Config",
"process_id": "Process_PlaceManualPayoffOrderProcessConfig"
},
{
"id": 11,
"name": "test",
"process_id": "Test"
},
{
"id": 12,
"name": "test2",
"process_id": "test2"
}
]
Do filters currently work in Loopback 4 or am I using them incorrectly?
EDIT: if I post the filters in the URL string they work. It seems as though the openapi ui isn't generating that part of the filter Into the URL string.
It seems as though the openapi ui isn't generating that part of the filter Into the URL string.
Yes, this a precise description.
OpenAPI Spec version 3.x does not specify how to serialize deeply-nested values to URL queries and swagger-js, the library powering swagger-ui (which powers LoopBack's REST API Explorer), silently ignores such values.
The issue has been reported and is being discussed here:
swagger-api/swagger-js#1385
OAI/OpenAPI-Specification#1706
AppSync appears to be loading the incorrect resolver template for some fields of nested objects. Also, it appears to only happen when the nested object has a field with the same name as a field on the parent object.
I've included an example below because I think that might be the best way to explain the issue. As you can see, the id fields for the nested objects are not being resolved correctly.
Each type, Task, User, List, and Tag, have a resolver for their id field because the data for each has a prefix on the id field. For example, Task.id has a resolver that returns $context.source.task_id and User.id has a resolver that returns $context.source.user_id. Same for List and Tag.
What appears to be happening is AppSync is loading the id resolver template for the parent type. You can see that this is the case for task.owner.id, where owner is a User but the id gets resolved as "$context.source.task_id". Same for task.list.id where list is a List. Again we can see this for task.tags[0].owner.id. owner is once again a User except this time the parent is a Tag so task.tags[0].owner.id is resolved as "$context.source.tag_id". These three example show that the problem is not with a particular type since User and List are behaving the same when they are nested in a Task. Also, we can see that the issue is not with Task since User is behaving similarly when nested in a Tag. Lastly, we can see that task.tags[1].owner.id actually behaves correctly. This indicates that the issue only presents itself on first execution.
At this point I strongly suspect this is a bug with AppSync however, I'm not 100% on that. Has anyone else experienced this issue? Am I doing something terribly wrong?
Example
Query
{
task(id: "task-123") {
id,
title,
owner {
id,
username,
},
list {
id,
name,
},
tags {
id,
name,
owner {
id,
username,
},
},
},
}
Result
{
"data": {
"task": {
"id": "task-123",
"title": "First Task",
"owner": {
"id": "$context.source.task_id",
"username": "tom"
},
"list": {
"id": "$context.source.task_id",
"name": "Inbox"
},
"tags": [
{
"id": "tag-123",
"name": "one",
"owner": {
"id": "$context.source.tag_id",
"username": "tom"
}
},
{
"id": "tag-234",
"name": "two",
"owner": {
"id": "user-123",
"username": "tom"
}
}
]
}
}
}
Task Schema
type Task {
id: ID!
title: String!
owner: User!
list: List
tags: [Tag]
}
User Schema
type User {
id: ID!
username: String!
}
List Schema
type List {
id: ID!
name: String!
}
Tag Schema
type Tag {
id: ID!
name: String!
owner: User!
}
Task Data
{
task_id: "task-123",
title: "First Task",
owner_id: "user-123",
list_id: "list-123",
tags: [
"tag-123",
"tag-234"
]
}
User Data
{
user_id: "user-123",
username: "tom"
}
List Data
{
list_id: "list-123",
name: "Inbox"
}
Tag Data
{
tag_id: "tag-123",
name: "one",
owner_id: "user-123"
}
{
tag_id: "tag-234",
name: "two",
owner_id: "user-123"
}
Example id resolver (User)
Request Mapping Template
{
"version": "2017-02-28",
"payload": "$context.source.user_id"
}
Response Mapping Template
$util.toJson($context.result)
The id resolvers for the other types are very similar
It may also be worth noting that I created different None Data Sources for each type, Task, User, List, and Tag. The id resolver for each type is using their respective None Data Source.
Is there a form to make loopback automatically validate input parameters in a remote method?
Let's assume we have the following definition of a remote method:
WebuserModel.remoteMethod('overLogin', {
description: "Performs a Webuser's login to the system",
accepts: [
{
arg: 'credentials', type: {
"username": { type: "string", required:true },
"password": { type: "string", required: true }
},
http: {source: 'body'},
required: true
},
],
returns: {arg: 'accesToken', type: "object", root: true},
http: {path: '/login', verb: 'post'}
}
I would here expect from loopback to perform validation of the input parameter on each request and to raise an error if the passed object does not comply with the defined schema (mandatory object with two mandatory properties).
Apparently it does not happen.
Any clue?
Disclaimer: I am a core developer of LoopBack and the author of argument validation in strong-remoting#3.x.
LoopBack does not support validation of nested object properties provided by the clients when invoking remote methods. Right now, we check only that the value is an object, see lib/types/object.js in strong-remoting.
In the upcoming LoopBack 4 version, we are planning to support full OpenAPI and/or JSON Schema validation for input arguments, see https://github.com/strongloop/loopback-next/issues/118
Based on the comments in that GitHub issue, it should be relatively easy to add JSONSchema-based validations to LoopBack 3.x too.