0

I'm trying to use a permission where if a user have it then the user will be able to edit a text field in a form, otherwise, the field will be disabled.

I know I can add a disabled parameter here {{ Form::text('name', ['disabled' => 'disabled']) }}

What should I do to achieve what I need to do without having to write my HTML form twice? Here's my form:

 @if (Auth::user()->can(\Permission::EDIT_INFO))
        <tr>
            <th>Name 1:</th>
                <td>
                {{ Form::text('name') }}
                </td>
            <th>Name 2:</th>
                <td>
                {{ Form::text('name_ar') }}
                </td>
        </tr>
 @endif

In other words: (if have permission show normal form else show the same form but disabled fields)

Salam
  • 1,126
  • 14
  • 20

2 Answers2

1

The straight forward solution would be to use the ternary operator:

<tr>
    <th>Name 1:</th>
    <td>{{ Form::text('name', Auth::user()->can(\Permission::EDIT_INFO) ? [] : ['disabled' => 'disabled']) }}</td>
    <th>Name 2:</th>
    <td>{{ Form::text('name_ar', Auth::user()->can(\Permission::EDIT_INFO) ? [] : ['disabled' => 'disabled']) }}</td>
</tr>

This will use the [] parameter array in case Auth::user()->can(\Permission::EDIT_INFO) and the ['disabled' => 'disabled'] array if the user lacks the permission.

But there might be even nicer ways to do it, because this solution will also produce duplicated code if you have other parameters, i.e. when [] is not empty but something like ['aria-label' => 'abc', 'maxlength' => 15].


Edit:

You could also create a helper method that simplifies using different kinds of parameters based on if a permission is present or not.

If this is the first time you are defining a custom helper method, you will need a place to put them. You basically need a plain .php file for this, so app/helpers.php is quite ok. To load the helper methods, you will have to include the file at some point - I recomment doing it in the AppServiceProvider::register() method:

/**
 * Register any application services.
 */
public function register()
{
    require_once app_path().'/helpers.php';

    // other code ...
}

Then you will have to define your helper method in the app/helpers.php file:

<?php

if (!function_exists('merge_if_has_permission')) {
    function merge_if_has_permission(string $permission, array $base, array $optional): array
    {
        if (\Auth::user()->can($permission)) {
            return array_merge($base, $optional);
        }
        return $base;
    }
}

You can then use this function in the frontend:

<td>{{ Form::text('name', merge_if_has_permission(\Permission::EDIT_INFO, ['maxlength' => 15], ['disabled' => 'disabled'])) }}</td>

This will add ['maxlength' => 15, 'disabled' => 'disabled'] to the form field if the currently authenticated user has the permission Permission::EDIT_INFO. If the user does not have this permission, it will only add ['maxlength' => 15].

As this is doing exactly the opposite of what you are asking (because you wanted the field to be disabled if the user does not have the permission) you will most likely need another method called merge_if_hasnt_permission() - but I guess you find your way there yourself now.

Shorter method names would make sense to reduce the code... but I figured it is quite hard to describe what the function does with less words.

By the way, you can also use this method to override properties of the $base array conditionally.

Namoshek
  • 6,394
  • 2
  • 19
  • 31
  • If my form has 20 input fields let’s say. Your solution runs the permission check 20 times. Right? – Salam May 03 '18 at 17:13
  • Yes. But that doesn't mean it will hit the database 20 times. It is also possible that it gets optimized away by the interpreter/compiler, although I wouldn't poker on that one. – Namoshek May 03 '18 at 17:19
0

This isn't really the best way to do this, but it'll work:

{{ Auth::user()->can(\Permission::EDIT_INFO) ? Form::text('name') : Form::text('name', ['disabled' => 'disabled']) }}

You should also remember to check server side to authorize the user.

I would suggest you look into the standard Authorization docs, it's got as much of a learning curve as most of the 3rd party solutions but ultimately works better/easier: https://laravel.com/docs/5.6/authorization

Lance Pioch
  • 1,147
  • 6
  • 18
  • Doesn’t his run the permission check for every input field I have in my form? My real form has a lot more fields. I don’t know if this is a reliable solution. – Salam May 03 '18 at 17:15