How to send an Enum variant as integer, not string in Angular - json

I'm using Angular 11, and have to post some data to a backend service. Here's the data I need to post:
interface User {
id: Guid; // Guid is just a type alias to string, with some validation checks
email: string;
role: Role
}
enum Role {
User = 0,
Administrator = 1
}
Now the problem comes when I try to post to my backend using the default HttpClient from Angular. Here's the code:
createOrUpdateUser(user: User): Observable<User> {
return this.http.post<User>(`${this.baseUrl}/${this.userUrl}/${this.userCreateOrUpdate}`, user);
}
This works fine, but the JSON sent is "wrong". It sends this:
{
"id": "2abe50d6-4c81-4ace-ad95-c8182d4384a3",
"email": "someEmail#example.org",
"role": "0"
}
Where as the backend is expecting this
{
"id": "2abe50d6-4c81-4ace-ad95-c8182d4384a3",
"email": "someEmail#example.org",
"role": 0
}
The difference being the backend expects "role": 0, but Angular sends "role": "0". How can I make Angular send "role": 0?

This is may not be a good idea. But it will be helped you.
createOrUpdateUser(user: User): Observable<User> {
user.role = Number(user.role);
return this.http.post<User>(`${this.baseUrl}/${this.userUrl}/${this.userCreateOrUpdate}`, user);
}

you can use + to make it as number before sending it api user.role = +user.role. Some where else you are assigning value of role in user object which is making it as a string. its not enum issue.

TypeScript is compiled to plain old javascript code, where type enforcement is more or less non-existent. This means that, in theory, you might be assigning a string to your User model.
There can be multiple reason - i.e. you receive it this way from backend, assign it to a variable and re-send later without modifying the value. Or, for example, the User comes from a FormGroup which passes the value as a string. You can even have TypeScript code omit type checks:
let user: User = {
id: '2abe50d6-4c81-4ace-ad95-c8182d4384a3',
email: 'someEmail#example.org',
role: Role.Administrator
}
user['role'] = "2" // Not a valid enumeration
So, to instead of going for some strange workaround like using +user.role in the mapping, perhaps look for where / how the value is assigned in the first place.

As it is not really clear if it gets sent from angular or received from server as string we can debug a bit to find the right place to investigate (angular frontend or backend)
You can investigate by logging console.log(typeof user.role)and see what it returns. Also have a look at what gets sent from frontend to backend using Chrome Devtools -> Network -> click on the request -> and scroll down on first tab to see what data gets sent.
What might happen is frontend to send the right data type (integer) for the role and backend interpret it as string.
In this case you could just use parseInt(user.role) in the backend as a fallback or investigate how to get the integer type on the backend body request instead of string.

Related

Unable to retrieve Claims in either the id_token or userinfo requests

I'm trying to retrieve the CIF and also the Tax Id of the logged in user following your documentation. When trying to request that information via additional claims via the Consumer API, with the scope of &scope=openid I'm supplying the below claims parameter in my authorization request. Making sure that the External App is configured with the claims access in the Banno portal, I don't get anything in my response id_token. I've also attempted to switch this to the userinfo leveraging the opid/me resource which just returns the user "sub".
Claims readable:
claims={"id_token":{"https://api.banno.com/consumer/claim/customer_identifier":null}}
Here it is url encoded:
claims==%7B%22id_token%22%3A%7B%22https%3A%2F%2Fapi.banno.com%2Fconsumer%2Fclaim%2Fcustomer_identifier%22%3Anull%7D%7D
decoded jwt id_token repsonse:
"id_token": {
"header": {
"alg": "RS256",
"typ": "JWT",
"kid": "sig-rs-0"
},
"body": {
"sub": "sub uuid",
"at_hash": "ShHf2gRtROCBdE-j_5YZkw",
"aud": "aud uuid",
"exp": 1668092577,
"iat": 1668088977,
"iss": "https://api.banno.com/a/consumer/api/v0/oidc"
}
}
using the same example switching the claims key to "userinfo" and making a request to .../a/consumer/api/v0/oidc/me I only get this response:
UserInfo Response:
{"sub":"sub uuid"}
In either scenario, I'm expecting the following example to be in the response:
"https://api.banno.com/consumer/claim/customer_identifier": "AAA1234",
However I don't get anything no matter what I do. What am I missing here?
It looks like there is an extra = in the encoded version. If I take what you've posted in the question, claims==%7B%22id_token%22%3A%7B%22https%3A%2F%2Fapi.banno.com%2Fconsumer%2Fclaim%2Fcustomer_identifier%22%3Anull%7D%7D and decode it, I get claims=={"id_token":{"https://api.banno.com/consumer/claim/customer_identifier":null}}, which has an extra = next to the claims parameter name.
That seems to have the effect of the name of the claim not matching up with what is expected, therefore that claim's value is not included in the Identity Token (and isn't available from the UserInfo endpoint).
The Claims in the Identity Token guide will be helpful to review.

