MODX. Авторизация с использованием Login

Данный метод взят у Ильи Уткина, с изменениями «для себя».

Создание структуры страниц

Для создания функционала авторизации понадобиться создать несколько рабочих страниц. Структуру их расположения в админ панели можно использовать свою, я предпочитаю такой вариант (код по ссылке):

  • Регистрация (2)

    [[!Register?
        &submitVar=`registerbtn`
        &activation=`10`
        &activationEmailSubject=`Подтверждение регистрации`
        &activationResourceId=`5`
        &successMsg=`Вам на почту отправлено письмо для подтверждение регистрации.`
        &usergroups=`Users`
        &validate=`nospam:blank,
          password:required:minLength=^8^,
          password_confirm:password_confirm=^password^,
          fullname:required,
          email:required:email`
        &usernameField=`email`
        &placeholderPrefix=`reg.`
    ]]
    
    [[!+error.message:eq=``:then=`
    <div class="register"><form action="[[*uri]]" method="post"><input name="nospam" type="hidden" value="[[!+reg.nospam]]" />
    <div class="clearfix"><label for="email">Электронная почта</label>
    <div class="input"><input name="email" type="text" value="[[!+reg.email]]" /> <span class="help-block text-error"> [[!+reg.error.email]] </span></div>
    </div>
    <div class="clearfix"><label for="password">Пароль</label>
    <div class="input"><input name="password" type="password" value="[[!+reg.password]]" /> <span class="help-block text-error"> [[!+reg.error.password]] </span></div>
    </div>
    <div class="clearfix"><label for="password_confirm">Пароль еще раз</label>
    <div class="input"><input name="password_confirm" type="password" value="[[!+reg.password_confirm]]" /> <span class="help-block text-error"> [[!+reg.error.password_confirm]] </span></div>
    </div>
    <div class="clearfix"><label for="fullname">Имя и фамилия</label>
    <div class="input"><input name="fullname" type="text" value="[[!+reg.fullname:Jevix]]" /> <span class="help-block text-error"> [[!+reg.error.fullname]] </span></div>
    </div>
    <div class="clearfix">
    <div class="form-buttons"><input class="btn primary" name="registerbtn" type="submit" value="Зарегистрироваться!" /></div>
    </div>
    </form></div>
    `:else=`
    <div class="alert alert-success">[[!+error.message]]</div>
    `]]
    • Подтверждение регистрации (5)

      [[!ConfirmRegister? &authenticate=`1` &errorPage=`4`]]
      <script type="text/javascript">
        setTimeout('document.getElementById("timer_inp").innerHTML = "через <b>4</b> секунды"', 1000);
        setTimeout('document.getElementById("timer_inp").innerHTML = "через <b>3</b> секунды"', 2000);
        setTimeout('document.getElementById("timer_inp").innerHTML = "через <b>2</b> секунды"', 3000);
        setTimeout('document.getElementById("timer_inp").innerHTML = "через <b>1</b> секунду"', 4000);
        setTimeout('document.getElementById("timer_inp").innerHTML = "<b>прямо сейчас</b>"', 5000);
        setTimeout('document.location.href="[[~4]]"', 5000);
      </script>
      
      <p>Страничка вашего <a href="[[~4]]">личного кабинета</a> откроется <span id="timer_inp">через <b>5</b> секунд</span></p>
      
    • Авторизация (3)

      [[!Login]]
      <p><a href="[[~6]]">Забыли пароль?</a></p>
    • Личный кабинет (4)

      [[!Profile]]
      <a href="[[~8]]" >Редактировать</a>
      <div class="form-horizontal well">
      <div class="row-fluid">
      <div class="span8 offset2">
        <div class="clearfix">
          <label class="control-label" for="fullname">Имя, фамилия</label>
          <div class="input" >
            <p >[[+fullname]]</p>
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="email">Email</label>
          <div class="input" >
            <p >[[+email]]</p>
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="password">Пароль</label>
          <div class="input" >
            <p ><a href="[[~7]]">Изменить пароль</a></p>
          </div>
        </div>
        [[+phone:notempty=`<div class="clearfix">
          <label class="control-label" for="phone">Телефон</label>
          <div class="input" >
            <p >[[+phone]]</p>
          </div>
        </div>`]]
        [[+mobilephone:notempty=`<div class="clearfix">
          <label class="control-label" for="mobilephone">Мобильный телефон</label>
          <div class="input" >
            <p >[[+mobilephone]]</p>
          </div>
        </div>`]]
        [[+country:notempty=`<div class="clearfix">
          <label class="control-label" for="country">Страна</label>
          <div class="input" >
            <p >[[+country:default=`Россия`]]</p>
          </div>
        </div>`]]
        [[+city:notempty=`<div class="clearfix">
          <label class="control-label" for="city">Город</label>
          <div class="input" >
            <p >[[+city]]</p>
          </div>
        </div>`]]
        [[+address:notempty=`<div class="clearfix">
          <label class="control-label" for="address">Адрес</label>
          <div class="input" >
            <p >[[+address]]</p>
          </div>
        </div>`]]
        [[+website:notempty=`<div class="clearfix">
          <label class="control-label" for="website">Сайт</label>
          <div class="input" >
            <p >[[+website:notempty=`<a href="http://[[+website]]">[[+website]]</a>`]]</p>
          </div>
        </div>`]]
      
      </div>
      </div>
      </div>
    • Восстановление пароля (6)

      [[!ResetPassword:empty=`[[!ForgotPassword? &resetResourceId=`[[*id]]`]]
      `]]
    • Изменение пароля (7)

      [[!ChangePassword?
         &submitVar=`change-password`
         &placeholderPrefix=`cp.`
         &validateOldPassword=`1`
         &validate=`nospam:blank`
      ]]
      
            <form class="callme" action="[[*uri]]" method="post">
              <input type="hidden" name="nospam" value="" />
              <div class="clearfix">
              <label for="password_old">Старый пароль</label>
              <div class="input">
                  <input type="password" name="password_old" id="password_old" value="[[+cp.password_old]]" />
                  <p class="help-block text-error">[[!+cp.error.password_old]]</p>
              </div>
              </div>
              
              <div class="clearfix">
              <label for="password_new">Новый пароль</label>
              <div class="input">
                  <input type="password" name="password_new" id="password_new" value="[[+cp.password_new]]" />
                  <p class="help-block text-error">[[!+cp.error.password_new]]</p>
              </div>
              </div>
              
              <div class="clearfix">
              <label for="password_new_confirm">Новый пароль еще раз</label>
              <div class="input">
                  <input type="password" name="password_new_confirm" id="password_new_confirm" value="[[+cp.password_new_confirm]]" />
                  <p class="help-block text-error">[[!+cp.error.password_new_confirm]]</p>
              </div>
              </div>
              
              <div class="clearfix">
              <div class="form-buttons">
                      <input type="submit" value="Сменить пароль!" name="change-password" class="btn primary"/>
              </div>
              </div>
             </form>
    • Редактирование профиля (8)

      [[!UpdateProfile]]
      <form class="form-horizontal well callme" action="[[*uri]]]" method="post">
      [[+login.update_success:eq=`1`:then=`<p>[[%login.profile_updated? &namespace=`login` &topic=`updateprofile`]]</p>
          <p>Вы будете перенаправлены в <a href="[[~4]]">личный кабинет</a> <span id="timer_inp">через <b>2</b> секунд</span></p>
          <script type="text/javascript">
            setTimeout('document.getElementById("timer_inp").innerHTML = "через <b>1</b> секунды"', 1000);
            setTimeout('document.getElementById("timer_inp").innerHTML = "<b>прямо сейчас</b>"', 2000);
            setTimeout('document.location.href="[[~4]]"', 2000);
          </script>
      `:else=``]]
      <div class="row-fluid">
      <div class="span8 offset2">
        [[+message]]
        <div class="clearfix">
          <label class="control-label" for="fullname">Имя, фамилия</label>
          <div class="input">
            <input type="text" name="fullname" id="fullname" value="[[+fullname]]">
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="phone">Телефон</label>
          <div class="input" >
            <input type="text" name="phone" id="phone" value="[[+phone]]">
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="mobilephone">Мобильный (второй) телефон</label>
          <div class="input" >
            <input type="text" name="mobilephone" id="mobilephone" value="[[+mobilephone]]">
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="country">Страна</label>
          <div class="input" >
            <input type="text"  name="country" id="country" value="[[+country:default=`Россия`]]">
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="city">Город</label>
          <div class="input" >
            <input type="text"  name="city" id="city" value="[[+city]]">
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="address">Адрес</label>
          <div class="input" >
            <input type="text"  name="address" id="address" value="[[+address]]">
            <p class="help-inline">Улица (проспект, переулок и пр.), дом, офис</p>
          </div>
        </div>
        <div class="clearfix">
          <label class="control-label" for="website">Сайт</label>
          <div class="input" >
            <input type="text"  name="website" id="website" value="[[+website]]">
          </div>
        </div>
      </div>
      <div class="clearfix">
      <div class="form-buttons">
              <input type="submit" value="Сохранить" class="btn primary"/>
      </div>
      </div>
      </div>
      </form>

