1

Part of a plugin I am writing needs to handle impersonating a user, in the same way that Craft offers the built in "Log in as X" for admins in the back end.

I have that working by essentially copying the /app/controllers/UsersController actionImpersonate() function into my plugin.

However, when the action is run, the newly logged in user is always being redirected to the homepage - which makes sense as it's the default page that front-end logins go to. But, I want to override it. I want my plugin to take them to a page I dynamically set. I can't seem to get it to happen. Here's my code:

public function actionMyAction()
{

    // basic security precautions
    $this->requirePostRequest();
    $this->requireAdmin();

    ... some stuff not relevant to the question ...

    // get the user we want to impersonate
    $originalUserId = craft()->userSession->getId();
    $orderOwnerId = $order->customer->user->id;

    // impersonate the user
    craft()->httpSession->add(UserSessionService::USER_IMPERSONATE_KEY, $originalUserId);

    if (craft()->userSession->loginByUserId($orderOwnerId))
    {
        craft()->userSession->setNotice(Craft::t('Logged in.'));
        // $this->_handleSuccessfulLogin(true);
        $this->redirectToPostedUrl();
    }
    else
    {
        craft()->httpSession->remove(UserSessionService::USER_IMPERSONATE_KEY);
        craft()->userSession->setError(Craft::t('There was a problem impersonating this user.'));
        Craft::log(craft()->userSession->getUser()->username.' tried to impersonate userId: '.$userId.' but something went wrong.', LogLevel::Error);
        }
    }
}

I'm expecting that to redirect the newly logged in user to the page that the form was posted from - but it doesn't. Also, and I don't know if it's related, if I uncomment the $this->_handleSuccessfulLogin(true); line I get an error. That line is not commented out in the original function, and looking at the Craft docs to try and learn what it does, it says the function is deprecated ( https://craftcms.com/classreference/services/UsersService#handleSuccessfulLogin-detail )

1

Since this is an action in your own plugin's controller, you can literally do anything you want after the login happens.

if (craft()->userSession->loginByUserId($orderOwnerId))
{
    $this->redirect('https://www.reddit.com/');
}

if I uncomment the $this->_handleSuccessfulLogin(true); line I get an error.

Because that's a private method you probably didn't copy over from Craft's UsersController.php. You don't have to use it if you don't want to.

it says the function is deprecated (https://craftcms.com/classreference/services/UsersService#handleSuccessfulLogin-detail)

Same method name (mostly), but not in the UsersController... it's on the UsersService. It's also public, not private.

| improve this answer | |
  • Thanks Brad, If that's the case, why doesn't $this->redirectToPostedUrl(); work? Am I right in understanding that should use the URL that was passed via a <input type='hidden' name='redirect' value='/wherever'> field in the form? – Matt Wilcox Nov 11 '16 at 9:59
1

AGH: my problem was only that the redirect value I was passing was incomplete, which caused the template I was redirecting to to itself redirect elsewhere.

Complete solution:

<form action="" method="POST">
    <input type="hidden" name="action" value="myplugin/mycontroller/myaction">
    <input type="hidden" name="redirect" value="{{ craft.request.path }}?{{ craft.request.queryStringWithoutPath }}">{# redirect back to this page #}
    <input type="hidden" name="orderNumber" value="{{ number }}">
    <input type="submit" class="button warning" value="Disable date restrictions &amp; impersonate customer"/>
</form>

The controller action:

public function actionMyAction()
{

    // basic security precautions
    $this->requirePostRequest();
    $this->requireAdmin();

    ... some stuff not relevant to the question ...

    // get the user we want to impersonate
    $originalUserId = craft()->userSession->getId();
    $orderOwnerId = $order->customer->user->id;

    // impersonate the user
    craft()->httpSession->add(UserSessionService::USER_IMPERSONATE_KEY, $originalUserId);

    if (craft()->userSession->loginByUserId($orderOwnerId))
    {
        craft()->userSession->setNotice(Craft::t('Logged in.'));
        $this->redirectToPostedUrl();
    }
    else
    {
        craft()->httpSession->remove(UserSessionService::USER_IMPERSONATE_KEY);
        craft()->userSession->setError(Craft::t('There was a problem impersonating this user.'));
        Craft::log(craft()->userSession->getUser()->username.' tried to impersonate userId: '.$userId.' but something went wrong.', LogLevel::Error);
        }
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.