View source  
  <?php
namespace Drupal\Tests\simplesamlphp_auth\Unit\Service;
use Drupal\Tests\UnitTestCase;
use Drupal\user\UserInterface;
use Drupal\simplesamlphp_auth\Service\SimplesamlphpDrupalAuth;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Messenger\MessengerInterface;
class SimplesamlphpDrupalAuthTest extends UnitTestCase {
  
  protected $simplesaml;
  
  protected $entityTypeManager;
  
  protected $logger;
  
  protected $configFactory;
  
  protected $externalauth;
  
  protected $entityAccount;
  
  protected $messenger;
  
  protected $moduleHandler;
  
  protected function setUp() {
    parent::setUp();
    $this->entityTypeManager = $this
      ->createMock('\\Drupal\\Core\\Entity\\EntityTypeManagerInterface');
    $this->logger = $this
      ->getMockBuilder('\\Psr\\Log\\LoggerInterface')
      ->disableOriginalConstructor()
      ->getMock();
    $this->messenger = $this
      ->getMockBuilder(MessengerInterface::class)
      ->disableOriginalConstructor()
      ->getMock();
    $this->moduleHandler = $this
      ->getMockBuilder(ModuleHandlerInterface::class)
      ->disableOriginalConstructor()
      ->getMock();
    $this->moduleHandler
      ->expects($this
      ->any())
      ->method('alter');
    $this->simplesaml = $this
      ->getMockBuilder('\\Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpAuthManager')
      ->disableOriginalConstructor()
      ->getMock();
    $this->configFactory = $this
      ->getConfigFactoryStub([
      'simplesamlphp_auth.settings' => [
        'register_users' => TRUE,
        'activate' => TRUE,
        'mail_attr' => 'mail',
      ],
    ]);
    $this->externalauth = $this
      ->createMock('\\Drupal\\externalauth\\ExternalAuthInterface');
    
    $this->entityAccount = $this
      ->createMock('Drupal\\user\\UserInterface');
  }
  
  public function testExternalLoginRegister() {
    $this->externalauth
      ->expects($this
      ->once())
      ->method('login')
      ->will($this
      ->returnValue(FALSE));
    
    $simplesaml_drupalauth = $this
      ->getMockBuilder('Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpDrupalAuth')
      ->setMethods([
      'externalRegister',
    ])
      ->setConstructorArgs([
      $this->simplesaml,
      $this->configFactory,
      $this->entityTypeManager,
      $this->logger,
      $this->externalauth,
      $this->entityAccount,
      $this->messenger,
      $this->moduleHandler,
    ])
      ->getMock();
    
    $simplesaml_drupalauth
      ->expects($this
      ->once())
      ->method('externalRegister')
      ->will($this
      ->returnValue($this->entityAccount));
    
    $loaded_account = $simplesaml_drupalauth
      ->externalLoginRegister("testuser");
    $this
      ->assertTrue($loaded_account instanceof UserInterface);
  }
  
  public function testExternalLoginWithRoleMatch() {
    
    $config_factory = $this
      ->getConfigFactoryStub([
      'simplesamlphp_auth.settings' => [
        'register_users' => TRUE,
        'activate' => 1,
        'role.eval_every_time' => 1,
        'role.population' => 'student:eduPersonAffiliation,=,student',
      ],
    ]);
    
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('getRoles')
      ->will($this
      ->returnValue([
      'teacher',
    ]));
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('addRole')
      ->with($this
      ->equalTo('student'));
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('removeRole')
      ->with($this
      ->equalTo('teacher'));
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('save');
    $this->externalauth
      ->expects($this
      ->once())
      ->method('login')
      ->will($this
      ->returnValue($this->entityAccount));
    
    $simplesaml = $this
      ->getMockBuilder('\\Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpAuthManager')
      ->disableOriginalConstructor()
      ->setMethods([
      'getAttributes',
    ])
      ->getMock();
    
    $attributes = [
      'eduPersonAffiliation' => [
        'student',
      ],
    ];
    $simplesaml
      ->expects($this
      ->any())
      ->method('getAttributes')
      ->will($this
      ->returnValue($attributes));
    
    $simplesaml_drupalauth = $this
      ->getMockBuilder('Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpDrupalAuth')
      ->setMethods([
      'externalLoginFinalize',
    ])
      ->setConstructorArgs([
      $simplesaml,
      $config_factory,
      $this->entityTypeManager,
      $this->logger,
      $this->externalauth,
      $this->entityAccount,
      $this->messenger,
      $this->moduleHandler,
    ])
      ->getMock();
    
    $simplesaml_drupalauth
      ->externalLoginRegister("testuser");
  }
  
