Browse Source

Add support for environment variable login

master-with-stable11-compat
Lukas Reschke 6 years ago
parent
commit
314ae475f6
No known key found for this signature in database
GPG Key ID: B9F6980CF6E759B1
  1. 35
      appinfo/app.php
  2. 7
      appinfo/info.xml
  3. 6
      appinfo/update.php
  4. 53
      js/admin.js
  5. 21
      lib/AppInfo/Application.php
  6. 96
      lib/Controller/SAMLController.php
  7. 30
      lib/Exceptions/NoUserFoundException.php
  8. 19
      lib/Settings/Admin.php
  9. 2
      lib/Settings/Section.php
  10. 3
      lib/samlsettings.php
  11. 6
      lib/userbackend.php
  12. 24
      templates/admin.php
  13. 1
      tests/AppInfo/ApplicationTest.php
  14. 246
      tests/Controller/SAMLControllerTest.php
  15. 45
      tests/Settings/AdminTest.php
  16. 2
      tests/Settings/SectionTest.php
  17. 549
      tests/clover.xml

35
appinfo/app.php

@ -21,6 +21,13 @@
require_once __DIR__ . '/../3rdparty/vendor/autoload.php';
// If we run in CLI mode do not setup the app as it can fail the OCC execution
// since the URLGenerator isn't accessible.
if(OC::$CLI) {
return;
}
$urlGenerator = \OC::$server->getURLGenerator();
$config = \OC::$server->getConfig();
$request = \OC::$server->getRequest();
@ -32,7 +39,7 @@ $samlSettings = new \OCA\User_SAML\SAMLSettings(
$userBackend = new \OCA\User_SAML\UserBackend(
$config,
\OC::$server->getURLGenerator(),
$urlGenerator,
\OC::$server->getSession(),
\OC::$server->getDb()
);
@ -41,17 +48,33 @@ OC_User::useBackend($userBackend);
OC_User::handleApacheAuth();
// Setting up the one login config may fail, if so, do not catch the requests later.
try {
$oneLoginSettings = new \OneLogin_Saml2_Settings($samlSettings->getOneLoginSettingsArray());
} catch(OneLogin_Saml2_Error $e) {
$returnScript = false;
$type = '';
switch($config->getAppValue('user_saml', 'type')) {
case 'saml':
try {
$oneLoginSettings = new \OneLogin_Saml2_Settings($samlSettings->getOneLoginSettingsArray());
} catch (OneLogin_Saml2_Error $e) {
$returnScript = true;
}
$type = 'saml';
break;
case 'environment-variable':
\OC::$server->getSession()->set('user_saml.samlUserData', $_SERVER);
$type = 'environment-variable';
break;
}
if($returnScript === true) {
return;
}
$redirectSituation = false;
// All requests that are not authenticated and match against the "/login" route are
// redirected to the SAML login endpoint
if(!$userSession->isLoggedIn() && \OC::$server->getRequest()->getPathInfo() === '/login') {
if(!$userSession->isLoggedIn() &&
\OC::$server->getRequest()->getPathInfo() === '/login' &&
$type === 'saml') {
$redirectSituation = true;
}

7
appinfo/info.xml

@ -1,11 +1,12 @@
<?xml version="1.0"?>
<info>
<id>user_saml</id>
<name>SAML authentication</name>
<description>Authenticates user against a SAML backend, such as Shibboleth.</description>
<name>SSO &amp; SAML authentication</name>
<description>Authenticates user against a SAML backend, such as Shibboleth or
other SSO solutions such as Kerberos.</description>
<licence>AGPL</licence>
<author>Lukas Reschke</author>
<version>1.2.1</version>
<version>1.2.2</version>
<dependencies>
<owncloud min-version="9.1" max-version="9.2" />
</dependencies>

6
appinfo/update.php

@ -28,3 +28,9 @@ $installedVersion = $config->getAppValue('user_saml', 'installed_version');
if (version_compare($installedVersion, '1.2.1', '<')) {
$config->setAppValue('user_saml', 'general-use_saml_auth_for_desktop', '1');
}
// Versions below 1.2.2 don't have the choice between environment variable or
// native SAML integration as the default was SAML back then.
if (version_compare($installedVersion, '1.2.2', '<')) {
$config->setAppValue('user_saml', 'type', 'saml');
}

53
js/admin.js

@ -5,6 +5,31 @@ function setSAMLConfigValue(category, setting, value) {
}
$(function() {
// Hide depending on the setup state
var type = $('#user-saml').data('type');
if(type !== '') {
$('#user-saml-choose-type').addClass('hidden');
$('#user-saml-warning-admin-user').removeClass('hidden');
} else {
$('#user-saml div:gt(2)').addClass('hidden');
$('#user-saml-settings .button').addClass('hidden');
}
if(type === 'environment-variable') {
$('#user-saml div:gt(4)').addClass('hidden');
$('#user-saml-settings .button').addClass('hidden');
}
$('#user-saml-choose-saml').click(function(e) {
e.preventDefault();
OC.AppConfig.setValue('user_saml', 'type', 'saml');
location.reload();
});
$('#user-saml-choose-env').click(function(e) {
e.preventDefault();
OC.AppConfig.setValue('user_saml', 'type', 'environment-variable');
location.reload();
});
// Enable tabs
$('input:checkbox[value="1"]').attr('checked', true);
@ -71,19 +96,21 @@ $(function() {
});
$('#user-saml').change(function() {
// Checks on each request whether the settings make sense or not
$.ajax({
url: OC.generateUrl('/apps/user_saml/saml/metadata'),
type: 'GET'
}).fail(function (e) {
if(e.status === 500) {
$('#user-saml-settings-complete').addClass('hidden');
$('#user-saml-settings-incomplete').removeClass('hidden');
}
}).success(function (e) {
$('#user-saml-settings-complete').removeClass('hidden');
$('#user-saml-settings-incomplete').addClass('hidden');
})
if(type === 'saml') {
// Checks on each request whether the settings make sense or not
$.ajax({
url: OC.generateUrl('/apps/user_saml/saml/metadata'),
type: 'GET'
}).fail(function (e) {
if (e.status === 500) {
$('#user-saml-settings-complete').addClass('hidden');
$('#user-saml-settings-incomplete').removeClass('hidden');
}
}).success(function (e) {
$('#user-saml-settings-complete').removeClass('hidden');
$('#user-saml-settings-incomplete').addClass('hidden');
})
}
});
$('#user-saml-settings .toggle').on('click', function() {

21
lib/AppInfo/Application.php

@ -33,27 +33,6 @@ class Application extends App {
parent::__construct('user_saml', $urlParams);
$container = $this->getContainer();
/**
* Controller
*/
$container->registerService('SAMLController', function(IAppContainer $c) {
/** @var \OC\Server $server */
$server = $c->query('ServerContainer');
return new SAMLController(
$c->getAppName(),
$server->getRequest(),
$server->getSession(),
$server->getUserSession(),
new SAMLSettings($server->getURLGenerator(), $server->getConfig()),
new UserBackend(
$server->getConfig(),
$server->getURLGenerator(),
$server->getSession(),
$server->getDb()
)
);
});
/**
* Middleware
*/

96
lib/controller/samlcontroller.php → lib/Controller/SAMLController.php

@ -21,12 +21,16 @@
namespace OCA\User_SAML\Controller;
use OCA\User_SAML\Exceptions\NoUserFoundException;
use OCA\User_SAML\SAMLSettings;
use OCA\User_SAML\UserBackend;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\IConfig;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\IUserSession;
class SAMLController extends Controller {
@ -38,6 +42,12 @@ class SAMLController extends Controller {
private $SAMLSettings;
/** @var UserBackend */
private $userBackend;
/** @var IConfig */
private $config;
/** @var IURLGenerator */
private $urlGenerator;
/** @var IUserManager */
private $userManager;
/**
* @param string $appName
@ -46,29 +56,92 @@ class SAMLController extends Controller {
* @param IUserSession $userSession
* @param SAMLSettings $SAMLSettings
* @param UserBackend $userBackend
* @param IConfig $config
* @param IURLGenerator $urlGenerator
* @param IUserManager $userManager
*/
public function __construct($appName,
IRequest $request,
ISession $session,
IUserSession $userSession,
SAMLSettings $SAMLSettings,
UserBackend $userBackend) {
UserBackend $userBackend,
IConfig $config,
IURLGenerator $urlGenerator,
IUserManager $userManager) {
parent::__construct($appName, $request);
$this->session = $session;
$this->userSession = $userSession;
$this->SAMLSettings = $SAMLSettings;
$this->userBackend = $userBackend;
$this->config = $config;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
}
/**
* @param array $auth
* @throws NoUserFoundException
*/
private function autoprovisionIfPossible(array $auth) {
$uidMapping = $this->config->getAppValue('user_saml', 'general-uid_mapping');
if(isset($auth[$uidMapping])) {
if(is_array($auth[$uidMapping])) {
$uid = $auth[$uidMapping][0];
} else {
$uid = $auth[$uidMapping];
}
$userExists = $this->userManager->userExists($uid);
if($userExists === true) {
return;
}
$autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed();
if(!$userExists && !$autoProvisioningAllowed) {
throw new NoUserFoundException();
} elseif(!$userExists && $autoProvisioningAllowed) {
$this->userBackend->createUserIfNotExists($uid);
return;
}
}
throw new NoUserFoundException();
}
/**
* @PublicPage
* @UseSession
* @OnlyUnauthenticatedUsers
*
* @return Http\RedirectResponse
* @throws \Exception
*/
public function login() {
$auth = new \OneLogin_Saml2_Auth($this->SAMLSettings->getOneLoginSettingsArray());
$ssoUrl = $auth->login(null, array(), false, false, true);
$this->session->set('user_saml.AuthNRequestID', $auth->getLastRequestID());
$type = $this->config->getAppValue($this->appName, 'type');
switch($type) {
case 'saml':
$auth = new \OneLogin_Saml2_Auth($this->SAMLSettings->getOneLoginSettingsArray());
$ssoUrl = $auth->login(null, [], false, false, true);
$this->session->set('user_saml.AuthNRequestID', $auth->getLastRequestID());
break;
case 'environment-variable':
$ssoUrl = $this->urlGenerator->getAbsoluteURL('/');
try {
$this->autoprovisionIfPossible($this->session->get('user_saml.samlUserData'));
} catch (NoUserFoundException $e) {
$ssoUrl = $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned');
}
break;
default:
throw new \Exception(
sprintf(
'Type of "%s" is not supported for user_saml',
$type
)
);
}
return new Http\RedirectResponse($ssoUrl);
}
@ -111,6 +184,7 @@ class SAMLController extends Controller {
if (!empty($errors)) {
print_r('<p>'.implode(', ', $errors).'</p>');
}
if (!$auth->isAuthenticated()) {
echo "<p>Not authenticated</p>";
exit();
@ -118,15 +192,11 @@ class SAMLController extends Controller {
// Check whether the user actually exists, if not redirect to an error page
// explaining the issue.
$uidMapping = \OC::$server->getConfig()->getAppValue('user_saml', 'general-uid_mapping', '');
if(isset($auth->getAttributes()[$uidMapping])) {
$uid = $auth->getAttributes()[$uidMapping][0];
$userExists = \OC::$server->getUserManager()->userExists($uid);
if(!$userExists && !$this->userBackend->autoprovisionAllowed()) {
return new Http\RedirectResponse(\OC::$server->getURLGenerator()->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
} elseif(!$userExists && $this->userBackend->autoprovisionAllowed()) {
$this->userBackend->createUserIfNotExists($uid);
}
try {
$this->autoprovisionIfPossible($auth->getAttributes());
} catch (NoUserFoundException $e) {
return new Http\RedirectResponse($this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.notProvisioned'));
}
$this->session->set('user_saml.samlUserData', $auth->getAttributes());

30
lib/Exceptions/NoUserFoundException.php

@ -0,0 +1,30 @@
<?php
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\User_SAML\Exceptions;
/**
* Class NoUserFoundException is thrown when no user has been found
*
* @package OCA\User_SAML\Exceptions
*/
class NoUserFoundException extends \Exception {
}

19
lib/Settings/Admin.php

@ -25,6 +25,7 @@ namespace OCA\User_SAML\Settings;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IL10N;
use OCP\Settings\ISettings;
@ -33,15 +34,20 @@ class Admin implements ISettings {
private $l10n;
/** @var Defaults */
private $defaults;
/** @var IConfig */
private $config;
/**
* @param IL10N $l10n
* @param Defaults $defaults
* @param IConfig $config
*/
public function __construct(IL10N $l10n,
Defaults $defaults) {
Defaults $defaults,
IConfig $config) {
$this->l10n = $l10n;
$this->defaults = $defaults;
$this->config = $config;
}
/**
@ -77,17 +83,22 @@ class Admin implements ISettings {
'text' => $this->l10n->t('Only allow authentication if an account is existent on some other backend. (e.g. LDAP)'),
'type' => 'checkbox',
],
'use_saml_auth_for_desktop' => [
];
$type = $this->config->getAppValue('user_saml', 'type');
if($type === 'saml') {
$generalSettings['use_saml_auth_for_desktop'] = [
'text' => $this->l10n->t('Use SAML auth for the %s desktop clients (requires user re-authentication)', [$this->defaults->getName()]),
'type' => 'checkbox',
],
];
];
}
$params = [
'sp' => $serviceProviderFields,
'security-offer' => $securityOfferFields,
'security-required' => $securityRequiredFields,
'general' => $generalSettings,
'type' => $type,
];
return new TemplateResponse('user_saml', 'admin', $params);

2
lib/Settings/Section.php

@ -48,7 +48,7 @@ class Section implements ISection {
* {@inheritdoc}
*/
public function getName() {
return $this->l->t('SAML authentication');
return $this->l->t('SSO & SAML authentication');
}
/**

3
lib/samlsettings.php

@ -43,7 +43,7 @@ class SAMLSettings {
public function getOneLoginSettingsArray() {
$settings = [
// 'debug' => true,
'debug' => true,
// 'strict' => true,
'security' => [
'nameIdEncrypted' => ($this->config->getAppValue('user_saml', 'security-nameIdEncrypted', '0') === '1') ? true : false,
@ -57,6 +57,7 @@ class SAMLSettings {
'wantNameId' => ($this->config->getAppValue('user_saml', 'security-wantNameId', '0') === '1') ? true : false,
'wantNameIdEncrypted' => ($this->config->getAppValue('user_saml', 'security-wantNameIdEncrypted', '0') === '1') ? true : false,
'wantXMLValidation' => ($this->config->getAppValue('user_saml', 'security-wantXMLValidation', '0') === '1') ? true : false,
'requestedAuthnContext' => false,
],
'sp' => [
'entityId' => $this->urlGenerator->linkToRouteAbsolute('user_saml.SAML.getMetadata'),

6
lib/userbackend.php

@ -301,7 +301,11 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
$uidMapping = $this->config->getAppValue('user_saml', 'general-uid_mapping', '');
if($uidMapping !== '' && isset($samlData[$uidMapping])) {
$uid = $samlData[$uidMapping][0];
if(is_array($samlData[$uidMapping])) {
$uid = $samlData[$uidMapping][0];
} else {
$uid = $samlData[$uidMapping];
}
if($this->userExists($uid)) {
return $uid;
}

24
templates/admin.php

@ -4,11 +4,30 @@ style('user_saml', 'admin');
/** @var array $_ */
?>
<form id="user-saml" class="section" action="#" method="post">
<h2 class="inlineblock"><?php p($l->t('SAML')); ?></h2>
<form id="user-saml" class="section" action="#" method="post" data-type="<?php p($_['type']) ?>">
<h2 class="inlineblock"><?php p($l->t('SSO & SAML authentication')); ?></h2>
<div id="user-saml-save-indicator" class="msg success inlineblock" style="display: none;">Saved</div>
<div id="user-saml-settings">
<div id="user-saml-choose-type">
<?php p($l->t('Please choose whether you want to authenticate using the SAML provider built-in in Nextcloud or whether you want to authenticate against an environment variable.')) ?>
<br/>
<button id="user-saml-choose-saml"><?php p($l->t('Use built-in SAML authentication')) ?></button>
<button id="user-saml-choose-env"><?php p($l->t('Use environment variable')) ?></button>
</div>
<div class="warning hidden" id="user-saml-warning-admin-user">
<?php p(
$l->t(
'Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account won\'t be possible anymore.',
[
$theme->getEntity()
]
)
)
?>
</div>
<div id="user-saml-general">
<h3><?php p($l->t('General')) ?></h3>
<?php foreach($_['general'] as $key => $attribute): ?>
@ -26,6 +45,7 @@ style('user_saml', 'admin');
<!-- FIXME: Add "Disable timeout from SAML" switch (checked by default)-->
</div>
<div id="user-saml-sp">
<h3><?php p($l->t('Service Provider Data')) ?></h3>
<p>

1
tests/AppInfo/ApplicationTest.php

@ -47,7 +47,6 @@ class ApplicationTest extends \Test\TestCase {
public function queryData() {
return [
['SAMLController', SAMLController::class],
['OnlyLoggedInMiddleware', OnlyLoggedInMiddleware::class],
];

246
tests/Controller/SAMLControllerTest.php

@ -0,0 +1,246 @@
<?php
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\User_SAML\Tests\Controller;
use OCA\User_SAML\Controller\SAMLController;
use OCA\User_SAML\SAMLSettings;
use OCA\User_SAML\UserBackend;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\IConfig;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserBackend;
use OCP\IUserManager;
use OCP\IUserSession;
use Test\TestCase;
class SAMLControllerTest extends TestCase {
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
private $request;
/** @var ISession|\PHPUnit_Framework_MockObject_MockObject */
private $session;
/** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
private $userSession;
/** @var SAMLSettings|\PHPUnit_Framework_MockObject_MockObject*/
private $samlSettings;
/** @var UserBackend|\PHPUnit_Framework_MockObject_MockObject */
private $userBackend;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
private $userManager;
/** @var SAMLController */
private $samlController;
public function setUp() {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->session = $this->createMock(ISession::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->samlSettings = $this->createMock(SAMLSettings::class);
$this->userBackend = $this->createMock(UserBackend::class);
$this->config = $this->createMock(IConfig::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->samlController = new SAMLController(
'user_saml',
$this->request,
$this->session,
$this->userSession,
$this->samlSettings,
$this->userBackend,
$this->config,
$this->urlGenerator,
$this->userManager
);
}
/**
* @expectedExceptionMessage Type of "UnknownValue" is not supported for user_saml
* @expectedException \Exception
*/
public function testLoginWithInvalidAppValue() {
$this->config
->expects($this->once())
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('UnknownValue');
$this->samlController->login();
}
public function testLoginWithEnvVariableAndExistingUser() {
$this->config
->expects($this->at(0))
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('environment-variable');
$this->session
->expects($this->once())
->method('get')
->with('user_saml.samlUserData')
->willReturn([
'foo' => 'bar',
'uid' => 'MyUid',
'bar' => 'foo',
]);
$this->config
->expects($this->at(1))
->method('getAppValue')
->with('user_saml', 'general-uid_mapping')
->willReturn('uid');
$this->userManager
->expects($this->once())
->method('userExists')
->with('MyUid')
->willReturn(true);
$this->urlGenerator
->expects($this->once())
->method('getAbsoluteURL')
->with('/')
->willReturn('https://nextcloud.com/absolute/');
$expected = new RedirectResponse('https://nextcloud.com/absolute/');
$this->assertEquals($expected, $this->samlController->login());
}
public function testLoginWithEnvVariableAndExistingUserAndArray() {
$this->config
->expects($this->at(0))
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('environment-variable');
$this->session
->expects($this->once())
->method('get')
->with('user_saml.samlUserData')
->willReturn([
'foo' => 'bar',
'uid' => ['MyUid'],
'bar' => 'foo',
]);
$this->config
->expects($this->at(1))
->method('getAppValue')
->with('user_saml', 'general-uid_mapping')
->willReturn('uid');
$this->userManager
->expects($this->once())
->method('userExists')
->with('MyUid')
->willReturn(true);
$this->urlGenerator
->expects($this->once())
->method('getAbsoluteURL')
->with('/')
->willReturn('https://nextcloud.com/absolute/');
$expected = new RedirectResponse('https://nextcloud.com/absolute/');
$this->assertEquals($expected, $this->samlController->login());
}
public function testLoginWithEnvVariableAndNotExistingUserWithProvisioning() {
$this->config
->expects($this->at(0))
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('environment-variable');
$this->session
->expects($this->once())
->method('get')
->with('user_saml.samlUserData')
->willReturn([
'foo' => 'bar',
'uid' => 'MyUid',
'bar' => 'foo',
]);
$this->config
->expects($this->at(1))
->method('getAppValue')
->with('user_saml', 'general-uid_mapping')
->willReturn('uid');
$this->userManager
->expects($this->once())
->method('userExists')
->with('MyUid')
->willReturn(false);
$this->urlGenerator
->expects($this->once())
->method('getAbsoluteURL')
->with('/')
->willReturn('https://nextcloud.com/absolute/');
$this->userBackend
->expects($this->at(0))
->method('autoprovisionAllowed')
->willReturn(true);
$this->userBackend
->expects($this->at(1))
->method('createUserIfNotExists')
->with('MyUid');
$expected = new RedirectResponse('https://nextcloud.com/absolute/');
$this->assertEquals($expected, $this->samlController->login());
}
public function testLoginWithEnvVariableAndNotExistingUserWithoutProvisioning() {
$this->config
->expects($this->at(0))
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('environment-variable');
$this->session
->expects($this->once())
->method('get')
->with('user_saml.samlUserData')
->willReturn([
'foo' => 'bar',
'uid' => 'MyUid',
'bar' => 'foo',
]);
$this->config
->expects($this->at(1))
->method('getAppValue')
->with('user_saml', 'general-uid_mapping')
->willReturn('uid');
$this->userManager
->expects($this->once())
->method('userExists')
->with('MyUid')
->willReturn(false);
$this->urlGenerator
->expects($this->once())
->method('linkToRouteAbsolute')
->with('user_saml.SAML.notProvisioned')
->willReturn('https://nextcloud.com/notprovisioned/');
$this->userBackend
->expects($this->once())
->method('autoprovisionAllowed')
->willReturn(false);
$expected = new RedirectResponse('https://nextcloud.com/notprovisioned/');
$this->assertEquals($expected, $this->samlController->login());
}
}

45
tests/Settings/AdminTest.php

@ -23,6 +23,7 @@ namespace OCA\User_SAML\Tests\Settings;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IL10N;
class AdminTest extends \Test\TestCase {
@ -32,30 +33,30 @@ class AdminTest extends \Test\TestCase {
private $l10n;
/** @var Defaults|\PHPUnit_Framework_MockObject_MockObject */
private $defaults;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
public function setUp() {
$this->l10n = $this->createMock(IL10N::class);
$this->defaults = $this->createMock(Defaults::class);
$this->config = $this->createMock(IConfig::class);
$this->admin = new \OCA\User_SAML\Settings\Admin(
$this->l10n,
$this->defaults
$this->defaults,
$this->config
);
return parent::setUp();
}
public function testGetForm() {
public function formDataProvider() {
$this->l10n
->expects($this->any())
->method('t')
->will($this->returnCallback(function($text, $parameters = array()) {
return vsprintf($text, $parameters);
}));
$this->defaults
->expects($this->once())
->method('getName')
->willReturn('Nextcloud');
$serviceProviderFields = [
'x509cert' => 'X.509 certificate of the Service Provider',
@ -99,6 +100,38 @@ class AdminTest extends \Test\TestCase {
'general' => $generalSettings,
];
return $params;
}
public function testGetFormWithoutType() {
$this->config
->expects($this->once())
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('');
$params = $this->formDataProvider();
unset($params['general']['use_saml_auth_for_desktop']);
$params['type'] = '';
$expected = new TemplateResponse('user_saml', 'admin', $params);
$this->assertEquals($expected, $this->admin->getForm());
}
public function testGetFormWithSaml() {
$this->defaults
->expects($this->once())
->method('getName')
->willReturn('Nextcloud');
$this->config
->expects($this->once())
->method('getAppValue')
->with('user_saml', 'type')
->willReturn('saml');
$params = $this->formDataProvider();
$params['type'] = 'saml';
$expected = new TemplateResponse('user_saml', 'admin', $params);
$this->assertEquals($expected, $this->admin->getForm());
}

2
tests/Settings/SectionTest.php

@ -44,7 +44,7 @@ class SectionTest extends \Test\TestCase {
$this->l10n
->expects($this->once())
->method('t')
->with('SAML authentication')
->with('SSO & SAML authentication')
->willReturn('SAML authentication');
$this->assertSame('SAML authentication', $this->section->getName());

549
tests/clover.xml

@ -0,0 +1,549 @@
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1479117325">
<project timestamp="1479117325">
<file name="/media/psf/stable9/apps/user_saml/appinfo/app.php">
<line num="22" type="stmt" count="0"/>
<line num="26" type="stmt" count="0"/>
<line num="27" type="stmt" count="0"/>
<line num="28" type="stmt" count="0"/>
<line num="30" type="stmt" count="0"/>
<line num="31" type="stmt" count="0"/>
<line num="32" type="stmt" count="0"/>
<line num="33" type="stmt" count="0"/>
<line num="34" type="stmt" count="0"/>
<line num="35" type="stmt" count="0"/>
<line num="36" type="stmt" count="0"/>
<line num="37" type="stmt" count="0"/>
<line num="39" type="stmt" count="0"/>
<line num="40" type="stmt" count="0"/>
<line num="41" type="stmt" count="0"/>
<line num="42" type="stmt" count="0"/>
<line num="43" type="stmt" count="0"/>
<line num="44" type="stmt" count="0"/>
<line num="45" type="stmt" count="0"/>
<line num="46" type="stmt" count="0"/>
<line num="47" type="stmt" count="0"/>
<line num="50" type="stmt" count="0"/>
<line num="51" type="stmt" count="0"/>
<line num="52" type="stmt" count="0"/>
<line num="53" type="stmt" count="0"/>
<line num="54" type="stmt" count="0"/>
<line num="55" type="stmt" count="0"/>
<line num="56" type="stmt" count="0"/>
<line num="57" type="stmt" count="0"/>
<line num="58" type="stmt" count="0"/>
<line num="59" type="stmt" count="0"/>
<line num="60" type="stmt" count="0"/>
<line num="61" type="stmt" count="0"/>
<line num="62" type="stmt" count="0"/>
<line num="63" type="stmt" count="0"/>
<line num="64" type="stmt" count="0"/>
<line num="65" type="stmt" count="0"/>
<line num="67" type="stmt" count="0"/>
<line num="68" type="stmt" count="0"/>
<line num="69" type="stmt" count="0"/>
<line num="71" type="stmt" count="0"/>
<line num="74" type="stmt" count="0"/>
<line num="75" type="stmt" count="0"/>
<line num="76" type="stmt" count="0"/>
<line num="77" type="stmt" count="0"/>
<line num="78" type="stmt" count="0"/>
<line num="87" type="stmt" count="0"/>
<line num="88" type="stmt" count="0"/>
<line num="89" type="stmt" count="0"/>
<line num="90" type="stmt" count="0"/>
<line num="91" type="stmt" count="0"/>
<line num="92" type="stmt" count="0"/>
<line num="93" type="stmt" count="0"/>
<line num="94" type="stmt" count="0"/>
<line num="95" type="stmt" count="0"/>
<line num="97" type="stmt" count="0"/>
<line num="98" type="stmt" count="0"/>
<line num="99" type="stmt" count="0"/>
<line num="100" type="stmt" count="0"/>
<metrics loc="100" ncloc="57" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="59" coveredstatements="0" elements="59" coveredelements="0"/>
</file>
<file name="/media/psf/stable9/apps/user_saml/appinfo/routes.php">
<line num="24" type="stmt" count="0"/>
<line num="25" type="stmt" count="0"/>
<line num="26" type="stmt" count="0"/>
<line num="27" type="stmt" count="0"/>
<line num="28" type="stmt" count="0"/>
<line num="29" type="stmt" count="0"/>
<line num="30" type="stmt" count="0"/>
<line num="31" type="stmt" count="0"/>
<line num="32" type="stmt" count="0"/>
<line num="33" type="stmt" count="0"/>
<line num="34" type="stmt" count="0"/>
<line num="35" type="stmt" count="0"/>
<line num="36" type="stmt" count="0"/>
<line num="37" type="stmt" count="0"/>
<line num="38" type="stmt" count="0"/>
<line num="39" type="stmt" count="0"/>
<line num="40" type="stmt" count="0"/>
<line num="41" type="stmt" count="0"/>
<line num="42" type="stmt" count="0"/>
<line num="43" type="stmt" count="0"/>
<line num="44" type="stmt" count="0"/>
<line num="45" type="stmt" count="0"/>
<line num="46" type="stmt" count="0"/>
<line num="47" type="stmt" count="0"/>
<line num="48" type="stmt" count="0"/>
<line num="49" type="stmt" count="0"/>
<line num="50" type="stmt" count="0"/>
<line num="51" type="stmt" count="0"/>
<line num="52" type="stmt" count="0"/>
<line num="53" type="stmt" count="0"/>
<line num="54" type="stmt" count="0"/>
<line num="55" type="stmt" count="0"/>
<metrics loc="56" ncloc="37" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="32" coveredstatements="0" elements="32" coveredelements="0"/>
</file>
<file name="/media/psf/stable9/apps/user_saml/appinfo/update.php">
<line num="22" type="stmt" count="0"/>
<line num="23" type="stmt" count="0"/>
<line num="28" type="stmt" count="0"/>
<line num="29" type="stmt" count="0"/>
<line num="30" type="stmt" count="0"/>
<line num="34" type="stmt" count="0"/>
<line num="35" type="stmt" count="0"/>
<line num="36" type="stmt" count="0"/>
<metrics loc="36" ncloc="7" classes="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="8" coveredstatements="0" elements="8" coveredelements="0"/>
</file>
<package name="OCA\User_SAML\AppInfo">
<file name="/media/psf/stable9/apps/user_saml/lib/AppInfo/Application.php">
<class name="Application" namespace="OCA\User_SAML\AppInfo">
<metrics complexity="2" methods="2" coveredmethods="2" conditionals="0" coveredconditionals="0" statements="6" coveredstatements="6" elements="8" coveredelements="8"/>
</class>
<line num="32" type="method" name="__construct" visibility="public" complexity="1" crap="1" count="2"/>
<line num="33" type="stmt" count="2"/>
<line num="34" type="stmt" count="2"/>
<line num="39" type="method" name="anonymous function" complexity="1" crap="1" count="2"/>
<line num="40" type="stmt" count="1"/>
<line num="41" type="stmt" count="1"/>
<line num="42" type="stmt" count="1"/>
<line num="44" type="stmt" count="2"/>
<line num="45" type="stmt" count="2"/>
<line num="46" type="stmt" count="2"/>
<metrics loc="47" ncloc="25" classes="1" methods="2" coveredmethods="2" conditionals="0" coveredconditionals="0" statements="8" coveredstatements="8" elements="10" coveredelements="10"/>
</file>
</package>
<package name="OCA\User_SAML\Controller">
<file name="/media/psf/stable9/apps/user_saml/lib/Controller/SAMLController.php">
<class name="SAMLController" namespace="OCA\User_SAML\Controller">
<metrics complexity="24" methods="7" coveredmethods="1" conditionals="0" coveredconditionals="0" statements="78" coveredstatements="34" elements="85" coveredelements="35"/>
</class>
<line num="63" type="method" name="__construct" visibility="public" complexity="1" crap="1" count="5"/>
<line num="72" type="stmt" count="5"/>
<line num="73" type="stmt" count="5"/>
<line num="74" type="stmt" count="5"/>
<line num="75" type="stmt" count="5"/>
<line num="76" type="stmt" count="5"/>
<line num="77" type="stmt" count="5"/>
<line num="78" type="stmt" count="5"/>
<line num="79" type="stmt" count="5"/>
<line num="80" type="stmt" count="5"/>
<line num="86" type="method" name="autoprovisionIfPossible" visibility="private" complexity="8" crap="8.02" count="4"/>
<line num="87" type="stmt" count="4"/>
<line num="88" type="stmt" count="4"/>
<line num="89" type="stmt" count="4"/>
<line num="90" type="stmt" count="1"/>
<line num="92" type="stmt" count="3"/>
<line num="95" type="stmt" count="4"/>
<line num="96" type="stmt" count="4"/>
<line num="97" type="stmt" count="2"/>
<line num="100" type="stmt" count="2"/>
<line num="101" type="stmt" count="2"/>
<line num="102" type="stmt" count="1"/>
<line num="103" type="stmt" count="1"/>
<line num="104" type="stmt" count="1"/>
<line num="105" type="stmt" count="1"/>
<line num="109" type="stmt" count="0"/>
<line num="120" type="method" name="login" visibility="public" complexity="4" crap="4.30" count="5"/>
<line num="121" type="stmt" count="5"/>
<line num="123" type="stmt" count="5"/>
<line num="124" type="stmt" count="0"/>
<line num="125" type="stmt" count="0"/>
<line num="126" type="stmt" count="0"/>
<line num="127" type="stmt" count="0"/>
<line num="128" type="stmt" count="5"/>
<line num="129" type="stmt" count="4"/>
<line num="131" type="stmt" count="4"/>
<line num="132" type="stmt" count="1"/>
<line num="133" type="stmt" count="1"/>
<line num="135" type="stmt" count="4"/>
<line num="137" type="stmt" count="1"/>
<line num="139" type="stmt" count="1"/>
<line num="145" type="stmt" count="4"/>
<line num="152" type="method" name="getMetadata" visibility="public" complexity="2" crap="6" count="0"/>
<line num="153" type="stmt" count="0"/>
<line num="154" type="stmt" count="0"/>
<line num="155" type="stmt" count="0"/>
<line num="156" type="stmt" count="0"/>
<line num="157" type="stmt" count="0"/>
<line num="159" type="stmt" count="0"/>
<line num="160" type="stmt" count="0"/>
<line num="161" type="stmt" count="0"/>
<line num="172" type="method" name="assertionConsumerService" visibility="public" complexity="7" crap="56" count="0"/>
<line num="173" type="stmt" count="0"/>
<line num="174" type="stmt" count="0"/>
<line num="175" type="stmt" count="0"/>
<line num="178" type="stmt" count="0"/>
<line num="179" type="stmt" count="0"/>
<line num="181" type="stmt" count="0"/>
<line num="184" type="stmt" count="0"/>
<line num="185" type="stmt" count="0"/>
<line num="187" type="stmt" count="0"/>
<line num="188" type="stmt" count="0"/>
<line num="189" type="stmt" count="0"/>
<line num="195" type="stmt" count="0"/>
<line num="196" type="stmt" count="0"/>
<line num="197" type="stmt" count="0"/>
<line num="201" type="stmt" count="0"/>
<line num="202" type="stmt" count="0"/>
<line num="203" type="stmt" count="0"/>
<line num="204" type="stmt" count="0"/>
<line num="206" type="stmt" count="0"/>
<line num="209" type="stmt" count="0"/>
<line num="210" type="stmt" count="0"/>
<line num="212" type="stmt" count="0"/>
<line num="218" type="method" name="singleLogoutService" visibility="public" complexity="1" crap="2" count="0"/>
<line num="219" type="stmt" count="0"/>
<line num="220" type="stmt" count="0"/>
<line num="221" type="stmt" count="0"/>
<line num="222" type="stmt" count="0"/>
<line num="223" type="stmt" count="0"/>
<line num="224" type="stmt" count="0"/>
<line num="225" type="stmt" count="0"/>
<line num="226" type="stmt" count="0"/>
<line num="233" type="method" name="notProvisioned" visibility="public" complexity="1" crap="2" count="0"/>
<line num="234" type="stmt" count="0"/>
<metrics loc="236" ncloc="159" classes="1" methods="7" coveredmethods="1" conditionals="0" coveredconditionals="0" statements="78" coveredstatements="34" elements="85" coveredelements="35"/>
</file>
</package>
<package name="OCA\User_SAML\Exceptions">
<file name="/media/psf/stable9/apps/user_saml/lib/Exceptions/NoUserFoundException.php">
<class name="NoUserFoundException" namespace="OCA\User_SAML\Exceptions" fullPackage="OCA" package="OCA">
<metrics complexity="0" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" elements="0" coveredelements="0"/>
</class>
<metrics loc="30" ncloc="6" classes="1" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" elements="0" coveredelements="0"/>
</file>
</package>
<package name="OCA\User_SAML\Middleware">
<file name="/media/psf/stable9/apps/user_saml/lib/Middleware/OnlyLoggedInMiddleware.php">
<class name="OnlyLoggedInMiddleware" namespace="OCA\User_SAML\Middleware" fullPackage="OCA" package="OCA">
<metrics complexity="6" methods="3" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="9" elements="12" coveredelements="12"/>
</class>
<line num="45" type="method" name="__construct" visibility="public" complexity="1" crap="1" count="6"/>
<line num="47" type="stmt" count="6"/>
<line num="48" type="stmt" count="6"/>
<line num="49" type="stmt" count="6"/>
<line num="56" type="method" name="beforeController" visibility="public" complexity="3" crap="3" count="3"/>
<line num="57" type="stmt" count="3"/>
<line num="58" type="stmt" count="1"/>
<line num="60" type="stmt" count="2"/>
<line num="69" type="method" name="afterException" visibility="public" complexity="2" crap="2" count="2"/>
<line num="70" type="stmt" count="2"/>
<line num="71" type="stmt" count="1"/>
<line num="74" type="stmt" count="1"/>
<metrics loc="76" ncloc="33" classes="1" methods="3" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="9" elements="12" coveredelements="12"/>
</file>
</package>
<package name="OCA\User_SAML\Settings">
<file name="/media/psf/stable9/apps/user_saml/lib/Settings/Admin.php">
<class name="Admin" namespace="OCA\User_SAML\Settings">
<metrics complexity="5" methods="4" coveredmethods="4" conditionals="0" coveredconditionals="0" statements="35" coveredstatements="35" elements="39" coveredelements="39"/>
</class>
<line num="45" type="method" name="__construct" visibility="public" complexity="1" crap="1" count="4"/>
<line num="48" type="stmt" count="4"/>
<line num="49" type="stmt" count="4"/>
<line num="50" type="stmt" count="4"/>
<line num="51" type="stmt" count="4"/>
<line num="56" type="method" name="getForm" visibility="public" complexity="2" crap="2" count="2"/>
<line num="58" type="stmt" count="2"/>
<line num="59" type="stmt" count="2"/>
<line num="62" type="stmt" count="2"/>
<line num="63" type="stmt" count="2"/>
<line num="64" type="stmt" count="2"/>
<line num="65" type="stmt" count="2"/>
<line num="66" type="stmt" count="2"/>
<line num="69" type="stmt" count="2"/>
<line num="70" type="stmt" count="2"/>
<line num="71" type="stmt" count="2"/>
<line num="72" type="stmt" count="2"/>
<line num="73" type="stmt" count="2"/>
<line num="74" type="stmt" count="2"/>
<line num="78" type="stmt" count="2"/>
<line num="79" type="stmt" count="2"/>
<line num="81" type="stmt" count="2"/>
<line num="83" type="stmt" count="2"/>
<line num="84" type="stmt" count="2"/>
<line num="88" type="stmt" count="2"/>
<line num="89" type="stmt" count="2"/>
<line num="90" type="stmt" count="1"/>
<line num="91" type="stmt" count="1"/>
<line num="92" type="stmt" count="1"/>
<line num="97" type="stmt" count="2"/>
<line num="98" type="stmt" count="2"/>
<line num="99" type="stmt" count="2"/>
<line num="100" type="stmt" count="2"/>
<line num="101" type="stmt" count="2"/>
<line num="104" type="stmt" count="2"/>
<line num="110" type="method" name="getSection" visibility="public" complexity="1" crap="1" count="1"/>
<line num="111" type="stmt" count="1"/>
<line num="121" type="method" name="getPriority" visibility="public" complexity="1" crap="1" count="1"/>
<line num="122" type="stmt" count="1"/>
<metrics loc="125" ncloc="83" classes="1" methods="4" coveredmethods="4" conditionals="0" coveredconditionals="0" statements="35" coveredstatements="35" elements="39" coveredelements="39"/>
</file>
<file name="/media/psf/stable9/apps/user_saml/lib/Settings/Section.php">
<class name="Section" namespace="OCA\User_SAML\Settings">
<metrics complexity="4" methods="4" coveredmethods="4" conditionals="0" coveredconditionals="0" statements="5" coveredstatements="5" elements="9" coveredelements="9"/>
</class>
<line num="36" type="method" name="__construct" visibility="public" complexity="1" crap="1" count="3"/>
<line num="37" type="stmt" count="3"/>
<line num="38" type="stmt" count="3"/>
<line num="43" type="method" name="getID" visibility="public" complexity="1" crap="1" count="1"/>
<line num="44" type="stmt" count="1"/>
<line num="50" type="method" name="getName" visibility="public" complexity="1" crap="1" count="1"/>
<line num="51" type="stmt" count="1"/>
<line num="57" type="method" name="getPriority" visibility="public" complexity="1" crap="1" count="1"/>
<line num="58" type="stmt" count="1"/>
<metrics loc="60" ncloc="26" classes="1" methods="4" coveredmethods="4" conditionals="0" coveredconditionals="0" statements="5" coveredstatements="5" elements="9" coveredelements="9"/>
</file>
</package>
<package name="OCA\User_SAML">
<file name="/media/psf/stable9/apps/user_saml/lib/samlsettings.php">
<class name="SAMLSettings" namespace="OCA\User_SAML">
<metrics complexity="17" methods="2" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="54" coveredstatements="0" elements="56" coveredelements="0"/>
</class>
<line num="38" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<line num="39" type="stmt" count="0"/>
<line num="40" type="stmt" count="0"/>
<line num="41" type="stmt" count="0"/>
<line num="42" type="stmt" count="0"/>
<line num="44" type="method" name="getOneLoginSettingsArray" visibility="public" complexity="16" crap="272" count="0"/>
<line num="45" type="stmt" count="0"/>
<line num="48" type="stmt" count="0"/>
<line num="49" type="stmt" count="0"/>
<line num="50" type="stmt" count="0"/>
<line num="51" type="stmt" count="0"/>
<line num="52" type="stmt" count="0"/>
<line num="53" type="stmt" count="0"/>
<line num="54" type="stmt" count="0"/>
<line num="55" type="stmt" count="0"/>
<line num="56" type="stmt" count="0"/>
<line num="57" type="stmt" count="0"/>
<line num="58" type="stmt" count="0"/>
<line num="59" type="stmt" count="0"/>
<line num="60" type="stmt" count="0"/>
<line num="61" type="stmt" count="0"/>
<line num="62" type="stmt" count="0"/>
<line num="63" type="stmt" count="0"/>
<line num="64" type="stmt" count="0"/>
<line num="65" type="stmt" count="0"/>
<line num="66" type="stmt" count="0"/>
<line num="67" type="stmt" count="0"/>
<line num="68" type="stmt" count="0"/>
<line num="69" type="stmt" count="0"/>
<line num="70" type="stmt" count="0"/>
<line num="71" type="stmt" count="0"/>
<line num="72" type="stmt" count="0"/>
<line num="73" type="stmt" count="0"/>
<line num="75" type="stmt" count="0"/>
<line num="76" type="stmt" count="0"/>
<line num="77" type="stmt" count="0"/>
<line num="78" type="stmt" count="0"/>
<line num="79" type="stmt" count="0"/>
<line num="80" type="stmt" count="0"/>
<line num="81" type="stmt" count="0"/>
<line num="82" type="stmt" count="0"/>
<line num="84" type="stmt" count="0"/>
<line num="85" type="stmt" count="0"/>
<line num="86" type="stmt" count="0"/>
<line num="87" type="stmt" count="0"/>
<line num="89" type="stmt" count="0"/>
<line num="90" type="stmt" count="0"/>
<line num="91" type="stmt" count="0"/>
<line num="92" type="stmt" count="0"/>
<line num="93" type="stmt" count="0"/>
<line num="94" type="stmt" count="0"/>
<line num="95" type="stmt" count="0"/>
<line num="96" type="stmt" count="0"/>
<line num="97" type="stmt" count="0"/>
<line num="99" type="stmt" count="0"/>
<line num="100" type="stmt" count="0"/>
<metrics loc="102" ncloc="73" classes="1" methods="2" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="54" coveredstatements="0" elements="56" coveredelements="0"/>
</file>
<file name="/media/psf/stable9/apps/user_saml/lib/userbackend.php">
<class name="UserBackend" namespace="OCA\User_SAML">
<metrics complexity="37" methods="18" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="146" coveredstatements="0" elements="164" coveredelements="0"/>
</class>
<line num="51" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
<line num="52" type="stmt" count="0"/>
<line num="53" type="stmt" count="0"/>
<line num="54" type="stmt" count="0"/>
<line num="55" type="stmt" count="0"/>
<line num="56" type="stmt" count="0"/>
<line num="57" type="stmt" count="0"/>
<line num="58" type="stmt" count="0"/>
<line num="59" type="stmt" count="0"/>
<line num="67" type="method" name="userExistsInDatabase" visibility="private" complexity="1" crap="2" count="0"/>
<line num="69" type="stmt" count="0"/>
<line num="70" type="stmt" count="0"/>
<line num="71" type="stmt" count="0"/>
<line num="72" type="stmt" count="0"/>
<line num="73" type="stmt" count="0"/>
<line num="74" type="stmt" count="0"/>
<line num="75" type="stmt" count="0"/>
<line num="76" type="stmt" count="0"/>
<line num="78" type="stmt" count="0"/>
<line num="79" type="stmt" count="0"/>
<line num="86" type="method" name="createUserIfNotExists" visibility="public" complexity="3" crap="12" count="0"/>
<line num="87" type="stmt" count="0"/>
<line num="88" type="stmt" count="0"/>
<line num="89" type="stmt" count="0"/>
<line num="90" type="stmt" count="0"/>
<line num="93" type="stmt" count="0"/>
<line num="94" type="stmt" count="0"/>
<line num="95" type="stmt" count="0"/>
<line num="96" type="stmt" count="0"/>
<line num="97" type="stmt" count="0"/>
<line num="98" type="stmt" count="0"/>
<line num="99" type="stmt" count="0"/>
<line num="100" type="stmt" count="0"/>
<line num="111" type="method" name="implementsActions" visibility="public" complexity="1" crap="2" count="0"/>
<line num="112" type="stmt" count="0"/>
<line num="113" type="stmt" count="0"/>
<line num="114" type="stmt" count="0"/>
<line num="125" type="method" name="checkPassword" visibility="public" complexity="3" crap="12" count="0"/>
<line num="127" type="stmt" count="0"/>
<line num="128" type="stmt" count="0"/>
<line num="129" type="stmt" count="0"/>
<line num="130" type="stmt" count="0"/>
<line num="131" type="stmt" count="0"/>
<line num="132" type="stmt" count="0"/>
<line num="133" type="stmt" count="0"/>
<line num="134" type="stmt" count="0"/>
<line num="136" type="stmt" count="0"/>
<line num="137" type="stmt" count="0"/>
<line num="138" type="stmt" count="0"/>
<line num="139" type="stmt" count="0"/>
<line num="140" type="stmt" count="0"/>
<line num="142" type="stmt" count="0"/>
<line num="143" type="stmt" count="0"/>
<line num="151" type="method" name="deleteUser" visibility="public" complexity="2" crap="6" count="0"/>
<line num="152" type="stmt" count="0"/>
<line num="154" type="stmt" count="0"/>
<line num="155" type="stmt" count="0"/>
<line num="156" type="stmt" count="0"/>
<line num="157" type="stmt" count="0"/>
<line num="158" type="stmt" count="0"/>
<line num="159" type="stmt" count="0"/>
<line num="160" type="stmt" count="0"/>
<line num="161" type="stmt" count="0"/>
<line num="172" type="method" name="getUsers" visibility="public" complexity="3" crap="12" count="0"/>
<line num="174" type="stmt" count="0"/>
<line num="175" type="stmt" count="0"/>
<line num="176" type="stmt" count="0"/>
<line num="177" type="stmt" count="0"/>
<line num="178" type="stmt" count="0"/>
<line num="179" type="stmt" count="0"/>
<line num="180" type="stmt" count="0"/>
<line num="181" type="stmt" count="0"/>
<line num="182" type="stmt" count="0"/>
<line num="183" type="stmt" count="0"/>
<line num="184" type="stmt" count="0"/>
<line num="185" type="stmt" count="0"/>
<line num="186" type="stmt" count="0"/>
<line num="188" type="stmt" count="0"/>
<line num="189" type="stmt" count="0"/>
<line num="190" type="stmt" count="0"/>
<line num="191" type="stmt" count="0"/>
<line num="193" type="stmt" count="0"/>
<line num="194" type="stmt" count="0"/>
<line num="202" type="method" name="userExists" visibility="public" complexity="2" crap="6" count="0"/>
<line num="203" type="stmt" count="0"/>
<line num="204" type="stmt" count="0"/>
<line num="205" type="stmt" count="0"/>
<line num="206" type="stmt" count="0"/>
<line num="207" type="stmt" count="0"/>
<line num="208" type="stmt" count="0"/>
<line num="216" type="method" name="getDisplayName" visibility="public" complexity="1" crap="2" count="0"/>
<line num="217" type="stmt" count="0"/>
<line num="218" type="stmt" count="0"/>
<line num="229" type="method" name="getDisplayNames" visibility="public" complexity="3" crap="12"