Gate Fascade and Model Policies - laravel

I'm currently trying to find out if you can add a Gate Fascade to a Policy or if there's a better way to handle my situation.
I have a list of users with each having ONE role and each role can have MANY permissions. All of this is stored in my database with the correct relationships established in my models.
I am trying to show or not show a delete icon based on whether a user can delete another user in my HTML list of users.
Example:
Lets say user1 has a role of 3 which is a site-admin. Site admins have the permission to delete users, however they are NOT able to delete other users who have the same role as them or a role higher than theirs.
When user1 accesses the /users uri they are shown the HTML table of users in the database and as the last table column are the actions that can be performed on the row for that user row. The available action icons are edit and delete. For the delete icon I want a policy to be ran to make sure than the authenicated user can delete users first but also pass the current row's user object and see if the user has the same role id or higher in which case it will NOT display that icon.
<?php
namespace App\Policies;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy
{
use HandlesAuthorization;
/**
* Create a new policy instance.
*
* #return void
*/
public function __construct()
{
//
}
public function delete(User $user) {
return Auth::user()->role->permission and $user->role_id < Auth::user()->role_id and $user->id != Auth::user()->id;
}
}
/reources/views/partials/tables/actions.blade.php
<td class="actions">
<i class="icon wb-edit" aria-hidden="true"></i>
<i class="icon wb-eye" aria-hidden="true"></i>
#can('delete-user', $user)
<form class="inline" method="POST" action="{{ route('users.delete', [$user->id]) }}">
{{ method_field('DELETE') }}
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-sm btn-icon btn-pure btn-default on-default" data-toggle="tooltip" data-original-title="Delete"><i class="icon wb-trash" aria-hidden="true"></i></button>
</form>
#endcan
</td>

