Unpredictable request payload structure but Need to create user from it - laravel

My system can get request from multiple sites and request payload will have user details. However, the structure or format of payload can be different and not known. My system shall extract out the details from it and create user in to my system.
e.g. one request source will send first name as fname='abc' and other might send it as first_name='abc'.
I have to implement it in PHP laravel

This would resolve your issue:
$name = null;
if(!empty($data['fname'])) {
$name = $data['fname'];
} elseif(!empty($data['first_name']) {
$name = $data['first_name'];
}
Then you can execute validation, autofill and things like that to create or modify your user model.

Related

create and update endpoints using PUT method with an identifier generated by me

How to create and update a resource using PUT method and 2 different endpoints? The identifier is generated by me in the path. (cnp is the identifier)
Create an artist
PUT /api/artists/cnp for example /api/artists/112
Result:
{
"cnp":"112",
"name":"John"
}
Update
PUT /api/artists/cnp for example /api/artists/112
The request should be like this, right?
{
"cnp":"112",
"name":"John Updated"
}
And the response should be the same.
If I try to update the resource, the endpoint for creating a resource will be triggered and I'll receive an error because the artist with this cnp already exists.
Is something like this possible? Or should I use POST? I read that I should use POST when the identifier is generated at the server level. In this case, the identifier is generated by me in the path.
How to manage this?

Verify graphql query

I'm building a simple platform using graphql as api gateway and a frontend that send some queries to this api, I'm blocked on how can I validate a query before run it to avoid malicious query to be ran. I was thinking to use persistgraphql but I just noticed that is now archived so I'm not sure if it's a good idea to use it, the second problem is that the api and the frontend are in 2 different repo so I didn't find yet a solution to whitelisting the query in the frontend and use this whitelist in the api...what's the best solution to whitelist a query with graphql?
If your concern is limiting access to certain fields based on who is making the request, then you should implement some kind of authorization strategy. You can populate the context with information about the logged in user and then use this information inside your resolvers for the fields you want to protect to determine whether the value of the field should be returned or not.
const resolvers = {
User: {
somePrivateField: (user, args, ctx) => {
// Make sure the request is from a logged in user and the user making the
// request is the same as the requested user OR the user is an admin
if (ctx.user && ( ctx.user.id === user.id || ctx.user.isAdmin )) {
return user.somePrivateField
}
// throw an error or just return null or undefined to resolve the field to
// null in the event authorization fails
}
}
}
More sophisticated strategies are possible using directives or existing libraries like graphql-shield.
Of course, certain fields that may exist on your database model -- like passwords -- should probably never be exposed in your API in the first place.

Laravel download pdf file stored in separate Laravel app

I have 2 Laravel(5.8) apps. One is a user application, the other is more of an API.
The Api has pdfs stored in the storage directory, I need to be able to allow a user to download the pdfs in the other application.
Really got no clue how to send the file over from app to the other.
The user app makes an api to the api with relevant file ids and things (fine), just can't work out how to send the file back, and then download it on the other end.
Tried things like return response()->stream($pdf) on the api and return response()->download($responeFromApiCall) and loads of other things but really getting nowhere fast.
Any advice welcome.
The laravel code you posted is basically correct, you can use one of stream(), download() or file() helper to serve a file.
file()
Serve a file using a binary response, the most straightforward solution.
// optional headers
$headers = [];
return response()->file(storage_path('myfile.zip'), $optionalHeaders);
You can also use your own absolute file path instead of the storage_path helper.
download()
The download helper is similar to file(), but it also sets a Content-Disposition header which will result in a download-popup if you retrieve the file using your browser.
$location = storage_path('myfiles/invoice_document.pdf');
// Optional: serve the file under a different filename:
$filename = 'mycustomfilename.pdf';
// optional headers
$headers = [];
return response()->download($location, $filename, $headers);
stream()
The stream() helper is a bit more complex and results in reading and serving a file in chunks. This can be used for situations where the filesize is unknown (like passing through another incoming stream from an API). It results in a Transfer-Encoding: chunked header which indicates that the data stream is divided into a series of non-overlapping chunks:
// optional status code
$status = 200;
// optional headers
$headers = [];
// The stream helper requires a callback:
return response()->stream(function() {
// Load a file from storage.
$stream = Storage::readStream('somebigfile.zip');
fpassthru($stream);
if(is_resource($stream)) {
fclose($stream);
}
}, $status, $headers);
Note: Storage::readStream takes the default storage disk as defined in config/filesystems.php. You can change disks using Storage::disk('aws')->readStream(...).
Retrieving your served file
Say your file is served under GET example.com/file, then another application can retrieve it with curl (assuming PHP). A popular wrapper for this would be Guzzle:
$client = new \GuzzleHttp\Client();
$file_path = __DIR__ . '/received_file.pdf';
$response = $client->get('http://example.com/file', ['sink' => $file_path]);
You can derive the filename and extension from the request itself by the way.
If your frontend is javascript, then you can retrieve the file as well but this another component which I dont have one simple example for.
So if I understand correctly you have two systems: user app and api. You want to serve a pdf from user app to the actual user. The user app does a call to api, which works fine. Your issue is converting the response of the api to a response which you can serve from your user app, correct?
In that case I'd say you want to proxy the response from the api via the user app to the user. I don't know what the connection between the user app and the api is, but if you use Guzzle you could look at this answer I posted before.
Here are the steps you should follow to get the PDF:
Make an API call using AJAX ( you are probably already doing it ) from your public site ( User site ) to the API server, with file ID.
API server fetches the PDF, copy it to the public/users/ directory, generate the URL of that PDF file.
Send the URL as a response back to the User site. Using JS add a button/ link in the DOM, to that PDF file.
Example:
jQuery.post(ajaxurl, data, function(response) {
var responseData = JSON.parse(response);
var result = responseData.result;
var pdf_path = responseData.pdf_path;
$(".nametag-loader").remove();
$(".pdf-download-wrapper").append("<a class='download-link' href='"+ pdf_path +"' target='_blank'>Download</a>");
});

Writing data to model from POST request (Odoo 9.0)

I have the following model:
class LibraryBook(models.Model):
_name = 'library.book'
name = fields.Char('Title', required=True)
date_release = fields.Date("Release Date")
author_ids = fields.Many2many("res.partner", string="Authors")
I'm new to Odoo and trying to understand the basics of how to save data to my model from a POST request like the following
curl -i -X POST --data "name=Odoo%20-%20Much%20Mystery,%20Wow&author_id=Doge" http://0.0.0.0:8069/test
I found a way doing this by setting the csrf parameter in my controller to false like so:
[...]
#http.route('/test', type='http', auth='public',methods=['POST'], website=True, csrf=False)
def test(self, **kwargs):
record = request.env['library.book'].sudo()
record.create(kwargs)
I'm wondering now if there is a way to avoid setting csrf=false since I've read that it's a bad idea to do so in general. Also, what would I need to get rid of that .sudo()? Not setting csrf=false leads to a 400 BAD REQUEST with Invalid CSRF token. Removing sudo() leads to a 500 INTERNAL SERVER ERROR. In Odoo Development Cookbook it says in one example with auth='none'
Lack of a user is also why we have to sudo() all our calls to model methods in the example code
Assuming I would expect a POST request from an API, is it possible to associate it with a user so I don't have to sudo()?
I would very much appreciate any clarification on this.
UPDATE
So I just found this (line 817):
if the form is accessed by an external third party (e.g. REST API endpoint, payment gateway callback) you will need to disable CSRF
protection (and implement your own protection if necessary) by
passing the csrf=False parameter to the route decorator.
which I guess leaves only one question open, regarding sudo.
SUDO()
creates a new environment with the provided user set, uses the administrator if none is provided (to bypass access rights/rules in safe contexts), returns a copy of the recordset it is called on using the new environment:
Odoo does not allow public users to create, update, delete a record.
If we want to create a record from the public users then we need to create a record with the sudo().
Create record object as administrator
request.env['library.book'].sudo().create(vals)
I hope this may help you.
for more information you can navigate to following links :
https://www.odoo.com/documentation/9.0/reference/orm.html
Thanks

How to use Qooxdoo's Stores to request an ajax response with a POST?

In the tutorial enter link description here they only show this:
var url = "http://api.twitter.com/1/statuses/public_timeline.json";
this.__store = new qx.data.store.Jsonp(url, null, "callback");
But I would need to communicate with my own server, so I've made some changes: (url and Jsonp to Json)
var url = "http://127.0.0.1:8000/";
this.__store = new qx.data.store.Json(url);
But I would need to be able to send some information to the server when the store make the request like:
{serviceToUseOnServer: 'articles', argument1: 'xxx'}
This is like a POST request, but I don't really know how to send that data to the server using qooxdoo's Store models. Please don't tell me to use GET and encode all that data in an url.
You got the possibility to configure the request object used to send the data. Just add a delegate to the store and implement the configureRequest method [1].
[1] http://demo.qooxdoo.org/current/apiviewer/#qx.data.store.IStoreDelegate~configureRequest

Resources