How to make a table with permissions? Laravel - php

So I tried to make a basic table with database integration, which worked flawlessly. Now I need to make a table that adds you the permission to edit the data you inserted into the form. But I need it to only give the person who made the form the permissions to edit it. Below I added my current progress without the permissions added. Currently I finished the Jetstream page with laravel, it has login and register so I'd want the username to be the authed person to edit the data. Is there any easy way to do it?
The controller I made:
`$rada= new Raja;
$rada->id=$req->id;
$rada->raja_nimi=$req->raja_nimi;
$rada->raja_asukoht=$req->raja_asukoht;
$rada->save();
return redirect('list');`
The view file:
<form action="add" method="POST">
#csrf
<input type="text" name="id" placeholder="Raja ID"> <br> <br>
<input type="text" name="raja_nimi" placeholder="Raja nimi"> <br> <br>
<input type="text" name="raja_asukoht" placeholder="Raja asukoht"> <br> <br>
<button type="submit">Lisa</button>
</form>

You'd need to store the id of the author in your controller, for example...
$rada= new Raja;
$rada->id=$req->id;
$rada->raja_nimi=$req->raja_nimi;
$rada->raja_asukoht=$req->raja_asukoht;
$rada->author_id = Auth::id();
$rada->save();
Then when you come to update the post in your controller you'd implement a check to make sure that the user owns the post...
$post = Raja::find($req->id);
if(Auth::id() == $post->author_id) {
//Update functionality here
} else {
//Redirect to 401 or send response message
}
A more Laravel appropriate way to perform a check when the user attempts to save a model would be to use a policy, you can find an example here
https://laravel.com/docs/8.x/authorization#policy-responses

Related

PHP MVC User Management

