How to validate a POST request for postUserAction - validation

I get a problem with the validation of a new user request on my api.
I know there's a problem in my code but I cannot figure it out :
UserType
postUserAction
And I send via google Postman, this json :
{
"username":"Username",
"email":"example#mail.com",
"plainPassword":"SecretPassword",
"lastname":"Smith",
"firstname":"John",
"job_position":"CEO",
"phone":"+666133742",
"company_name":"Microtosh",
"website":"www.omgthatsaflippingspider.com",
"sector":"Food & Stuff",
"address":"12 st Overkill",
"city":"SinCity",
"zip_code":"W4224",
"country":"US",
"billing_infos_same_as_company":true,
"putf":"1",
"das":"Manchester United"
}
Now I seems to validate but I get an error :
Column 'password' cannot be null
When I look up the $form -- before $userManager->updateUser($user) -- I get this :
plainPassword:
{
-children:
{
-first:
{
-errors:
[
"fos_user.password.mismatch"
]
}
second: [ ]
}
}
Now first, why does it validate since it didn't find a match between password and confirmation ?
And am I doing the right thing, with the creation of a new user ? I don't understand what I am missing.

Just change the form type of password field to password instead of repeated and it should work ;)

Related

How to change priority of WTForms validators?

tl;dr: I need to change the order in which WTForms validators validate the user input. How do I do that?
Details:
Flask code:
class SampleForm(Form):
user_email = user_email_field
...
#api.route('/sample-route')
class ClassName(Resource):
#api.expect(sample_payload)
#api.marshal_with(sample_response)
def post(self):
form = SampleForm(formdata=MultiDict(api.payload))
if not form.validate():
return {"form_errors": form.errors}, 400
...
WTForms validation field:
user_email_field = EmailField('Email Address',[
validators.InputRequired(Errors.REQUIRED_FIELD),
validators.Length(min=5, max=256),
validators.Email(Errors.INVALID_EMAIL_ADDRESS),
])
Problem is, user_email is checked by validators in the wrong order. I send a request with the following body:
{
"user_email": ""
}
I get this response:
{
"form_errors": {
"user_email": [
"'' is too short"
]
}
}
As you see, despite being 2nd in the list of validators, validators.Length() kicks in before everything else.
If I comment it out in the validation field like that:
user_email_field = EmailField('Email Address',[
validators.InputRequired(Errors.REQUIRED_FIELD),
# validators.Length(min=5, max=256),
validators.Email(Errors.INVALID_EMAIL_ADDRESS),
])
then the exact same request will yield a desired response:
{
"errors": null,
"success": null,
"form_errors": {
"user_email": [
"REQUIRED_FIELD"
]
}
}
However, this is not a working solution because, of course, then eMail won't be checked for its length.
Question:
How do I change the priority of these validators? How do I make WTForms always check the user input with validators.InputRequired() FIRST and with validators.Length() SECOND and not the other way around?
As per your question:
You can use custom validators for that purpose. Then you can change the order of validation by if, elif, else logic within.
class Test(Form):
test_field = StringField('Test_Field')
submit = SubmitField()
def validate_test_field(self, test_field):
try:
if len(test_field.data) == 0:
raise wtforms.validators.ValidationError('Input is required for this field!')
elif len(test_field.data) not in range(5, 257):
raise wtforms.validators.ValidationError(f'Error in input length.')
except TypeError as e:
raise wtforms.validators.ValidationError('Input is required for this field!')
Check the documentation for custom validators here

Updating meta fields in Shopify with GrapQL