Azure Logic App - Parse JSON with dynamic key/name

just want to know if and how I can parse a HTTP response with a dynamic name in a JSON?
I used the Azure Management API to receive the managed identities (system- and user assigned managed identities) to receive all managed identities.
With a foreach I am iterating the results.
If a resource has a system assigned managed identity and user assigned managed identity, the response looks like this:
{
"principalId": "<principalId1>",
"tenantId": "<tenantId>",
"type": "SystemAssigned, UserAssigned",
"userAssignedIdentities": {
"/subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<userAssignedIdentitiesName>": {
"principalId": "<principalId2>",
"clientId": "<clientId>"
}
}
}
Now, I would like to get the <principalId2>.
Unfortunately, the Name of the object is dynamic related to the scope of the resource /subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<userAssignedIdentitiesName>.
How can I parse the JSON to receive the needed <principalId2>?
For all other responses I can easily use the Data operations Parse JSON with the payload I inserted from the HTTP response.
Is there a way to use a wildcard? Otherwise, could I somehow just select the first object of userAssignedIdentities to receive the needed value?
Ok, this should work for you. This is the flow I tested with ...
Initialise JSON
Your JSON as a string, how you do that in your solution may differ slightly.
Initialize XPath Result
Defined as an Array and the expression is ...
xpath(xml(json(concat('{ root: ', replace(variables('JSON'), 'PrincipalId', 'principalId'), '}'))), '(//principalId)[2]')
Initialize Result
A bit more work again but defined as a String and the expression is ...
array(xpath(xml(base64ToString(variables('XPath Result')[0]?['$content'])), '//text()'))[0]
The end result should be your value ...

how to pass object in post api to create account in flutter