У всех создаваемых ресурсов убираем галки «использовать визуальный редактор». 

  1. Страница регистрации — в параметре activationResourceId указываем id ресурса «Подтверждение регистрации»;
  2. Подтверждение регистрации — в трех местах указываем id ресурса «Личный кабинет»: в параметре errorPage, на 8 и на 11 строчках;
  3. Авторизация —  указываем правильную ссылку на страницу восстановления пароля;
  4. Личный кабинет — ссылки на редактирование и на смену пароля.

Создаем политику пользователей 

Заходим в системные настройки → «Контроль доступа», нажимаем кнопку «Новая группа пользователей», в поле «Имя» пишем Users, отмечаем галочку «Создать параллельную группу ресурсов», «Политика бэкенда» указываем (без политики). Сохраняем.

Идем в «Содержимое» → «Группы ресурсов» и перетаскиваем из правого дерева в группу «Users» следующие ресурсы:

  • Личный кабинет
      • Изменение пароля
      • Редактирование данных

Теперь если неавторизованный пользователь откроет одну из этих страниц, он увидит ошибку 404 — для него таких страниц не существует. Но нас такое поведение не устраивает. Мы хотим, чтобы при открытии страницы личного кабинета отображалась форма авторизации. Для этого идем в настройки системы и находим настройку unauthorized_page — Страница ошибки 403 «Доступ запрещен», и указываем в ней id страницы «Авторизация». У меня это — 3. Однако поведение все еще не изменится.

Просто анонимному пользователю MODX не хочет раскрывать информацию даже о том, что такой ресурс существует. Чтобы разрешить отображение ошибки 403, где это нужно, идем в «Системные настройки» → «Контроль доступа», нажимаем правой кнопкой мыши на группе (аноним) и выбираем «Редактировать». Переходим на вкладку «Доступ к группам ресурсов», добавляем группу:

  • Группа — Users,
  • контекст — web,
  • минимальная роль — Member,
  • политика доступа — Load only

Теперь при входе в личный кабинет нужно будет сначала ввести логин (e-mail) и пароль.