Rewrite your policy method like this (I used your own syntax and assumed it's true):
public function delete(User $authUser, User $user) {
return $authUser->role->permission and
$user->role_id < $authUser->role_id and
$user->id != $authUser->id;
}
In your policy methods, first argument is always your authenticated user, and other arguments are what you pass through methods like #can or Gate::allow.

Related

Getting id value from url in controller and displaying values associated laravel

I'm trying to create a ticket management system with laravel jetstream and livewire. In the user page there's a table with all tickets that the user created. When the user clicks on the button to open one specific ticket, it should pass the id of the ticket and redirect to another page where it receives the data of that ticket he clicked, like title, message, etc..
The id is passed through the url, but my main problem is that whenever I try to display that data in the view, nothing shows, no errors either. I think that something might be wrong with my controller.
Here's my route:
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers']);
The button to redirect to that specific ticket:
<a href="{{ url('tickets.answers' . '/'. $ticket->id ) }}" > <x-jet-secondary-button >
See Answer
</x-jet-secondary-button></a>
AnswersController:
public function render(Request $request)
{
$tickets = Ticket::where('id', $request->url('id'));
return view('livewire.tickets.answers', [
'tickets' => $tickets,
]);
}
And how I'm trying to display in my blade:
#foreach($tickets as $key => $ticket)
<!-- This example requires Tailwind CSS v2.0+ -->
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Ticket nº {{$ticket->id}} - {{$ticket->title}}
</h3>
</div>
</div>
#endforeach
In your TicketsController you can fetch the id like this
public function answer(Request $request, int $id)
{
// Use the find() method, instead of where(), when searching for the primary key
$tickets = Ticket::find($id);
// .. more
}
In your routes files you specify an answer method, so use this in your TicketsController.
// See how to name a route
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers'])->name('tickets.answers');
Then use the named route in your view like this:
<a href="{{ route('tickets.answers', ['id' => $ticket->id]) }}">
You can see a similar example in the Laravel docs.

View and Controller for a Downloadpage

I need to create a downloadpage. Ich have a model Product and a model File. The create/store and the edit/update is already working. With a submit button I'm saving fields like produktname, description, etc. into products-table. Fields like filename, filePath and product_id saving into files-table. Files also uploaded to Storage. Model Product has a hasMany-relation to File and the model File has a BelongsTo-relation to Product. In the File model "product_id" is related to the Product model.
So far so good. What's also working is: Index view of FileController. I can see all uploaded files and can also download them. Through the product_id I can access the actual product show method. That's how it should be. It's possible here in the index.blade.php:
#foreach ($files as $file)
<tr>
<th>{‌{ $file->filename }}</th>
<td>download</td>
<td>{‌{ $file->product_id }}</td>
<td>{‌{ $file->id }}</td>
</tr>
#endforeach
In the show.blade.php I can see already all data from the products table. I have two buttons for downloading changelog (just a link) and working and for downloading the stored file (which is in the files table. I can't get it working for the download stored file. dd($files); is NULL. Here's the ProductController show part. I applied use App\File; on top of the controller, because I want to give the ability to access the File model.
public function show(Product $product)
{
return view('products.show', compact('product','file'));
}
In show.blade.php I get an error: compact(): Undefined variable: file
<div>
<button id="changelog" name="changelog" class="btn btn-lg btn-primary btn-block" type="submit" onclick="window.open('{‌{ $product->changelog }}')">Download Changelog</button>
<button id="filename" name="filename" class="btn btn-lg btn-success btn-block" type="submit" onclick="window.open('{‌{ $file->filename }}')">Download Installer</button>
</div>
How can I access an element of the other model or the other table? How can I expand {‌{ $file->filename }} or probably {‌{ $product->$file->filename }} to get the file to download?
I'm trying since days and can't find the solution.
Thx, for responding. I still have problems doing Eloquent and Query building, but the use of dd od var_dump helps alot and showed me that I have valuable data. The problem was to define the query.
Here's the working stuff:
Product model:
public function file()
{
return $this->hasMany('App\File', 'product_id');
}
File model:
public function product()
{
return $this->hasOne('App\Product', 'id');
}
Product controller:
public function show(Product $product)
{
$files = Product::with('file')->find($product->id)->file;
return view('products.show', compact('product', 'files'));
}
show view:
#foreach ($files as $file)
<button id="filepath" name="filepath" class="btn btn-lg btn-success btn-block" type="submit" onclick="window.open('{{ $file->filepath }}')">Download File: {{ $file->filename }}</button>
#endforeach

How to check data from pivot table?

I have an Event and User model which have a pivot table called event_users.
In the pivot table event_id and user_id is saved when user press participate button.
I have displayed all the event list.
Now i want to display event which is participated as participated and not participated as participate.
i have tried
controller
public function vieweventlist()
{
$data['events'] = Event::with('users')->get();
return view('page',$data);
}
blade file
#foreach($events as $event)
<h1>Event Name</h1>
#foreach($event->users as $check)
#if($check->pivot->user_id == auth()->user()->id && $check->pivot->event_id == $event->id)
<button type="button" class="btn participateevent" disabled>Participated</button>
#else
<button type="button" class="btn participateevent">Participate</button>
#endif
#endforeach
#endforeach
I have set belongsToMany relation in both the Event and User models.
The problem with this code is second foreach loop is pivot table loop. Suppose I have one data in pivot table. I have list down 5 events. Because of pivot table foreach (Second one) only one button is shown in blade file which is participated but doesn't show #else participate button.
Your second foreach makes it so only events who has participants (ether the logged in user or not) will show a button (participated or participate). If an event has no users attached to it, no button will be shown.
If you want to get the list of events with the information "if the current user is already participating to it or not" then here is a better way.
Controller
public function vieweventlist(){
$data['events'] = Event::withCount('users', function($user) {
$user->where('id','=', auth()->id());
})->get();
return view('page',$data);
}
Blade
#foreach($events as $event)
<h1>Event Name</h1>
#if($event->users_count)
<button type="button" class="btn participateevent" disabled>Participated</button>
#else
<button type="button" class="btn participateevent">Participate</button>
#endif
#endforeach

I am new in laravel and I want to announcement on homepage

Actually I want to display admin announcement or any notification on home page so when ever any user will be login with credentials detail so he or she can see announcement or notification..
please help me step by step , if possible with code logic, please do for me thank you very much
as you requested for full step by step process try this
first make form in your admin panel like this
<form method="post" action="{{ route('announcement') }}">
<label>Enter Your Announcement</label>
<textarea class="form-control" name="text">
</textarea>
<select name="active_status">
<option value="0">Deactive</option>
<option value="1">Active</option>
</select>
</form>
open your route/web.php make post method
Route::post('/announcement', [
'uses' => 'AdminController#postAnnouncement',
'as' => announcement
]);
if you have AdminController and its okay if not make it with these commands
php artisan make:controller AdminController
now you can add your function for save your announcement to database
public function postAnnouncement(Request $request){
$announcement = new Announcement;
$announcement->text = $request->text;
$announcement->active = $request->active_status;
$announcement->save();
return back()->with('status', 'Announcement Posted Success');
}
add use App\Announcement; in top of your controller
now you need to make announcement table and model
php artisan make:model Announcement -m
it will generate 2 file model & migration
go to database/migration folder and add this line to announcement migration after
$table->increments('id');
$table->string('text');
$table->boolean('active');
your table is ready to migrate now
php artisan migrate
now you can show in your homepage like this
first goto your homecontroller & add these lines
$announcements = App\Announcement::where('active', true)->get();
return view('home', compact('announcements'));
in your home.blade.php file
//Only for Authenticated Users
#auth
#foreach($announcements as $announcement)
<p>{{ $announcement->text }}</p>
#endforeach
#endauth
//Only for Guest Users
#guest
#foreach($announcements as $announcement)
<p>{{ $announcement->text }}</p>
#endforeach
#endguest
You can do it simply with the help of built-in user model.
First, check if the user is authorized and after that, you can show the announcement section.
All this should be done in the view of your page. you can do something like this
#if (Auth::check())
//show authorized content (Announcements etc.)
#else
//show unauthorized content
#endif
Or you can also do this in laravel 5.6
#auth
// The user is authenticated...
#endauth
#guest
// The user is not authenticated...
#endguest
Also do some research for this there are plenty of examples there on the Internet.
Try This
#auth
// For Logged in users only
<h1> You Are Loged In</h1>
#endauth
#guest
// For Guest Users
<h1> You Are Guest </h1>
#endguest
#auth
//if user logged in
<h1> You Are Loged In</h1>
#else
else guest
<h1> You Are Guest </h1>
#endauth

GET Data empty in Laravel

Hi I am new to Laravel and so far I made good progress. Right now my head is blocked now and I need some direction or help, please.
I am getting data from radio button but GET Data is empty. I need to fill-in this data (pay) into an exist DB and I am getting "Creating default object from empty value" and I agree with Laravel :) I guess, my lack of knowledge is blocking me here.
Thanks.
This is the GET and POST data
GET Data empty
POST Data
_token = "72nrnI7Y7xuIQJe6LZPLGLzNsAv6ZZbY29zkjcIr"
pay = "CC"`
This is the Model
namespace App;
use Illuminate\Database\Eloquent\Model;
use DB;
use Auth;
class DAddress extends Model
{
protected $table='dAddress';
protected $fillable = ['payment_method'];
public function createPay()
{
$user = Auth::user();
$order = $user->daddress()->create([
'payment_method' => paymentMethod()
]);
}
}
This is the Controller
public function paymentMethod(Request $request) {
$address->payment_method = $request->pay;
DAddress::createPay();
Cart::destroy();
return redirect('abc');
}
This is where I get the HTML data
<form action="{{url('/paymentMethod')}}" method="post">
<input type="hidden" value="{{csrf_token()}}" name="_token"/>
<div class="form-group">
<div class="col-md-6">
<!-- First name -->
<input type="radio" class="form-control" name="pay"
value="CC"><i class="fa fa-credit-card"></i> Credit Card
<br> <br>
<input type="radio" class="form-control" name="pay"
value="PP"><i class="fa fa-paypal"></i> Paypal
<br> <br>
<input type="radio" class="form-control" name="pay"
value="BT"><i class="fa fa-university"></i> Bank Transfer
</div>
</div>
<input type="submit" class="btn btn-primary" value="Move to Last Page" />
This is the User.php I added below function.
public function daddress()
{
return $this->hasMany(DAddress::class);
}
i do not understand what you are trying to do with this line $address->payment_method = $request->pay;
when you say $address->payment_method, what is the $address object holding and where is payment_method you are trying to access, why not do something like this $payment_method = $request->pay, except is you are setting $payment_method as a global variable
if you are using the laravel create method you could do something like this $payment_method= App\createPay::create(['payment_method' => $request->pay]);
else you could instantiate you model like
$pay =createPay();
$pay->payment_method=$request->pay;
$pay->save();
i would have love you logic to be in the controller, i would have done something like this in my controller
public function createPay(Request $request){
$user = Auth::user();
$id=$user->id;
$payment=createPay::find($id);
$payment->payment_method=$request->pay;
$payment->save();
return redirect('abc');
}
i used laravel eloquent here, that is if you want to update a record, i don't know if this is close to what you want.

Resources