Yii2: AccessControl errors returned nothing when using ajax

Created on 11 Jun 2018  路  4Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

Set AccessControl to not allowing login then we accessing login page from ajax modal

What is the expected result?

Showing message in ajax modal

What do you get instead?

Not Showing anything in ajax modal (but give an 403 error)

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.15
| PHP version | 7.2.5
| Operating system | Archlinux

Proposed Code:

change denyAccess function to:

    protected function denyAccess($user)
    {
        if ($user !== false && $user->getIsGuest()) {
            $user->loginRequired();
        } else {
            $message = Yii::t('yii', 'You are not allowed to perform this action.'); 
            if (Yii::$app->getRequest()->getIsAjax()) {
                echo $message;
            } else {
                throw new ForbiddenHttpException(Yii::t('yii', $message));
            }
        }
    }

Downside

We have returned value/message when using ajax, but we lose information about that page is 403.

Another solution

Create a doc how to override original denyAccess to user-version denyAccess that enabling ajax.

JS ready for adoption bug

All 4 comments

How do you try to display modal?

If you use jQuery you should use error callback as it is triggered when ajax response is error (eg. 403).

@paweljankowiak06: yes, I use jQuery ajax modal. But not really the ajax, but it derivative, load(). Below is my ajax-modal-popup.js code.:

$(function () {
    $('.showModalButton').click(function () {
        var target = $(this).attr('target');
        $('#' + target).load($(this).attr('value'));
        $('.' + target + '-toggle').toggle();
    });
    $('.closeModalButton').click(function () {
        var target = $(this).attr('target');
        $('#' + target).empty();
        $('.' + target + '-toggle').toggle();
    });

    $('.modalButton').on('click', function () {
        var title = $(this).attr('title');
        $('#modalTitle').text(title);
        $('.modal').modal('show')
            .find('#modalContent')
            .load($(this).attr('value'));
    });
});

Yes, we can use ajax error callback, but we lose something like:

  1. Translation that yii provide.
  2. We work twice: 1st controller throw errors, 2nd our js check ajax error responses and return error message accordingly. But, why not we just let controller throw the errors, and our js get then show the error messages?
  3. What if we want to throw custom error?

Thanks!

@tonny-sofijan

As I see in documentation load has second parameter which is error callback.

$("#modal").modal("show")
    .find(".modal-body")
    .load('/your-action', function (response, status, xhr) {
          // $(this) is .modal-body div
          $(this).html(response);
    });

In this case response will contain error message generated by Yii. If you want custom error just throw it in controller and status code will be in xhr.status.

To customize error message (eg. put it in alert alert-danger) you can override yii\web\ErrorHandler::renderAjaxResponse.

Hope this helps.

@paweljankowiak06: Just now tried your code. It works.
@samdark: looks like the initial code is perfect as it is. With @paweljankowiak06 code, not only it return the 403, it return the message too.

Thanks all. Turns out it's my ajax-fu that is less adequate.

Was this page helpful?
0 / 5 - 0 ratings