  public function testExternalRegister() {
    
    $entity_storage = $this
      ->createMock('Drupal\\Core\\Entity\\EntityStorageInterface');
    
    $entity_storage
      ->expects($this
      ->any())
      ->method('loadByProperties')
      ->will($this
      ->returnValue([]));
    $this->entityTypeManager
      ->expects($this
      ->any())
      ->method('getStorage')
      ->will($this
      ->returnValue($entity_storage));
    
    $externalauth = $this
      ->createMock('Drupal\\externalauth\\ExternalAuthInterface');
    
    $externalauth
      ->expects($this
      ->once())
      ->method('register')
      ->will($this
      ->returnValue($this->entityAccount));
    $externalauth
      ->expects($this
      ->once())
      ->method('userLoginFinalize')
      ->will($this
      ->returnValue($this->entityAccount));
    
    $simplesaml_drupalauth = $this
      ->getMockBuilder('Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpDrupalAuth')
      ->setMethods([
      'synchronizeUserAttributes',
    ])
      ->setConstructorArgs([
      $this->simplesaml,
      $this->configFactory,
      $this->entityTypeManager,
      $this->logger,
      $externalauth,
      $this->entityAccount,
      $this->messenger,
      $this->moduleHandler,
    ])
      ->getMock();
    
    $simplesaml_drupalauth
      ->expects($this
      ->once())
      ->method('synchronizeUserAttributes');
    
    $registered_account = $simplesaml_drupalauth
      ->externalRegister("testuser");
    $this
      ->assertTrue($registered_account instanceof UserInterface);
  }
  
  public function testExternalRegisterWithAutoEnableSaml() {
    $config_factory = $this
      ->getConfigFactoryStub([
      'simplesamlphp_auth.settings' => [
        'register_users' => TRUE,
        'activate' => TRUE,
        'autoenablesaml' => TRUE,
      ],
    ]);
    
    $entity_storage = $this
      ->createMock('Drupal\\Core\\Entity\\EntityStorageInterface');
    
    $entity_storage
      ->expects($this
      ->any())
      ->method('loadByProperties')
      ->will($this
      ->returnValue([
      $this->entityAccount,
    ]));
    $this->entityTypeManager
      ->expects($this
      ->any())
      ->method('getStorage')
      ->will($this
      ->returnValue($entity_storage));
    
    $externalauth = $this
      ->getMockBuilder('\\Drupal\\externalauth\\ExternalAuth')
      ->disableOriginalConstructor()
      ->setMethods([
      'register',
      'linkExistingAccount',
      'userLoginFinalize',
    ])
      ->getMock();
    
    $externalauth
      ->expects($this
      ->once())
      ->method('linkExistingAccount');
    $externalauth
      ->expects($this
      ->once())
      ->method('userLoginFinalize')
      ->will($this
      ->returnValue($this->entityAccount));
    
    $externalauth
      ->expects($this
      ->never())
      ->method('register');
    
    $simplesaml_drupalauth = $this
      ->getMockBuilder('Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpDrupalAuth')
      ->setMethods([
      'synchronizeUserAttributes',
    ])
      ->setConstructorArgs([
      $this->simplesaml,
      $config_factory,
      $this->entityTypeManager,
      $this->logger,
      $externalauth,
      $this->entityAccount,
      $this->messenger,
      $this->moduleHandler,
    ])
      ->getMock();
    
    $simplesaml_drupalauth
      ->expects($this
      ->once())
      ->method('synchronizeUserAttributes');
    $simplesaml_drupalauth
      ->externalRegister("test_authname");
  }
  