I have created a login form with email, password a login button. I am new to flutter, dart and web.
How do I integrate the JSON Restfull API for Login and Signup, by using JSON as an object.
Assuming you're completely new at Flutter and dart, there are a few steps to complete a RESTful API call.
At first, you'll need to provide a dependency from pub.dev named http.
After adding the dependency in pubspec.yaml file, go to the terminal, and run the command pub get.
Now, in your login form, I'm assuming you're trying to post a username and a password to a certain endpoint.
Let's create a separate file named networking_helper.dart just to keep everything of RESTful API in a well-mannered structure. You can keep your API implementation in your FORM screen, but I will strongly recommend not mixing UI code with backend code.
Now, create a class in the networking_helper.dart file to bind all API methods. Create a method that will contain all your API-related code with the login endpoint. For example:
class NetworkingHelper{
Future<bool> login(String email, String password) async {
//api implementation will be here
}
}
Now, look closely here, here I've created a class named NetworkingHelper to encapsulate my API methods. Inside the NetworkingHelper class there is a method named login. The login method requires some parameters based on its need. The login method is declared as async, to execute the job in the background.
Let's prepare some data that will be provided to complete the API call.
Assuming you will be using a POST method to execute your login FORM's data, let's declare a Map of the String key and dynamic value like this:
final Map<String, String> bodyParams = {
"username": username,
"password": password,
"grant_type": "password",
};
Don't panic yet about why I choose to use "username", "password" and "grant_type" keys. My login endpoints require these values. Communicate with your API developer about their needs and replace your required keys with the above-mentioned keys.
To establish an HTTP connection with your required data and to wait for a response, follow this step:
final Response response = await post(Uri.parse(<url>), body: bodyParams);
Typically asynchronous method returns a value with delay, so we have to wait until it finishes the job. So we used the await key to indicate the waiting period.
After that, it's fairly simple. Just implement few if/else based on your needs to ensure your data is valid and HTTP call was successful. Example:
if (response.statusCode == 200) {
return true;
} else {
return false;
}
Remember the method's return type declared above? What was it?
It was Future<bool?>. Let's break it down too. Let's start with the impression. Our return type is a boolean value that will be provided in the future because our method was declared as async. Make sense!!!
This is why we are returning true or false after we finished our API call waiting phase.
To give the complete structure of the API call, here is the complete code:
class NetworkingHelper{
Future<bool> login(String email, String password) async {
final Map<String, String> bodyParams = {
"username": username,
"password": password,
"grant_type": "password",
};
final Response response = await post(Uri.parse(<url>), body: bodyParams);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}
Hope that will help you a bit. Happy coding :D
This is Very Easy Example.
I was created already in my github account.
Please try it: https://github.com/JayswalViraj/Flutter-Login-With-Rest-API
Note: Login and registration both are working process same. Only you need change api url for registration process. Login api url to registration api url.

Response custom error when key not satisfies the exact value in couchbase view

I have a document like -
{
"fullUserName": "xxyz",
"userFirstName": "xx",
"userLastName": "xx",
"primaryRole": "xy",
"actualRole": "rrr",
"userId": "abcd1234",
"password":"c28f5c7cb675d41c7763ab0c42d",
"type":"login",
"channels":"*"
}
and view -
function (doc, meta) {
if(doc.userId,doc.password,doc.type){
emit([doc.userId,doc.password,doc.type],doc);
}
}
When the key matches with the docment's property it return the document otherwise it return empty JSON like -
{"total_rows":2,"rows":[
]
}
Now I want to response the error message in JSON format when the key does not match for example-
{
"Error-Code":"400",
"Error-Msg":"user id and password does not match"
}
Is there any way to do so,Please correct if I am moving in the wrong direction.
Thanks in advance.
You shouldn't directly expose the view query result to your users but interpret it instead.
So make a view request, look at the response and do the business logic of checking there. For example:
"if result is empty it can only be because the user is unknown or the password hash didn't match the user, so return a business-specific error message, otherwise carry on with login"
There's no way you can change the behavior and response format of the server, and that doesn't make much sense to do so anyway. This is the API and contract of how you interact with the server. You should add your own business logic in a layer in between.

Sencha Touch's proxy's reader's rootProperty and Parse.com's REST API response

My backend is Parse.com's REST API, and parse send me back a results object that looks like:
{
...fields...
}
when there is only object, meaning any time there is a create, a read or an update to one record. When I GET a collection of objects from Parse, it sends out a results object that looks like:
{
results: [
{
...fields...
}
]
}
In ST, when I have my proxy's reader's rootProperty set to: 'results', my reader isn't able to read the record Parse sends on a create or an update and therefore the local record doesn't get synced with the one the server sent.
When I have my reader's rootProperty set to: '', my local record gets synced with the one that Parse sent, but now my list, which takes a store, isn't displaying the list of records, because Parse sends that with a "results" node.
I tried using setRootProperty, but despite confirming that the reader's root property just before calling save() on a record is in fact: '', the local record doesn't sync with Parse's response. As soon as I remove the logic that does real time changes to root property, it starts working again.
What is the suggested way of handling this situation? Any help is much appreciated! Thanks!
So you have one store with a proxy that has a certain rootProperty but you olso have 2 type of response, single object or an array of objects inside results. If it is so, definitly your proxy is able to read only one type of response.
Some solutions:
-if you can operate on server make sure you send always an array of results whether the response contains none, one or many results.
-implement a custom reader (this is what i did when i had to manage different responses and make some changes on data in the meanwhile)
Ext.define('MyApp.store.MyStore',{
extend:'Ext.data.Store',
model:'MyApp.model.MyModel',
proxy: {
type:'jsonp',
url:'#'
},
autoLoad:false,
loadSolr:function(PARAMS){
this.groupField = groupField;
Ext.data.JsonP.request({
scope:this,
url: 'http://myserver.com',
callbackKey: 'json.wrf',
params: {
PARAMS
},
success: function(response) {
// handle your response here
var records = [];
Ext.each(response.results, function(record){
records.push({
field1: record.field1,
field2: record.field2
});
});
//load your data into store
this.loadData(records);
}
});
}
});
Hope it helps, post some code if i misunderstood something