Laravel livewire google recaptcha validation problem - laravel

I have a livewire component where i am trying to implement google recaptcha using a package https://github.com/anhskohbo/no-captcha. but getting validation error even when i complete the captcha validation process.
Below is my code livewire blade code.
<div class="col-md-6">
<div wire:ignore>
{!! NoCaptcha::renderJs() !!}
{!! NoCaptcha::display() !!}
</div>
</div>
<div class="form-inline justify-content-center text-center">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1"><i class="far fa-envelope"></i></span>
</div>
<input type="email" class="form-control align-self-center" placeholder="Enter email" aria-label="newsletter_email" aria-describedby="basic-addon1" name="newsletter_email" wire:model.defer="newsletter_email">
</div>
<div class="form-group ml-3">
<button class="btn" style="background-color: #fff!important; color: #000!important;" wire:click.defer="newsletterEmail">SUBSCRIBE</button>
</div>
</div>
#error('recaptcha')
<div style="color: #fff">{{ $message }}</div>
#enderror
#error('newsletter_email')
<div style="color: #fff">{{ $message }}</div>
#enderror
#section('js')
<script type="text/javascript">
var onCallback = function () {
#this.set('recaptcha', grecaptcha.getResponse());
}
</script>
#endsection
and below is my validation code in livewire controller.
public $newsletter_email;
public $hascaptcha = 0;
public $captcha;
protected $rules = [
'newsletter_email' => 'required|email',
'recaptcha' => 'required|captcha',
];
protected $messages = [
'newsletter_email.required' => 'The Email Address cannot be empty.',
'newsletter_email.email' => 'The Email Address format is not valid.',
'recaptcha.required' => 'Please verify that you are not a robot.',
'recaptcha.captcha' => 'Captcha error! try again later or contact site admin.',
];
public function newsletterEmail()
{
$this->resetErrorBag();
$this->validate();
$current_date_time = Carbon::now()->toDateTimeString();
DB::table('news_letter')->insert([
'email' => $this->newsletter_email,
'created_at' => $current_date_time,
]);
$this->newsletter_email = "";
session()->flash('newsletter_message', 'Great!! You have subscribed for newsletter.');
}

No Package Needed...
Incase one needs Laravel Livewire - G Recaptcha V2,
In Your Component :-
<x-jet-form-section submit="submit(grecaptcha.getResponse(widgetId1))" method="POST">
<div class="col-span-6 sm:col-span-4"><div id="g-recaptcha"></div><x-jet-input-error for="g-recaptcha-response" class="mt-2" /></div>.
In Your Script :-
#section('scripts') <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer> </script> <script> var widgetId1; var onloadCallback = function() { widgetId1 = grecaptcha.render('g-recaptcha', { 'sitekey' : "{{ \Config::get('recaptcha.G_RECAPTCHA_SITE_KEY') }}", 'theme' : 'light' }); }; </script> #endsection
Your Component Class
public function submit($recaptcha)
Rest Of The Verification Code :-
`$url = 'https://www.google.com/recaptcha/api/siteverify';
$parameters = [
'secret' => \Config::get('recaptcha.G_RECAPTCHA_SITE_SECRET'),
'response' => $recaptcha
];
$qs = http_build_query($parameters);
$curl_request = "{$url}?{$qs}";
$curl = curl_init();
curl_setopt_array($curl, array(CURLOPT_URL => $curl_request, CURLOPT_RETURNTRANSFER => 1));
$response = curl_exec($curl);
$responseData = json_decode($response);
curl_close($curl);
if($responseData->success){ }else{ throw ValidationException::withMessages(['g-recaptcha-response' => 'ReCaptcha validation failed.']); }`

Related

Can't upload files using livewire

I can't submit a form with file in order to proced to upload method, the file is selected when I submit it says that the file is required (empty data).
Everything works fine on mylocal Windows machine but I face the problem when using vps for production.
view :
<form wire:submit.prevent="submit" enctype="multipart/form-data">
<div>
#if(session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
#endif
</div>
<div class="form-group">
<label for="exampleInputName">Title:</label>
<input type="text" class="form-control" id="exampleInputName" placeholder="Enter title" wire:model="title">
#error('title') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<div class="form-group">
<label for="exampleInputName">File:</label>
<input type="file" class="form-control" id="exampleInputName" wire:model="file">
#error('file') <span class="text-danger">{{ $message }}</span> #enderror
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
controller :
use WithFileUploads;
public $file, $title;
public function submit()
{
$validatedData = $this->validate([
'title' => 'required',
'file' => 'required',
]);
$validatedData['name'] = $this->file->store('files', 'public');
// File::create($validatedData);
session()->flash('message', 'File successfully Uploaded.');
}
VPS folders :
I tried to change permessions, user group.... no success.
try this
use WithFileUploads;
public $title;
public $file;
protected function rules()
{
return [
'title' => ['required', 'string', 'max:50'],
'file' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:5000']
];
}
public function submit()
{
$this->validate();
$data = [
'title' => $this->title
];
if (!empty($this->file)) {
$url = $this->file->store('files', 'public');
$data['file'] = $url;
}
File::create($data);
session()->flash('message', 'File successfully Uploaded.');
}

