sqrl-2.0.0-rc1/src/Plugin/SqrlAction/Ident.php

src/Plugin/SqrlAction/Ident.php
<?php

namespace Drupal\sqrl\Plugin\SqrlAction;

use Drupal\Core\Entity\EntityStorageException;
use Drupal\sqrl\Entity\Identity;
use Drupal\sqrl\Exception\ClientException;
use Drupal\sqrl\SqrlActionPluginBase;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;

/**
 * Plugin implementation of the sqrl action "ident".
 *
 * @SqrlAction(
 *   id = "ident",
 *   label = @Translation("Ident"),
 *   description = @Translation("TBD.")
 * )
 */
class Ident extends SqrlActionPluginBase {

  /**
   * {@inheritdoc}
   *
   * @throws \JsonException
   */
  public function run(): bool {
    return match ($this->client->getNut()->getClientOperation()) {
      'register' => $this->register(),
      'login' => $this->login(),
      'link' => $this->setkey(),
      'unlink' => $this->unsetkey(),
      'profile' => ($this->client->getIdentity() !== NULL),
      default => FALSE,
    };
  }

  /**
   * Performs the login action.
   *
   * @return bool
   *   TRUE, if login was successful, FALSE otherwise.
   *
   * @throws \Drupal\sqrl\Exception\ClientException
   * @throws \JsonException
   */
  private function login(): bool {
    if ($this->client->getIdentity() === NULL) {
      return $this->register();
    }

    if (!$this->client->getIdentity()->isEnabled()) {
      throw new ClientException('SQRL disabled for this account');
    }

    $found_active_user = FALSE;
    foreach ($this->client->getIdentity()->getUsers() as $user) {
      if ($user->isActive()) {
        $found_active_user = TRUE;
        break;
      }
    }
    if (!$found_active_user) {
      return FALSE;
    }

    if (($this->client->getTif() & $this->client::FLAG_PIDK_MATCH) === $this->client::FLAG_PIDK_MATCH) {
      return $this->setkey();
    }
    return TRUE;
  }

  /**
   * Performs the register action.
   *
   * @return bool
   *   TRUE, if registration was successful, FALSE otherwise.
   *
   * @throws \Drupal\sqrl\Exception\ClientException
   * @throws \JsonException
   */
  private function register(): bool {
    if ($this->client->getIdentity() !== NULL) {
      return $this->login();
    }

    $registerMethod = $this->configFactory->get('user.settings')->get('register');
    if ($registerMethod === UserInterface::REGISTER_ADMINISTRATORS_ONLY) {
      // We can't create new accounts on this server.
      $this->log->debug('No user registration allowed!');
      return FALSE;
    }

    $userinfo = [
      'name' => '',
      'pass' => $this->random->string(32),
      'init' => '',
      'status' => $registerMethod === UserInterface::REGISTER_VISITORS,
      'access' => $this->time->getRequestTime(),
    ];
    $pattern = $this->configFactory->get('sqrl.settings')->get('account_name_pattern');
    if (!str_contains($pattern, '[rand]')) {
      $pattern .= '[rand]';
    }
    $length = $this->configFactory->get('sqrl.settings')->get('account_name_random_length');
    $user = NULL;
    while ($user === NULL) {
      $name = str_replace('[rand]', $this->random->name($length, TRUE), $pattern);
      if (mb_strlen($name) > UserInterface::USERNAME_MAX_LENGTH) {
        $name = mb_substr($name, 0, UserInterface::USERNAME_MAX_LENGTH);
      }
      if (!user_load_by_name($name)) {
        $userinfo['name'] = $userinfo['init'] = $name;
        $userinfo['mail'] = $this->identities->dummyMail();
        try {
          $user = User::create($userinfo);
          $user->save();
        }
        catch (\Exception) {
          // Do nothing, just retry.
          $user = NULL;
        }
      }
    }
    $this->account = $user;
    if ($this->setkey()) {
      if ($registerMethod === UserInterface::REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) {
        // New accounts require admin approval.
        $this->state->addMessage($this->sqrl->getNut()->getPublicNut(), $this->t('Account created, please wait for an administrator for approval of your account.'));
      }
      return TRUE;
    }
    return FALSE;
  }

  /**
   * Performs the set key action.
   *
   * @return bool
   *   TRUE, if set key action was successful, FALSE otherwise.
   *
   * @throws \Drupal\sqrl\Exception\ClientException
   */
  private function setkey(): bool {
    if ($this->account === NULL && $this->client->getIdentity() === NULL) {
      return FALSE;
    }
    if ($this->account !== NULL && $this->client->getIdentity() !== NULL && $this->identities->getIdentityByIdk($this->account->id())) {
      // Nothing changed and we have nothing to do.
      return TRUE;
    }
    if ($identity = $this->identities->getIdentityByIdk()) {
      // We know we do have the account as well, because from login (where we
      // don't know the account yet) we only get to setkey() when the client
      // request was matching a previous key.
      $identity->addUser($this->account);
    }
    else {
      $values = [
        'idk' => $this->client->getClientVar('idk'),
        'suk' => $this->client->getClientVar('suk'),
        'vuk' => $this->client->getClientVar('vuk'),
        'status' => TRUE,
      ];
      if ($this->account !== NULL) {
        $values['user'] = $this->account;
      }
      $identity = Identity::create($values);
    }
    try {
      if ($identity->save()) {
        if ($previous_identity = $this->identities->getIdentityByPidk()) {
          $previous_identity
            ->setSuccessor($identity)
            ->save();
          // Bring forward all linked user accounts to the new identity.
          $changed = FALSE;
          foreach ($previous_identity->getUsers() as $user) {
            if ($this->account === NULL || $user->id() !== $this->account->id()) {
              $identity->addUser($user);
              $changed = TRUE;
            }
          }
          if ($changed) {
            $identity->save();
          }
        }
        return TRUE;
      }
    }
    catch (EntityStorageException) {
    }
    // Saving previous id failed, undo everything.
    try {
      $identity->delete();
    }
    catch (EntityStorageException) {
    }
    throw new ClientException('Saving current or previous ID failed');
  }

  /**
   * Performs the unset key action.
   *
   * @return bool
   *   TRUE, if unset key action was successful, FALSE otherwise.
   */
  private function unsetkey(): bool {
    if ($this->client->getIdentity() === NULL) {
      return FALSE;
    }
    $this->client->getIdentity()->removeUser($this->account);
    return TRUE;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc