How to use joi validator with strapi.js? - joi

I have worked a lot with joi with node's express and little with Hapi.js. And now I'm exploring the Strapi.js. Now I have marked that when I create a Content Type builder it gives me basic CRUD API's. Now I want to validate all request using joi. As strapi makes all routes in JSON file. So how could I use joi? I had search a lot but I'm not getting any solution on this.
I have found one solution like this.
{
"method": "POST",
"path": "/users",
"handler": "users.create",
"validate":{ <---------------- Hear I can validate my req
body:{
fname: Joi.string().required()
}
},
"config": {
"policies": []
}
}
Hear the issue is they used Joi but I have to define its package name but hear I have a JSON file so I'm not able to do like this.
Is there anyone has a solution to this?
Update
I have renamed the file as a router.json.
const router = require('koa-joi-router');
const Joi = router.Joi;
module.exports = {
"routes": [
{
"method": "POST",
"path": "/tests",
"validate":{
"body":{
"name":Joi.string().required()
}
},
"handler": "Test.create",
"config": {
"policies": []
}
},
]
}
Still Joi is not working.

OKay after having investigated on this topic, you will not be able to manage your validation in this way.
I suggest you to manage your validation layer with a middleware.
Use your route file with a JSON format (like the default one)
then in the config object you add the validation key that contains your validation schema. But you validation skema will be a string.
Here is an example:
{
"method": "POST",
"path": "/articles",
"handler": "Article.create",
"config": {
"policies": [],
"validate":{
"body":{
"name": "string.required"
}
}
}
},
Then you will have to follow the Middleware documentation 📚 to create you validation middelware.
In this middleware you will be able to get the requested url with ctx.request.url and with a .find() in strapi.config.routes you will be able to find your validation configs.
Then you will have to use the JSON validation config you set and recompose the Joi validation on your request body - ctx.request.body

For the routes.json file, you can rename it routes.js and add a module.exports and your json file become an js file.
{
"routes": [
{
"method": "GET",
...
-
module.exports = {
"routes": [
{
"method": "GET",
But it's only a part of the response.

Related

Using Cloud Firestore REST API how to send data using http package with http.post() method

I have a collection called "txt" and would like to create a new document under that, with an auto-generated document Id, with the field 'test' and its value as 'title'.
I have the following code in Flutter which does not work:
Future<http.Response> _post() {
String url =
'https://firestore.googleapis.com/v1/projects/onebear-webapp/databases/(default)/documents/txt?key=AIzxSyAllNuEbN40DEvBPIQkcLIWn00c9TYWqY';
return http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'test': 'title',
}),
);
}
And it keeps giving errors as per below:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"test\" at 'document': Cannot find field.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "document",
"description": "Invalid JSON payload received. Unknown name \"test\" at 'document': Cannot find field."
}
]
}
]
}
}
I cant seem to figure out the error message and what the errors "Invalid JSON payload received." or "fieldViolations" mean - even though I'm encoding with jsonEncode.
Please any help or guidance on this very much appreciated. Thx!
I would suggest you have a look at these similar posts (1)(2) with other users running into similar issues.
If you want to update multiple fields and values, have you managed to try to specify each one separately? For example, your request body should look something like this:
{
"fields": {
"field": {
"stringValue": "Value1"
},
"Field2": {
"stringValue": "Value2"
}
}
}
Since it seems you are attempting to set up a string Hash. I would suggest you have a look at this documentation on map's field as it follows a different structure, for example: An object containing a list of "key": value pairs.
map (key: string, value: object (Value))
{ "name": "wrench", "mass": "1.3kg", "count": "3" }
Since jsonEncode looks to be a functionality specific to Flutter development, I would recommend bringing your question to the Flutter developers team as the they would be more knowledgeable of this implementation method.

Validation fails but error messages missing

I'm attempting to validate a JSON file against a specific schema using this code:
string data = File.ReadAllText("../../../testFiles/create.json");
string schemaText = File.ReadAllText("../../../schemas/request-payload.schema.json");
var serializer = new JsonSerializer();
var json = JsonValue.Parse(data);
var schema = serializer.Deserialize<JsonSchema>(JsonValue.Parse(schemaText));
var result = schema.Validate(json);
Assert.IsTrue(result.IsValid);
The assertions fails because result.IsValid is false (which is correct - there is an intentional error in my JSON) but there is no indication where the error is happening:
My schema does have sub-schemas in the definition section. Could that have anything to do with it? Do I need to set some property to see that error information?
Update: Added schema and test JSON
My original schema was several hundred lines long, but I pared it down to a subset which still has the problem. Here is the schema:
{
"$schema": "https://json-schema.org/draft/2019-09/schema#",
"$id": "request-payload.schema.json",
"type": "object",
"propertyNames": { "enum": ["template" ] },
"required": ["template" ],
"properties": {
"isPrivate": { "type": "boolean" },
"template": {
"type": "string",
"enum": [ "TemplateA", "TemplateB" ]}},
"oneOf": [
{
"if": {
"properties": { "template": { "const": "TemplateB" }}},
"then": { "required": [ "isPrivate" ] }}]
}
And here is a test JSON object:
{
"template": "TemplateA"
}
The above JSON validates fine. Switch the value to TemplateB and the JSON fails validation (because isPrivate is missing and it is required for TemplateB), but the result doesn't contain any information about why it failed.
The code I'm using to run the validation test is listed above
The issue is likely that you haven't set the output format. The default format is flag which means that you'll only get a true/false of whether the value passed.
To get more details, you'll need to use a different format setting. You can do this via the schema options.
For example:
JsonSchemaOptions.OutputFormat = SchemaValidationOutputFormat.Detailed;
The available options are here.

