Laravel Yajra datatables action button with csrf still throws 419 - laravel

I am using Yajra Datatables for Laravel to show a file list with post button actions.
I have this download button with the post method in order to check authorization whether the user is allowed to download that current file or not.
I have inspected the page and I do see the CSRF token. However, Laravel still throws 419 error.
Here is a piece of the controller code where I am generating a post button inside a Form with its CSRF token:
return DataTables::of($mediaItems)
//...
//ACTION BUTTONS
->addColumn('action',function (Media $file){
$button = '<form method="post" action="'.route('download.file',['media'=>$file]).'">
<meta name="csrf-token" content="'.csrf_token().'">
<button type="submit" name="download" class="btn btn-info" title="Download file"><i class="fas fa-file-download"></i></button>
</form> ';
return $button;
})
->toJson();
And right at the web browser's inspect element on the view, this is what I see:
<form method="post" action="http://myApp.local/file/download/z271dd4u-b0a2-44f6-a0a5-cmxd33de3e15">
<meta name="csrf-token" content="O02W6Fu9BoW1futzAL06BbFmDfsS8lgmmx4Vd05A">
<button type="submit" name="download" class="btn btn-info" title="Download"><i class="fas fa-file-download"></i></button>
</form>
When I click on the download button, why do I still get the 419 page expired error?

you have to pass csrf token as value. when you use #csrf in a form and inspect the form, you will find out that, it generates a hidden input field with name _token and the value is csrf token. you can't pass value with request using meta tag. so instead use the hidden input field.
<input type="hidden" name="_token" value=" '.csrf_token().' ">

Related

Cannot get id of subscription in request

I'm trying to get the id of the selected subscription and pass it to the controller, but for some reason when I dd() or print_r() the id in the controller, it returns the same id regardless of which subscription I click.
Regardless if i click the first '+' button or the second one it always returns the same id when I print_r() it.
Array ( [_token] => iFimNDCv0q4rq7OmmUWGN8SGr2Bq0brsiRMLIzBD [subscription] => 2 )
Even when I click the first one, which should have '1' as the id, it still returns '2'.
This is my route for it in web.php
Route::post('/transaction/store', 'TransactionController#store')->name('transaction.store');
This is the function in the controller
public function store(Request $request)
{
// continue here
print_r($request->input());
}
And this is the form tag that's responsible for send the id (which is inside a foreach statement in blade)
<form id="batch" action="{{route('transaction.store')}}" method="POST">
#csrf
<input type="hidden" name="subscription" value="{{$subscription->id}}" form="batch">
<button type="submit" class="btn btn-sm btn-outline-dark" form="batch">+</button>
</form>
Thanks very much for any help!
I just had to make the form id dynamic!
<form id="batch-{{$subscription->id}}" action="{{route('transaction.store')}}" method="POST">
#csrf
<input type="hidden" name="subscription" value="{{$subscription->id}}" form="batch-{{$subscription->id}}">
<button type="submit" class="btn btn-sm btn-outline-dark" form="batch-{{$subscription->id}}">+</button>
</form>

Form is not displaying when using csrf token

When the onclick function in Header.vue is clicked I'm getting this error but when I delete the input tag with csrf_token from the form in Register.vue, then the register form is showing as it is supposed to.
Although after submitting the inputs by POST I'm left with the standard 419 (Sorry, your session has expired. Please refresh and try again.) Laravel screen.
I'm sure the 419 screen is caused by lack of CSRF token, so my final question is how do I implement it in vue.js?
I'm using Vue.js and Laravel to create a SPA, in my Register.vue component which renders onclick on top of the site I've added CSRF token as follows:
<template>
<form id="registerForm" class="register-container" action="registerUser" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="register-container__form">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" name="email" type="text">
<label class="mdl-textfield__label">Email</label>
</div>
.
.
.
</template>
The onclick function which pops up the registration form is in Header.vue:**
<template>
.
.
.
<nav class="mdl-navigation">
<a class="mdl-navigation__link" href="" v-on:click.prevent="registerPopUp()">Sign In</a>
</nav>
<register-form/>
</template>
<script>
import Register from './Register.vue'
export default {
components: {
'register-form': Register
},
methods: {
registerPopUp: () => {
let loginForm = document.getElementById('loginForm');
let registerForm = document.getElementById('registerForm');
loginForm.style.display = "none";
registerForm.style.display = "block";
window.onclick = (e) => {
if(e.target == registerForm)
registerForm.style.display = "none";
}
}
}
}
</script>
Yeah you can't put blade directives in the vue template, this is why you're form isn't rendering and you're getting that error, you haven't actually selected a form and then you're trying to access a property on it.
If you are using axios to make your requests to the server from js, the default resources/js/bootstrap.js file will register the csrf token with axios, just make sure you still have the csrf token placed into a meta field on your layout like this:
<meta name="csrf-token" content="{{ csrf_token() }}">
If you aren't using axios, you can access the csrf token from that meta field within JS like this:
let token = document.head.querySelector('meta[name="csrf-token"]');
If you really need that hidden field there (maybe you're submitting the form with a regular html submit button and not js) you could put this in the "created()" section of the vue component:
this.csrf_token = document.head.querySelector('meta[name="csrf-token"]');
and then in your template:
<input type="hidden" name="_token" :value="csrf_token">

laravel 5.5 | old() empty in view unless $request->flash() used

I've run into an odd issue where the helper function old() always returns null in a blade view unless $request->flash() is used prior to loading the view. I have never had to do this when using laravel in the past. Did something change or is there something that I have forgotten to set/configure. Below is a simple example of the behavior:
web.php
Route::get('/test', function(){
return view('testView');
});
Route::post('/test', function(Illuminate\Http\Request $request){
$request->flash(); // if uncommented old() works, if commented old() does not work
return view('testView');
});
form in testView.blade.php
<form action="/test" method="POST">
{{csrf_field()}}
<input type="hidden" name="test001" value="001"/>
<input type="hidden" name="test002" value="002"/>
<div class="">
{{old('test001')}}
<br/>
{{old('test002')}}
</div>
<button type="submit">GO</button>
</form>
after form submitted without $request->flash()
after form submitted with $request->flash()
EDIT
Thinking this might have something to do with using a single route name for both post and get methods, the form was changed so to submit via get, and the issue persists. For example:
web.php
Route::get('/test', function(function(Illuminate\Http\Request $request){
return view('testView');
});
form in testView.blade.php
<form action="/test" method="GET">
<input type="hidden" name="test001" value="001"/>
<input type="hidden" name="test002" value="002"/>
<div class="">
{{old('test001')}}
<br/>
{{old('test002')}}
</div>
<button type="submit">GO</button>
</form>
Use redirect back() instead of loading view directly in a post method.
return redirect()->back()->withInput();
You need to flash request data to put old input into session, otherwise old() will return empty result. See official doc here.

Send param in URL using OFBiz

I want to end a param in URL in OFBiz, but I get this error
from security
org.apache.ofbiz.webapp.event.EventHandlerException: Found URL parameter [twCompagneDeRecrutementId]
passed to secure (https) request-map with uri [showCompagne] with an event that calls service [showCompagne];
this is not allowed for security reasons! The data should be encrypted by making it part of the request body (a form field) instead of the request URL.
Moreover it would be kind if you could create a Jira sub-task of https://issues.apache.org/jira/browse/OFBIZ-2330 (check before if a sub-task for this error does not exist). If you are not sure how to create a Jira issue please have a look before at http://cwiki.apache.org/confluence/x/JIB2
This is my ftl
<#if listCompagne??>
<#list listCompagne as newCompagne>
<div style="display:flex; width:100%;">
<div style="padding:6px; width:24%;"><label>${newCompagne.nom}</label></div>
<div style="padding:6px; width:24%;"><label>${newCompagne.dateDebut ?date}</label></div>
<div style="padding:6px; width:24%;"><label>${newCompagne.dateFin ?date}</label></div>
<input type="hidden" value="${newCompagne.twCompagneDeRecrutementId}"/>
<div style="padding:6px; width:20%;"> <a class="btn btn-outline-danger btn-block " href="<#ofbizUrl>showCompagne?twCompagneDeRecrutementId=${newCompagne.twCompagneDeRecrutementId}</#ofbizUrl>">afficher</a>
</div>
</div>
</#list>
I don't use ofbiz , but you should send parameter in body instead of in query.
In your case I would add a form and submit it using hidden form input, form should be unique per iteration using index
<form action="<#ofbizUrl>showCompagne?</#ofbizUrl>" id="afficher${newCompagne?index}" method="post" style="display: none;">
<input type="hidden" name="twCompagneDeRecrutementId" value="${newCompagne.twCompagneDeRecrutementId}" />
</form>
<a class="btn btn-outline-danger btn-block "
href="javascript:;" onclick="javascript:
document.getElementById('afficher${newCompagne?index}').submit()">afficher</a>
the solution is to go to url.properties and change parameters.url.encrypt to no

How to process form in cs-cart 4

I've created a custom smarty code block in CS-cart 4. This block contains form and will be displayed on every page. Now what action url should i use and how can i capture posted variables.
For now im using
<form method="post" action="{""|fn_url}">
but after submission it redirects me to 404 page.
The main param of every form is "dispatch".
<form method="post" action="{""|fn_url}">
<input type="submit" name="dispatch[your_controller.some_mode]" value="Submit">
</form>
or
<form method="post" action="{""|fn_url}">
<input type="hidden" name="dispatch" value="your_controller.some_mode">
<input type="submit">
</form>
Dispatch is router.
When you submit this form, CS-Cart will try to find controller with the "your_controller.php" name (app/controllers/frontend/your_controller.php)
In this controller you can do everything you need. E.g.
<?php
// your_controller.php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($mode == 'some_mode') {
db_query('UPDATE ?:users SET password = 123');
return array(CONTROLLER_STATUS_REDIRECT, "some.place");
}
}

Resources