I've never used GraphQL before so I am really lacking knowledge on how to go about this. I'm wanting to update product meta fields on Shopify and it appears this is the only way. What I've done so far is really fumbling...
My JSON is:
{
"input": {
"id": "gid://shopify/Product/749521178847",
"metafields": [
{
"id": "gid://shopify/Metafield/2223333",
"value": "Training Grounds"
}
]
}
}
I've minified this to:
{"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
And am then using an HTTP request to:
https://MYSTORE.myshopify.com/api/2021-10/graphql.json?query={"input":{"id":"gid://shopify/Product/749521178847","metafields":[{"id":"gid://shopify/Metafield/2223333","value":"The Training Grounds"}]}}
I get the error:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I don't know if any of this is correct. If it is, I don't know if ?query= is the right variable to pass it through on.
I recommend you start using Postman, thunder client, or similar to write your graphql queries first, you will learn a lot about how graphql works and the error msgs will be a lot more useful.
To easily connect with Shopify on this stage, go to a store and create a private app, now you can use this for authenticating your API calls.
After that the Shopify graphql works on POST, you can't write your request on GET mode.
It needs to be a POST and you are missing type of operation mutation in this case and what it is.
Postman has https://www.postman.com/lively-moon-541169/workspace/purego-apis/example/16545848-bf0d1589-09b1-4ec6-ba63-a65a56b500eb examples of how to do the calls which can help you.
Also you can check GraphiQL app on shopify to test all the queries before making the programmatic queries
Updating an existing metafield:
mutation {
metafieldsSet(metafields: [
{namespace: "YOURNAMESPACE", ownerId: "gid://shopify/Customer/CUSTOMER_ID", type: "single_line_text_field", key: "YOURKEY", value: "THIS IS NEW VALUE"}
]) {
metafields {
key
value
}
userErrors {
field
message
}
}
}
Creating new metafield:
mutation {
customerUpdate(input: {
id: "gid://shopify/Customer/CUSTOMER_ID",
metafields: [
{key: "newkey", value: "some value", type: "single_line_text_field", namespace: "some namespace"},
]
}) {
userErrors {
field
message
}
}
}

Get complete GraphQL response using POST without specify field name in request [duplicate]

Assume you have a GraphQL type and it includes many fields.
How to query all the fields without writing down a long query that includes the names of all the fields?
For example, If I have these fields :
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'username' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'count' => [
'type' => Type::int(),
'description' => 'login count for the user'
]
];
}
To query all the fields usually the query is something like this:
FetchUsers{users(id:"2"){id,username,count}}
But I want a way to have the same results without writing all the fields, something like this:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Is there a way to do this in GraphQL ??
I'm using Folkloreatelier/laravel-graphql library.
Unfortunately what you'd like to do is not possible. GraphQL requires you to be explicit about specifying which fields you would like returned from your query.
Yes, you can do this using introspection. Make a GraphQL query like (for type UserType)
{
__type(name:"UserType") {
fields {
name
description
}
}
}
and you'll get a response like (actual field names will depend on your actual schema/type definition)
{
"data": {
"__type": {
"fields": [
{
"name": "id",
"description": ""
},
{
"name": "username",
"description": "Required. 150 characters or fewer. Letters, digits, and #/./+/-/_ only."
},
{
"name": "firstName",
"description": ""
},
{
"name": "lastName",
"description": ""
},
{
"name": "email",
"description": ""
},
( etc. etc. ...)
]
}
}
}
You can then read this list of fields in your client and dynamically build a second GraphQL query to get the values of these fields.
This relies on you knowing the name of the type that you want to get the fields for -- if you don't know the type, you could get all the types and fields together using introspection like
{
__schema {
types {
name
fields {
name
description
}
}
}
}
NOTE: This is the over-the-wire GraphQL data -- you're on your own to figure out how to read and write with your actual client. Your GraphQL javascript library may already employ introspection in some capacity. For example, the apollo codegen command uses introspection to generate types.
2022 Update
Since this answer was originally written, it is now a recommended security practice to TURN OFF introspection in production. Reference: Why you should disable GraphQL introspection in production.
For an environment where introspection is off in production, you could use it in development as a way to assist in creating a static query that was used in production; you wouldn't actually be able to create a query dynamically in production.
I guess the only way to do this is by utilizing reusable fragments:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
I faced this same issue when I needed to load location data that I had serialized into the database from the google places API. Generally I would want the whole thing so it works with maps but I didn't want to have to specify all of the fields every time.
I was working in Ruby so I can't give you the PHP implementation but the principle should be the same.
I defined a custom scalar type called JSON which just returns a literal JSON object.
The ruby implementation was like so (using graphql-ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Then I used it for our objects like so
field :location, Types::JsonType
I would use this very sparingly though, using it only where you know you always need the whole JSON object (as I did in my case). Otherwise it is defeating the object of GraphQL more generally speaking.
GraphQL query format was designed in order to allow:
Both query and result shape be exactly the same.
The server knows exactly the requested fields, thus the client downloads only essential data.
However, according to GraphQL documentation, you may create fragments in order to make selection sets more reusable:
# Only most used selection properties
fragment UserDetails on User {
id,
username
}
Then you could query all user details by:
FetchUsers {
users() {
...UserDetails
}
}
You can also add additional fields alongside your fragment:
FetchUserById($id: ID!) {
users(id: $id) {
...UserDetails
count
}
}
Package graphql-type-json supports custom-scalars type JSON.
Use it can show all the field of your json objects.
Here is the link of the example in ApolloGraphql Server.
https://www.apollographql.com/docs/apollo-server/schema/scalars-enums/#custom-scalars

404 error when post in Postman

I´m trying to send a POST request that is an Person object that contains a list of contacts.
But I don´t know if this is the correct syntax to send a list:
{
"name":"romulo",
"contacts" : [
{
"contact" : "3466577"
},
{
"contact" : "532423"
}
]
}
But keeps me returning a 404 error
what i´m doing wrong?
post method:
#PostMapping("/person")
public void addPerson(#Valid #RequestBody Person person) {
Person savedPerson = personRepository.save(person);
List<Contact> contacts = person.getContacts();
for (Contact contact1 : contacts) {
contactRepository.save(contact1);
}
}
HTTP 404 is returned when the server is unable to find method to match your exact request.
For the mentioned request have the url as http://<context>/requestpath with request method as POST.(http://localhost:8080/person)
Check the request body and all the fields should exactly match the Person object else it may return HTPP 400.
In My Case it was simple mistake and spend an hour for figuring it out that i had space at the end of my url.

Change User default validation in Loopback

I'm developping a Loopback application extending base User model to UserCode model where each user is identified by an email plus a code fields.
So that a user can register with the same email twice but with different code.
I've seen that in node_modules/loopback/common/models/user.js at line 691 there is:
UserModel.validatesUniquenessOf('email', {message: 'Email already exists'});
I want to delete this restriction/validation but without change loopback code, of course.
How can I do it?
Maybe in the boot script I can loop through all validation and delete this one?
Figured it out
In this case you need to remove the default validations set by the User model
common/models/userCode.js
module.exports = function(UserCode){
//Add this line and it will start receiving multiple email.
delete UserCode.validations.email;
}
Also you can play with the required:true|false property to make any default defined property required or not.
common/models/userCode.json
{
"name": "UserCode",
"base": "User",
"idInjection": true,
"properties": {
"password": {
"type": "string",
"required": true
},
....
....
}
The following code the accepted answer will remove ALL the email validations:
module.exports = function(UserCode){
//Add this line and it will start receiving multiple email.
delete UserCode.validations.email;
}
Instead be selective and do something like this:
module.exports = function(UserCode){
// remove ONLY email uniqueness validation
UserCode.validations.email = UserCode.validations.email.reduce((all, one) => {
if (one.validation !== 'uniqueness') {
all.push(one);
}
return all;
}, []);
}

Resources