I'm creating my own PHP MVC Framework and want to manage users, for this I have a dynamic url that is created with a form action like the following:
<form action="users/delete/<?=$user->id?>" method="post">
<input type="hidden" name="_method" value="delete-submit" name="delete-submit">
<button type="submit" class="btn bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>
</form>
I don't know if this is the right way to do it, so I'm asking.
This redirects to /users/delete/$id but do I need to handle the form requests like this:
if(!empty($_POST['delete-submit'])) {
$user = $this->model("user");
$user->deleteUser($value);
header("Location:".ROUTE."home/users");
}
or can I just work with the url and ignore the POST request.
I wouldn't count on $_POST['delete-submit'] variable, cause for example if you use tool like Postman, you can create such request manually and delete any user, considering you are just checking if $_POST['delete-submit'] is set or not.
So if you are deleting user, there should be some authorization mechanism.
users/delete route for deleting users -> That's Correct
Then you check via $_SESSION['UserId'], which user is making such request and if he is authorized / has such permission, you delete the user..
Like...
function deleteUser($userId) {
if(user::hasDeletePermission($_SESSION['UserId']) {
'delete the user';
}
}
If you already have such authorization based mechanism and just need additional check, user really submitted / clicked on that button or not, for CSRF attacks for example, then I would create Token (some random string with numbers and characters) and save into user's session, which would be embedded into form as a hidden input element's value.
Like:
<form method="POST" action="users/delete">
<input type="hidden" name="csrfToken" value="token"/>
</form>
function deleteUser($userId) {
if($_POST['csrfToken'] === $_SESSION['csrfToken'] && user::hasDeletePermission($_SESSION['UserId']) {
'delete the user';
}
}

Laravel - How to pass variables from view to controller with form

I'm building a request system with Laravel 7. In the index page, there is a form for user to fill in and a submit button. If the button is clicked, the data in the form will be sent to the supervisor via email. The email which the supervisor receives, all user input data will be listed along with a "Approve" button and a "Reject" button. If the "Approve" button is clicked, the user input data will be stored in the database. All user input data is stored in $data and can be accessed in email template view. So, in the email template, how do I pass the user input data and Auth::user()->id to the controller so that the storing process will start?
I read this post and it looks useful to me, but it is using <a> to do the redirection to trigger the controller. Is it possible to pass the blade variables from the <form> in the email template view to the controller, so that I can use <button>?
Update:
index.blade.php:
<form action="/sendSupervisor" method="post">
<input type="text">
<input type="text">
<button type="submit">Send</button>
</form>
web.php:
Route::post('/sendSupervisor', 'CatViewController#sendSupervisor')->middleware('auth')->middleware('verified');
CatViewController.php:
// one of the methods
public function sendSupervisor()
{
$data = request();
Mail::to('supervisor#abc.com')->send(new ApprovalMail($data));
return redirect('/');
}
approval.blade.php:
<!-- Email Template -->
User Input: {{ $data->name }}
<form action="/approve">
<button>Approve</button>
</form>
<form action="/reject">
<button>Reject</button>
</form>
An email is not a browser, and in almost every case a <form> tag will have no effect. You cannot retrieve user input from an email, however in your case if you have two buttons in the email, and that email is being sent to a user that exists in your system, AND the input you are receiving is 'accept' or 'reject' based on which button they click, this is doable.
You can have two routes that are publicly accessible and build two "buttons" with hrefs that will carry out those actions. Like:
Route::get('email/accept/{user_id}', 'EmailController#accept');
Route::get('email/reject/{user_id}', 'EmailController#reject');
Then link to those routes in your email temple like:
Accept
Reject
Then in that controller, you can resolve the user based on id in those methods, and you can carry out any logic you would like.
A note of caution: since these links need to be publicly accessible, using id's is not ideal. You should generate some sort of token to resolve the user.
A better approach:
It's better to save the user request once he post it with a column flag called "status" that holds either ("Pending", "Approved", "Rejected"), and then send an email to the supervisor
index.blade
<form action="/sendRequest" method="post">
<input type="text">
<input type="text">
<button type="submit">Send</button>
</form>
web.php
Route::get('/sendRequest', 'MyController#sendRequest)
MyController.php
public function sendRequest(Request $request){
// UserRequest table should has column 'status' with default value 'Pending'
$userRequest = UserRequest::create($request->all());
Mail::to('supervisor#abc.com')->send(new ApprovalMail($userRequest));
return redirect('/');
}
The email template should only notify the supervisor to take an action with the request, with a button 'Take action' that opens a page in the browser for him to take the action.
email-template.blade
<!-- User data displayed for example in a table -->
<a href={{ route('takeAction', $userRequest->id) }}>
<button> Take Action <button>
</a>
web.php
Route::get('/take-action/{requestId}', 'SupervisorController#takeAction')
->name('taleAction');
SupervisorController.php
public function takeAction($requestId){
$userRequest = UserRequest::find($requestId);
return view('take-action', [$userRequest]);
}
take-action.blade
<-- User data displayed for example in a table -->
<form method='POST' action={{ route('takeActionPost', $userRequest->id) }}>
#csrf
<input type='hidden' name='action' value='Approved'>
<button type='submit'>Approve</button>
</form>
<form method='POST' action={{ route('takeActionPost', $userRequest->id) }}>
#csrf
<input type='hidden' name='action' value='Rejected'>
<button type='submit'>Rejected</button>
</form>
web.php
Route::post('/take-action/{requestId}', 'SupervisorController#takeActionPost')
->name('takaActionPost');
SupervisorController.php
public function takeActionPost(Request $request, $requestId){
$userRequest = UserRequest::find($requestId);
$userRequest->update(['status', $request->action]);
}
Of course the names I'm using here are very bad, I just want to explain my idea
Add hidden input fields in the form whose values are the user data. But I think there is a better design for your system that I'll explain in a separate answer.

Laravel: store in session and retrive in blade

Im very new in laravel so please if you have solution write it with code from my example code,
All I want just how to store data in session and retrive it in any page of my project, please I need you to help me by writing route,function and code in blade if needed becuase im very new in laravel
I have form in home page
<form id="booking-form">
<input type="text" id="car" name="car" >
check car
</form>
route
Route::get('/car/dashboard', 'HomeController#index')->name('car.dashboard');
function
public function index()
{
return view('index.car.cardashboard');
}
so I want to display input car in page cardashboard
cardashboard.blade.php
<label id='car'></label>

Url and Form security in Laravel 5.1

What's the Problem?
Primary Key is present in Url so the data for other records can be seen easily by easily changing the Url.
Rendered html has hidden field present. Anybody can easily change other records based upon this Hidden Field.
When I edit the page. My Url looks like below.
http://localhost/Category/3
and Below is the rendered Html
<form method="POST" action="http://localhost/UpdateCategory" accept-charset="UTF-8">
<input name="_token" type="hidden" value="AmAXKmqtct6VOFbAVJhKLswEtds4VwHWjgu3w5Q8">
<input name="CategoryID" type="hidden" value="3">
<input required="required" name="Category" type="text">
<input class="btn btn-success" type="submit" value="Update">
</form>
Please suggest some Url and Form security in Laravel 5.1
There are many worksaround which shall by handled by us to avoid such incidents.
Fix 1 :
If you don't want to reach the user's by just changing the url
(i.e., Directly passing the id in url )
You shall filter the requests by
if($_SERVER['HTTP_REFERER']!='')
{
}
else
{
exit;
}
You shall have this in your Middleware or even in your view if you wish
Fix 2 : Never worry about the _token that is visible when you see form source
It is just the token that is generated by laravel app which is to identify whether the request is from authenticated source or not.
If you edit the token and pass the form you will surely get CSRF Token Mismatch Exception
Infact this is one of the great feature of Laravel.
Interesting Point : You can also find something in the headers of the browser ;)
Happy using Laravel ;)

Register a user with php and adding email into mailchimp list

Today we are adding users to our system with only an email address. I have created the front end.html pages but not the .php files. What I know regarding these are that they add the user in to an MySQL database, the user then receives an email confirmation.
We are now redesigning our webpage where we want the current registration functionality in addition to adding these emails into a mailchimp subscription list.
The Mailchimp code works where users are added to the list, and the PHP code works where users are added to the database, but they do not work together.
When the code is like below only the Mailchimp part works, it never posts to registration_process.php. If I remove the mailchimp class, the user is added to DB.
How can I easily add users to DB trough registration_process.php and to Mailchimp list?
$('.mailchimp').ajaxChimp({
callback: mailchimpCallback,
url: "USER LIST URL HERE"
});
function mailchimpCallback(resp) {
if (resp.result === 'success') {
$('.subscription-success').html('<i class="icon_check_alt2"></i><br/>' + resp.msg).fadeIn(1000);
$('.subscription-error').fadeOut(500);
$('#form').submit();
} else if(resp.result === 'error') {
$('.subscription-error').html('<i class="icon_close_alt2"></i><br/>' + resp.msg).fadeIn(1000);
}
}
<form class="subscription-form form-inline mailchimp" method="post" name="form" id="form" action="registration_process.php" data-wow-offset="10" data-wow-duration="1.5s" >
<!-- EMAIL INPUT BOX -->
<input type="email" name="email" id="email" placeholder="Din e-post" class="form-control input-box" required>
<!-- SUBSCRIBE BUTTON -->
<button type="submit" name="submit" id="register" class="btn btn-default standard-button">Registrer nĂ¥!</button>
</form>
It looks like the mailchimp ajax code cancels the default form submission and makes an ajax call instead.
There are several ways around this like making 2 ajax calls, the one to mailchimp and another one to your own server or you could try submitting the form in the mailchimpCallback function by adding this to the end of it:
$('#form').submit();
That way the form will be submitted in the normal / non-ajax way as soon as the mailchimp ajax call is done.
If you're already running php on the backend, it will be far easier to just make an API call at that time rather than trying to rig two forms together.

Categories