Keep modal open if any validation error exists laravel

I am trying to upload a csv and store the data accordingly in database. Form is in the modal. I want the modal to open if there exists any validation error message.
Here is the modal and ajax query:
$('#formSubmit').click(function(e) {
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('input[name="_token"]').val()
}
});
$.ajax({
url: "{{ url('/resellers') }}",
type: 'POST',
contentType: false,
processData: false,
data: {
csv_file: $('#csv_file').val(),
},
success: function(result) {
if (result.errors) {
$('.alert-danger').html('');
$.each(result.errors, function(key, value) {
$('.alert-danger').show();
$('.alert-danger').append('<li>' + value + '</li>');
});
} else {
$('.alert-danger').hide();
$('#reseller_modal').modal('hide');
}
}
});
});
<div class="col-sm-6">
<button type="button" id="csv-import" class="btn btn-secondary m-2 csv-import" data- toggle="modal" data-target="#reseller_modal">Import Csv</button>
</div>
<!-- Bootstrap modal -->
<div class="modal fade" id="reseller_modal" tabindex="-1" role="dialog" aria- labelledby="reseller_modal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="demoModalLabel">CSV import</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="alert alert-danger" style="display:none"></div>
<div class="modal-body">
<div class="row">
<form class="form-horizontal" method="POST" action="{{ route('processImport') }}" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-group">
<input id="csv_file" type="file" class="form-control" name="csv_file" required>
#if ($errors->has('csv_file'))
<span class="help-block">
<strong>{{ $errors->first('csv_file') }}</strong>
</span>
#endif
</div>
<div class="form-check">
</div>
<button type="submit" class="btn btn-primary" id="formSubmit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
And here is the controller:
public function processImport(Request $request)
{
$validator = Validator::make($request->all(), [
'csv_file' => 'required|file|mimes:csv,txt'
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()->all()]);
}
$rows = importCsv($request->file('csv_file'));
foreach ($rows as $data) {
$validator = Validator::make($data, [
'name' => ['required', 'string'],
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string'],
]);
$status = User::where('email', '=', $data['email'])->exists();
if (!$validator->fails()) {
if (!$status) {
User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
]);
} else {
$user = User::where('email', '=', $data['email'])->first();
$user->update([
'password' => $data['password']
]);
}
} else {
Log::channel('import_fail')->info($data['email'] . ' Couldnot be stored . Has the validation message" : ' . $validator->errors()->first());
}
}
return redirect()->route('resellers')->with('success', 'Resellers imported successfully');
Even though I have csv_field in form, I get this error The csv_file field is required. It keeps the modal open.
I guess problem is here.
data: {
csv_file: $('#csv_file').val(),
},
You are sending text value i.e. name of file instead of actual file. and validating file.
Refer this to upload file using ajax. https://makitweb.com/how-to-upload-a-file-using-jquery-ajax-in-laravel-8/

Ajax script to update record does not work, Laravel

I wrote a small script that updates the information on the page when editing. Everything basically works as it should, but I just can’t update the image. I don’t understand what the matter is. Without a script, with a page reload, everything works as it should.
Ajax script
<script type="text/javascript">
$("document").ready(function() {
$("#editPostButton{{$post->id}}").click(function() {
var formData = $("#EditPostForm{{$post->id}}").serialize();
$.ajax({
url: "{{route('editPost', ['id' => $user->id, 'postId' => $post->id])}}",
type: "POST",
data: formData,
success: function(data) {
$("#textpostdata{{$post->id}}").html($(data).find("#textpostdata{{$post->id}}").html());
$("#closeButton{{$post->id}}").click();
}
});
});
});
</script>
My Controller
public function editPost(Request $request, $id, $postId) {
$validator = $this->validate($request,[
'title' => 'max:100',
'message' => 'max:5000',
'img' => 'mimes:jpeg,png,gif,jpg|max:5000',
'videoPost' => 'max:100'
]);
if($validator) {
$user = User::find($id);
if(!$user && $user != Auth::user()->id) {
return abort(404);
}
$post = Profile::find($postId);
if(!$post) {
return abort(404);
}
$post->user_id = Auth::user()->id;
$post->title = $request->title;
$post->message = $request->message;
$post->videoPost = str_replace('watch?v=', 'embed/', $request->videoPost);
if($request->file('img')) {
$path = Storage::putFile('public/'.Auth::user()->id.'/post', $request->file('img'));
$url = Storage::url($path);
$post->img = $url;
}
$post->update();
return redirect()->back();
}
}
And update form
<form action="{{route('editPost', ['id' => $user->id, 'postId' => $post->id])}}" method="post" enctype="multipart/form-data" id="EditPostForm{{$post->id}}" name="postForm">
#csrf #method('PATCH')
<div class="form-group">
<textarea maxlength="100" name="title" class="form-control" rows="1">{{$post->title}}</textarea>
</div>
<div class="form-group">
<textarea id="message" maxlength="5000" name="message" class="form-control" rows="10">{{$post->message}}</textarea>
</div>
<div class="form-group">
<textarea maxlength="100" class="form-control mt-1" id="videoPost" name="videoPost" cols="100" rows="1">{{$post->videoPost}}</textarea>
</div>
<h6>Current image</h6>
<img src="{{$post->img}}" class="img-fluid mb-2" width="230">
<div class="form-group">
<input type="file" id="img" name="img" accept="image/*">
</div>
<button type="button" class="btn btn-sm btn-primary" id="editPostButton{{$post->id}}">Edit</button>
</form>