IBM Function returning weird data back when calling REST API Endpoint

I have an IBM Cloud Function like:
return {'body': csv_output.getvalue(),
'headers': {'Content-Type': 'text/csv',
'Content-Disposition': 'attachment;filename=dat.csv'}}
When called a public API endpoint it returns a csv file with right data.
But when I use postman to make a REST API endpoint call I get a weird result like:
{
"annotations": [
{
"key": "exec",
"value": "python:3.7"
},
{
"key": "web-export",
"value": true
},
{
"key": "final",
"value": true
},
{
"key": "raw-http",
"value": true
}
],
"exec": {
"kind": "python:3.7",
"code": "import
Can someone please tell me what am I doing wrong? Seems like I am getting code back rather than invoking the function.
It looks like you are using POSTMAN to return actions details (via the platform API), rather than invoking as a web action.
The HTTP endpoint for an action is https://{APIHOST}/api/v1/namespaces/_/actions/<ACTION_NAME>.
The HTTP endpoint for invoking an action as a web action is https://{APIHOST}/api/v1/web/{QUALIFIED ACTION NAME}.{EXT}.

Can not create new layer (featuretype) in GeoServer using REST API

So I just used 2 working days trying to figure this out. We are automatic rendering process for maps. All the data is given in SQL base and my job is to write "wrapper" so we can implement this in our in-house framework. I managed all but one needed requests.
That request is POST featuretype since this is a way of creating a layer that can later be rendered.
I have all requests saved in postman for pre-testing on example data given by geoserver itself. I can't even get response with status code 201 and always get 500 internal server error. This status is described as possible syntax error in sytax. But I actually just copied and pasted exampled and used geoserver provided data.
This is the requst: http://127.0.0.1:8080/geoserver/rest/workspaces/tiger/datastores/nyc/featuretypes
and its body:
{
"name": "poi",
"nativeName": "poi",
"namespace": {
"name": "tiger",
"href": "http://localhost:8080/geoserver/rest/namespaces/tiger.json"
},
"title": "Manhattan (NY) points of interest",
"abstract": "Points of interest in New York, New York (on Manhattan). One of the attributes contains the name of a file with a picture of the point of interest.",
"keywords": {
"string": [
"poi",
"Manhattan",
"DS_poi",
"points_of_interest",
"sampleKeyword\\#language=ab\\;",
"area of effect\\#language=bg\\;\\#vocabulary=technical\\;",
"Привет\\#language=ru\\;\\#vocabulary=friendly\\;"
]
},
"metadataLinks": {
"metadataLink": [
{
"type": "text/plain",
"metadataType": "FGDC",
"content": "www.google.com"
}
]
},
"dataLinks": {
"org.geoserver.catalog.impl.DataLinkInfoImpl": [
{
"type": "text/plain",
"content": "http://www.google.com"
}
]
},
"nativeCRS": "GEOGCS[\"WGS 84\", \n DATUM[\"World Geodetic System 1984\", \n SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]], \n AUTHORITY[\"EPSG\",\"6326\"]], \n PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], \n UNIT[\"degree\", 0.017453292519943295], \n AXIS[\"Geodetic longitude\", EAST], \n AXIS[\"Geodetic latitude\", NORTH], \n AUTHORITY[\"EPSG\",\"4326\"]]",
"srs": "EPSG:4326",
"nativeBoundingBox": {
"minx": -74.0118315772888,
"maxx": -74.00153046439813,
"miny": 40.70754683896324,
"maxy": 40.719885123828675,
"crs": "EPSG:4326"
},
"latLonBoundingBox": {
"minx": -74.0118315772888,
"maxx": -74.00857344353275,
"miny": 40.70754683896324,
"maxy": 40.711945649065406,
"crs": "EPSG:4326"
},
"projectionPolicy": "REPROJECT_TO_DECLARED",
"enabled": true,
"metadata": {
"entry": [
{
"#key": "kml.regionateStrategy",
"$": "external-sorting"
},
{
"#key": "kml.regionateFeatureLimit",
"$": "15"
},
{
"#key": "cacheAgeMax",
"$": "3000"
},
{
"#key": "cachingEnabled",
"$": "true"
},
{
"#key": "kml.regionateAttribute",
"$": "NAME"
},
{
"#key": "indexingEnabled",
"$": "false"
},
{
"#key": "dirName",
"$": "DS_poi_poi"
}
]
},
"store": {
"#class": "dataStore",
"name": "tiger:nyc",
"href": "http://localhost:8080/geoserver/rest/workspaces/tiger/datastores/nyc.json"
},
"cqlFilter": "INCLUDE",
"maxFeatures": 100,
"numDecimals": 6,
"responseSRS": {
"string": [
4326
]
},
"overridingServiceSRS": true,
"skipNumberMatched": true,
"circularArcPresent": true,
"linearizationTolerance": 10,
"attributes": {
"attribute": [
{
"name": "the_geom",
"minOccurs": 0,
"maxOccurs": 1,
"nillable": true,
"binding": "com.vividsolutions.jts.geom.Point"
},
{},
{},
{}
]
}
}
So it is example case and I can't get any useful response from the server. I get the code 500 with body name (the first item in json). Similarly I get same code with body FeatureTypeInfo when trying with xml body(first tag).
I already tried the request in new instance of geoserver in Docker (changed the port) and still no success.
I check if datastore, workspace is available and that layer "poi" doesn't yet exists.
Here are also some logs of request (similar for xml body):
2018-08-03 07:35:02,198 ERROR [geoserver.rest] -
com.thoughtworks.xstream.mapper.CannotResolveClassException: name at
com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:79)
at .....
Does anyone know the solution to this and got it working. I am using GeoServer 2.13.1
So i was still looking for the answer and using this post (https://gis.stackexchange.com/questions/12970/create-a-layer-in-geoserver-using-rest) got to the right content to POST featureType and hence creating a layer in GeoServer.
The documentation is off in REST API docs.
Using above link I found out that when using JSON there is a missing insertion in JSON. For API to work here we need to add:
{featureType:
name: "...",
nativeName: "...",
.
.
.}
So that it doesn't start with "name" attribute but it is contained in "featureType".
I didn't try that for XML also but I guess it could be similar.
Hope this helps someone out there struggling like I did.
Blaz is correct here, you need an outer object of FeatureType and then an inner object with your config. So;
{
"featureType": {
"name": "layer",
"nativeName": "poi",
"your config": "stuff"
}
I find though that using a post request I get very little if any response and its not obvious if the layer creation worked. But you can call http://IP:8080/geoserver/rest/layers.json to check if your new layer is there.
It costs me a lot of time to create FeatureTypes using REST API. Use Json like this really works:
{
"featureType": {
"name": "layer",
"nativeName": "poi"
"otherProperties...":"values..."
}
And use Json below to create Workspace:
{
"workspace": {
"name": "test_workspace"
}
}
The REST API is out of date now. That's disappointing. Is there anyone knows how to get the lastest REST API document?

RIPE: How to lookup IP Address using REST API

As per the RIPE REST API documentation, one needs to specify the requests in the following format:
http://rest.db.ripe.net/{source}/{objecttype}/{key}
So I am assuming that looking up an IP address will be like this:
http://rest.db.ripe.net/ripe/inetnum/193.0.6.142.json
However, the response I get is :
{
"link": {
"type": "locator",
"href": "http://rest.db.ripe.net/ripe/inetnum/193.0.6.142"
},
"errormessages": {
"errormessage": [
{
"severity": "Error",
"text": "ERROR:101: no entries found\n\nNo entries found in source %s.\n",
"args": [
{
"value": "RIPE"
}
]
}
]
},
"terms-and-conditions": {
"type": "locator",
"href": "http://www.ripe.net/db/support/db-terms-conditions.pdf"
}
}
What am I doing wrong ?
You are using the wrong URL, the correct URL for your example query would be:
http://rest.db.ripe.net/search.json?query-string=193.0.0.0/21&flags=no-filtering
Or this for XML:
http://rest.db.ripe.net/search.xml?query-string=193.0.0.0/21&flags=no-filtering
Looks like https://rest.db.ripe.net/search.json?query-string=193.0.6.142 is the correct link to use. This seems to return back the same data as I see on ripe.net
You didn't write {key} part right. Inetnum objects on RIPE have "193.0.0.0 - 193.0.7.255" type of key. You must make a request like this:
https://rest.db.ripe.net/ripe/inetnum/91.123.16.0 - 91.123.31.255