  public function testSynchronizeUserAttributes() {
    
    $simplesaml = $this
      ->getMockBuilder('\\Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpAuthManager')
      ->disableOriginalConstructor()
      ->setMethods([
      'getDefaultName',
      'getDefaultEmail',
    ])
      ->getMock();
    
    $simplesaml
      ->expects($this
      ->once())
      ->method('getDefaultName')
      ->will($this
      ->returnValue("Test name"));
    $simplesaml
      ->expects($this
      ->once())
      ->method('getDefaultEmail')
      ->will($this
      ->returnValue("test@example.com"));
    
    $entity_storage = $this
      ->createMock('Drupal\\Core\\Entity\\EntityStorageInterface');
    
    $entity_storage
      ->expects($this
      ->any())
      ->method('loadByProperties')
      ->will($this
      ->returnValue([]));
    $this->entityTypeManager
      ->expects($this
      ->any())
      ->method('getStorage')
      ->will($this
      ->returnValue($entity_storage));
    
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('setUsername')
      ->with($this
      ->equalTo("Test name"));
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('setEmail')
      ->with($this
      ->equalTo("test@example.com"));
    $this->entityAccount
      ->expects($this
      ->once())
      ->method('save');
    $simplesaml_drupalauth = new SimplesamlphpDrupalAuth($simplesaml, $this->configFactory, $this->entityTypeManager, $this->logger, $this->externalauth, $this->entityAccount, $this->messenger, $this->moduleHandler);
    $simplesaml_drupalauth
      ->synchronizeUserAttributes($this->entityAccount, TRUE);
  }
  
  public function testRoleMatching($rolemap, $attributes, $expected_roles) {
    
    $config_factory = $this
      ->getConfigFactoryStub([
      'simplesamlphp_auth.settings' => [
        'register_users' => TRUE,
        'activate' => 1,
        'role.population' => $rolemap,
      ],
    ]);
    
    $simplesaml = $this
      ->getMockBuilder('\\Drupal\\simplesamlphp_auth\\Service\\SimplesamlphpAuthManager')
      ->disableOriginalConstructor()
      ->setMethods([
      'getAttributes',
    ])
      ->getMock();
    
    $simplesaml
      ->expects($this
      ->any())
      ->method('getAttributes')
      ->will($this
      ->returnValue($attributes));
    $simplesaml_drupalauth = new SimplesamlphpDrupalAuth($simplesaml, $config_factory, $this->entityTypeManager, $this->logger, $this->externalauth, $this->entityAccount, $this->messenger, $this->moduleHandler);
    $matching_roles = $simplesaml_drupalauth
      ->getMatchingRoles();
    $this
      ->assertEquals(count($expected_roles), count($matching_roles), 'Number of expected roles matches');
    $this
      ->assertEquals($expected_roles, $matching_roles, 'Expected roles match');
  }
  
  public function roleMatchingDataProvider() {
    return [
      
      [
        'admin:userName,=,externalAdmin|test:something,=,something',
        [
          'userName' => [
            'externalAdmin',
          ],
        ],
        [
          'admin' => 'admin',
        ],
      ],
      
      [
        'employee:mail,@=,company.com',
        [
          'mail' => [
            'joe@company.com',
          ],
        ],
        [
          'employee' => 'employee',
        ],
      ],
      
      [
        'employee:mail,@=,company.com',
        [
          'mail' => [
            'joe@anothercompany.com',
          ],
        ],
        [],
      ],
      
      [
        'employee:affiliate,~=,xyz',
        [
          'affiliate' => [
            'abcd',
            'wxyz',
          ],
        ],
        [
          'employee' => 'employee',
        ],
      ],
      
      [
        'admin:userName,=,externalAdmin|employee:mail,@=,company.com',
        [
          'userName' => [
            'externalAdmin',
          ],
          'mail' => [
            'externalAdmin@company.com',
          ],
        ],
        [
          'admin' => 'admin',
          'employee' => 'employee',
        ],
      ],
      
      [
        'admin:domain,=,http://admindomain.com',
        [
          'domain' => [
            'http://admindomain.com',
            'http://drupal.org',
          ],
        ],
        [
          'admin' => 'admin',
        ],
      ],
    ];
  }
}