Laravel get a empty variable from axios.post from vuie.js module

partners from stackOverflow im making a module using laravel like backend, and vue.js by frontend, i have a form to create a new entity, but the controller dont get the values¡, plz help me to find the error. I'm going to share the code.
the routes.web
//new event from API
Route::resource('/api/events', 'EventsController', ['except' => 'show','create']);
The function in the controller EventsController.php
<?php
namespace soColfecar\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use soColfecar\Http\Requests\CreateEventRequest;
use soColfecar\Http\Requests\UpdateEventRequest;
use soColfecar\User;
use soColfecar\Change;
use soColfecar\Event;
use soColfecar\Event_type;
use Auth;
public function store(Request $request)
{
$exploded = explode(',', $request->banner);
$decoded = base64_decode($exploded[1]);
if(str_contains($exploded[0],'jpeg'))
$extension = 'jpg';
else
$extension = 'png';
$fileName = str_random().'.'.$extension;
$path = public_path().'/storage/banner/'.$fileName;
file_put_contents($path, $decoded);
Event::create([
'event' => strtoupper($request['event']),
'id_event_type' => $request['id_event_type'],
'date_init' => $request['date_init'],
'date_end' => $request['date_end'],
//'banner' => $fileName,
]);
Change::create([
'description' => 'Creo el de evento:'.$request['event'].' correctamente.',
'id_item' => 10,
'id_user' => Auth::user()->id,
]);
return redirect()->route('events.index')
->with('info', 'evento guardado con exito');
}
the method:
<form method="POST" v-on:submit.prevent="storeNewEvent">
<div class="form-group m-form__group">
<label for="eventTypeInput">Tipo de vento:</label>
<v-select :options="eventTypes" v-model="newEvent.id_event_type" id="eventTypeInput">
<template slot="option" slot-scope="option">
{{ option.label }}
</template>
</v-select>
<span v-for="error in errors" class="text-danger" :key="error.error">{{ error.city_id }}</span>
</div>
<div class="form-group m-form__group">
<label for="inputHotelName">Nombre del Evento</label>
<input type="text" class="form-control" name="inputHotelName" v-model="newEvent.event" placeholder="Nombre del Evento">
<span v-for="error in errors" class="text-danger" :key="error.error">{{ error.hotel_name }}</span>
</div>
<div class="form-group m-form__group">
<label for="date_init_imput">Fecha de inicio</label>
<input class="form-control" type="date" v-model="newEvent.date_init" value="" id="date_init_imput">
</div>
<div class="form-group m-form__group">
<label for="date_end_imput">Fecha de finalizacion</label>
<input class="form-control" type="date" v-model="newEvent.date_end" value="" id="date_end_imput">
</div>
<div class="form-group m-form__group">
<label for="customFile">Banner del Evento</label>
<div></div>
<div class="custom-file">
<input type="file" class="custom-file-input" #change="getLogo" id="customFile">
<label class="custom-file-label" for="customFile">Seleccione archivo</label>
<span v-for="error in errors" class="text-danger" :key="error.error">{{ error.logo }}</span>
</div>
</div>
<hr>
<button type="submit" class="btn btn-info waves-effect text-left">Guardar</button>
</form>
data() {
return {
changes: [],
eventTypes: [],
errors: [],
newEvent: {
event: '',
id_event_type: '',
date_init: '',
date_end: '',
banner: '',
}
}
},
storeNewEvent : function() {
var url = 'api/events';
var newEvent = this.newEvent
axios.post(url, {event: this.newEvent}).then(response => {
this.newEvent = {}
this.errors = [];
$('#new_event_modal').modal('hide');
$('.modal-backdrop').remove();
toastr.success('Se ha creado el evento con exito!')
}).catch(error => {
this.errors = error.response.data
});
},
And the error
"Too few arguments to function soColfecar\Http\Controllers\EventsController::store(), 0 passed and exactly 1 expected"
enter image description here
You need to type hint the $request so Laravel knows to fill it in ("dependency injection").
At the top of your file:
use Illuminate\Http\Request;
Then, for your function:
public function store(Request $request) {

Vue/Laravel - uploading a file on update doesn't work

I have a component that works on create form, but not on an update form. The image is being shown in the update form, but when I try to upload it, in the backend, I don't get any file for the field 'image'
This is the component:
<template>
<div>
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onFileChange">
</div>
<div v-else>
<img :src="image" />
<input type="file" name="image" style="display:none">
<button #click="removeImage">Remove image</button>
</div>
</div>
</template>
<script>
export default {
props: {
image: {
type: String,
default: ""
}
},
data() {
return {
formData:new FormData(),
file: null
}
},
methods: {
onFileChange: function onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
this.formData.append('file', files[0]);
this.file = files[0];
},
createImage: function createImage(file) {
var image = new Image();
var reader = new FileReader();
var vm = this;
reader.onload = function (e) {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function removeImage(e) {
this.image = '';
}
}
}
</script>
And this is how I call it in the create view:
<image-upload></image-upload>
And this is for the update view:
<image-upload image="/uploads/{{ $magazine->image }}"></image-upload>
But, when I do dd($request->all()) in the update function in my controller I get this output:
array:8 [▼
"_method" => "PUT"
"_token" => "oNkMAyKsKsxOpqeonRDvyusqtFrfVgBEQOnyNrFw"
"image" => "1.png"
"name" => "Article name"
"summary" => ""
"visual_id" => ""
"spid_id" => ""
"files" => "1"
]
And for the create function where it actually works I get:
array:6 [▼
"_token" => "oNkMAyKsKsxOpqeonRDvyusqtFrfVgBEQOnyNrFw"
"name" => "Article name"
"summary" => ""
"visual_id" => ""
"spid_id" => ""
"image" => UploadedFile {#222 ▶}
]
This is the form:
{!! Form::model($magazine, ['method' => 'PUT', 'route' => ['magazines.update', 'id' => $magazine->id, 'files' => true]]) !!}
<div class="row magasin-form large-6 large-offset-3 columns">
<ul class="tabs">
<li class="tabs-title is-active">Tilbake</li>
</ul>
<div class="tabs-content">
<div class="tabs-panel is-active">
#section('errors')
#include('layouts.partials.errors')
#show
<p>Redigere</p>
<div class="row">
<div class="large-12 columns">
<label>Navn
{!! Form::text('name', $magazine->name, ['placeholder' => 'Navn']) !!}
</label>
</div>
</div>
<image-upload image="/uploads/{{ $magazine->image }}"></image-upload>
<div class="row">
<div class="large-12 columns">
<label>Visual ID
{!! Form::text('visual_id', $magazine->visual_id, ['placeholder' => 'Visual id']) !!}
</label>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<label>Spid ID
{!! Form::text('spid_id', $magazine->spid_id, ['placeholder' => 'spid id']) !!}
</label>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<label>Summary
{!! Form::textarea('summary', $magazine->name) !!}
</label>
</div>
</div>
<div class="row">
<div class="large-6 columns">
{!! Form::submit('Lagre', ['class'=> 'secondary button']) !!}
</div>
<div class="large-6 columns">
<a class="secondary hollow button" href="{{ route('magazines.index')}}">Avbryte</a>
</div>
</div>
</div>
</div>
</div>
{!! Form::close() !!}
Updated
I have also tried with changing my component to this:
<template>
<div class="Image-input">
<div class="Image-input__input-wrapper">
<h2>+</h2>
<input #change="previewThumbnail" class="Image-input__input" name="thumbnail" type="file">
</div>
<div class="Image-input__image-wrapper">
<i v-show="! imageSrc" class="icon fa fa-picture-o"></i>
<img v-show="imageSrc" class="Image-input__image" :src="imageSrc">
</div>
</div>
</template>
<script>
export default {
props: ['imageSrc'],
methods: {
previewThumbnail: function(event) {
var input = event.target;
if (input.files && input.files[0]) {
var reader = new FileReader();
var vm = this;
reader.onload = function(e) {
vm.imageSrc = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
}
}
</script>
But I get the same output for my form on update.
It looks like you're accidentally passing the files boolean to the route array instead. Try updating your form opening to:
{!! Form::model($magazine, ['method' => 'PUT', 'route' => ['magazines.update', 'id' => $magazine->id], 'files' => true]) !!}
Your input field doesn't have a name so that might be why the form won't pick it up
Not sure why you are modifying the FormData. Any Reason you can't just submit the <input> with the form instead of extracting it?
Try showing us how the form looks, the place where you put your image-upload component

Resources