Merge pull request #567 from nextcloud/feat/dev-is-24

This commit is contained in:
John Molakvoæ 2021-12-10 10:17:11 +01:00 committed by GitHub
commit 5a720dc71d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 4361 additions and 577 deletions

View file

@ -1,183 +1,4 @@
kind: pipeline
name: compatibility
clone:
depth: 1
steps:
- name: app-code-check
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: master
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server
- ./occ app:check-code $APP_NAME -c strong-comparison -c deprecation
- cd apps/$APP_NAME/
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: compatibility-23
clone:
depth: 1
steps:
- name: app-code-check
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable23
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server
- ./occ app:check-code $APP_NAME -c strong-comparison -c deprecation
- cd apps/$APP_NAME/
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: compatibility-22
clone:
depth: 1
steps:
- name: app-code-check
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable22
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server
- ./occ app:check-code $APP_NAME -c strong-comparison -c deprecation
- cd apps/$APP_NAME/
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: compatibility-21
clone:
depth: 1
steps:
- name: app-code-check
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable21
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server
- ./occ app:check-code $APP_NAME -c strong-comparison -c deprecation
- cd apps/$APP_NAME/
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: tests-master
clone:
depth: 1
steps:
- name: php7.3
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: master
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php7.4
image: nextcloudci/php7.4:php7.4-2
environment:
APP_NAME: user_saml
CORE_BRANCH: master
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php8.0
image: nextcloudci/php8.0:latest
environment:
APP_NAME: user_saml
CORE_BRANCH: master
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: integration-tests-master
clone:
@ -211,61 +32,6 @@ trigger:
type: docker
---
kind: pipeline
name: tests-23
clone:
depth: 1
steps:
- name: php7.3
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable23
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php7.4
image: nextcloudci/php7.4:php7.4-2
environment:
APP_NAME: user_saml
CORE_BRANCH: stable23
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php8.0
image: nextcloudci/php8.0:latest
environment:
APP_NAME: user_saml
CORE_BRANCH: stable23
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: integration-tests-stable23
@ -301,61 +67,6 @@ trigger:
type: docker
---
kind: pipeline
name: tests-22
clone:
depth: 1
steps:
- name: php7.3
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable22
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php7.4
image: nextcloudci/php7.4:php7.4-2
environment:
APP_NAME: user_saml
CORE_BRANCH: stable22
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php8.0
image: nextcloudci/php8.0:latest
environment:
APP_NAME: user_saml
CORE_BRANCH: stable22
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---
kind: pipeline
name: integration-tests-stable22
@ -389,60 +100,6 @@ trigger:
- pull_request
- push
type: docker
---
kind: pipeline
name: tests-21
clone:
depth: 1
steps:
- name: php7.3
image: nextcloudci/php7.3:php7.3-5
environment:
APP_NAME: user_saml
CORE_BRANCH: stable21
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php7.4
image: nextcloudci/php7.4:php7.4-2
environment:
APP_NAME: user_saml
CORE_BRANCH: stable21
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
- name: php8.0
image: nextcloudci/php8.0:latest
environment:
APP_NAME: user_saml
CORE_BRANCH: stable21
DB: sqlite
commands:
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server/apps/$APP_NAME
- cd tests/unit/
- phpunit --configuration phpunit.xml
trigger:
branch:
- master
- stable*
event:
- pull_request
- push
type: docker
---

31
.github/workflows/lint-info-xml.yml vendored Normal file
View file

@ -0,0 +1,31 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on:
pull_request:
push:
branches:
- master
- stable*
jobs:
xml-linters:
runs-on: ubuntu-latest
name: info.xml lint
steps:
- name: Checkout
uses: actions/checkout@master
- name: Download schema
run: wget https://raw.githubusercontent.com/nextcloud/server/master/resources/app-info-shipped.xsd
- name: Lint info.xml
uses: ChristophWurst/xmllint-action@v1
with:
xml-file: ./appinfo/info.xml
xml-schema-file: ./app-info-shipped.xsd

35
.github/workflows/lint-php-cs.yml vendored Normal file
View file

@ -0,0 +1,35 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on:
pull_request:
push:
branches:
- master
- stable*
jobs:
lint:
runs-on: ubuntu-latest
name: php-cs
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v2
with:
php-version: "7.4"
coverage: none
- name: Install dependencies
run: composer i
- name: Lint
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )

35
.github/workflows/lint-php.yml vendored Normal file
View file

@ -0,0 +1,35 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on:
pull_request:
push:
branches:
- master
- stable*
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ["7.3", "7.4", "8.0"]
name: php
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
- name: Lint
run: composer run lint

74
.github/workflows/phpunit.yml vendored Normal file
View file

@ -0,0 +1,74 @@
name: PHPUnit
on:
pull_request:
push:
branches:
- master
- stable*
env:
APP_NAME: user_saml
jobs:
php:
runs-on: ubuntu-latest
strategy:
# do not stop on another job's failure
fail-fast: false
matrix:
php-versions: ['7.4', '8.0']
databases: ['sqlite']
server-versions: ['stable21', 'stable22', 'stable23', 'master']
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
steps:
- name: Checkout server
uses: actions/checkout@v2
with:
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
submodules: true
- name: Checkout app
uses: actions/checkout@v2
with:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v1
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, gd, zip
- name: Set up PHPUnit
working-directory: apps/${{ env.APP_NAME }}
run: composer i
- name: Set up Nextcloud
env:
DB_PORT: 4444
run: |
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password
./occ app:enable --force ${{ env.APP_NAME }}
php -S localhost:8080 &
- name: PHPUnit & coverage
working-directory: apps/${{ env.APP_NAME }}
run: |
cd tests/unit
../../vendor/phpunit/phpunit/phpunit --coverage-clover coverage.xml -c phpunit.xml
# - name: PHPUnit integration
# working-directory: apps/${{ env.APP_NAME }}
# run: ../../vendor/phpunit/phpunit/phpunit -c phpunit.integration.xml
- name: Upload coverage
working-directory: apps/${{ env.APP_NAME }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: bash <(curl -s https://codecov.io/bash)

2
.gitignore vendored
View file

@ -7,3 +7,5 @@
3rdparty/vendor/onelogin/php-saml/endpoints/
build
vendor
.php_cs.cache

17
.php_cs.dist Normal file
View file

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
require_once './vendor/autoload.php';
use Nextcloud\CodingStandard\Config;
$config = new Config();
$config
->getFinder()
->notPath('build')
->notPath('l10n')
->notPath('src')
->notPath('vendor')
->in(__DIR__);
return $config;

View file

@ -24,7 +24,7 @@ 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.
$cli = false;
if(OC::$CLI) {
if (OC::$CLI) {
$cli = true;
}
try {
@ -70,7 +70,7 @@ $params = [];
// Setting up the one login config may fail, if so, do not catch the requests later.
$returnScript = false;
$type = '';
switch($config->getAppValue('user_saml', 'type')) {
switch ($config->getAppValue('user_saml', 'type')) {
case 'saml':
try {
$oneLoginSettings = new \OneLogin\Saml2\Settings($samlSettings->getOneLoginSettingsArray(1));
@ -96,7 +96,7 @@ if ($type === 'environment-variable') {
OC_User::handleApacheAuth();
}
if($returnScript === true) {
if ($returnScript === true) {
return;
}
@ -122,7 +122,7 @@ if ($user !== null) {
// All requests that are not authenticated and match against the "/login" route are
// redirected to the SAML login endpoint
if(!$cli &&
if (!$cli &&
!$userSession->isLoggedIn() &&
\OC::$server->getRequest()->getPathInfo() === '/login' &&
$type !== '') {
@ -145,10 +145,10 @@ if(!$cli &&
// UX (users don't have to reauthenticate) we default to disallow the access via
// SAML at the moment.
$useSamlForDesktopClients = $config->getAppValue('user_saml', 'general-use_saml_auth_for_desktop', '0');
if($useSamlForDesktopClients === '1') {
if ($useSamlForDesktopClients === '1') {
$currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT));
if(substr($currentUrl, 0, 12) === '/remote.php/' || substr($currentUrl, 0, 5) === '/ocs/') {
if(!$userSession->isLoggedIn() && $request->isUserAgent([\OCP\IRequest::USER_AGENT_CLIENT_DESKTOP])) {
if (substr($currentUrl, 0, 12) === '/remote.php/' || substr($currentUrl, 0, 5) === '/ocs/') {
if (!$userSession->isLoggedIn() && $request->isUserAgent([\OCP\IRequest::USER_AGENT_CLIENT_DESKTOP])) {
$redirectSituation = true;
if (preg_match('/^.*\/(\d+\.\d+\.\d+).*$/', $request->getHeader('USER_AGENT'), $matches) === 1) {
@ -173,7 +173,7 @@ if ($redirectSituation === true && $showLoginOptions) {
// ignore exception when PUT is called since getParams cannot parse parameters in that case
}
$redirectUrl = '';
if(isset($params['redirect_url'])) {
if (isset($params['redirect_url'])) {
$redirectUrl = $params['redirect_url'];
}
@ -185,17 +185,16 @@ if ($redirectSituation === true && $showLoginOptions) {
);
header('Location: '.$targetUrl);
exit();
}
if($redirectSituation === true) {
if ($redirectSituation === true) {
try {
$params = $request->getParams();
} catch (\LogicException $e) {
// ignore exception when PUT is called since getParams cannot parse parameters in that case
}
$originalUrl = '';
if(isset($params['redirect_url'])) {
if (isset($params['redirect_url'])) {
$originalUrl = $urlGenerator->getAbsoluteURL($params['redirect_url']);
}

View file

@ -16,7 +16,7 @@ The following providers are supported and tested at the moment:
* Any other provider that authenticates using the environment variable
While theoretically any other authentication provider implementing either one of those standards is compatible, we like to note that they are not part of any internal test matrix.]]></description>
<version>4.2.0</version>
<version>4.3.0</version>
<licence>agpl</licence>
<author>Lukas Reschke</author>
<namespace>User_SAML</namespace>
@ -33,7 +33,7 @@ While theoretically any other authentication provider implementing either one of
<screenshot>https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/1.png</screenshot>
<screenshot>https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/2.png</screenshot>
<dependencies>
<nextcloud min-version="21" max-version="23" />
<nextcloud min-version="21" max-version="24" />
</dependencies>
<commands>
<command>OCA\User_SAML\Command\GetMetadata</command>

19
composer.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "nextcloud/user_saml",
"config": {
"optimize-autoloader": true,
"classmap-authoritative": true,
"platform": {
"php": "7.4"
}
},
"scripts": {
"cs:fix": "php-cs-fixer fix",
"cs:check": "php-cs-fixer fix --dry-run --diff",
"lint": "find . -name \\*.php -not -path '*/vendor/*' -print0 | xargs -0 -n1 php -l"
},
"require-dev": {
"nextcloud/coding-standard": "^0.5.0",
"phpunit/phpunit": "^8"
}
}

3939
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@ use OCP\AppFramework\IAppContainer;
use OCP\SabrePluginEvent;
class Application extends App {
public function __construct(array $urlParams = array()) {
public function __construct(array $urlParams = []) {
parent::__construct('user_saml', $urlParams);
$container = $this->getContainer();
@ -57,7 +57,6 @@ class Application extends App {
}
public function registerDavAuth() {
$container = $this->getContainer();
$dispatcher = $container->getServer()->getEventDispatcher();
@ -74,7 +73,7 @@ class Application extends App {
$config = $container->getServer()->getConfig();
$dispatcher = $container->getServer()->getEventDispatcher();
$dispatcher->addListener('OCA\Files::loadAdditionalScripts', function() use ($session, $config, $userSession) {
$dispatcher->addListener('OCA\Files::loadAdditionalScripts', function () use ($session, $config, $userSession) {
if (!$userSession->isLoggedIn()) {
return;
}

View file

@ -38,8 +38,6 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Security\ICrypto;
use OneLogin\Saml2\Auth;
@ -120,7 +118,7 @@ class SAMLController extends Controller {
private function autoprovisionIfPossible() {
$auth = $this->userData->getAttributes();
if(!$this->userData->hasUidMappingAttribute()) {
if (!$this->userData->hasUidMappingAttribute()) {
throw new NoUserFoundException('IDP parameter for the UID not found. Possible parameters are: ' . json_encode(array_keys($auth)));
}
@ -142,17 +140,17 @@ class SAMLController extends Controller {
return;
}
$autoProvisioningAllowed = $this->userBackend->autoprovisionAllowed();
if($userExists) {
if($autoProvisioningAllowed) {
if ($userExists) {
if ($autoProvisioningAllowed) {
$this->userBackend->updateAttributes($uid, $auth);
}
return;
}
$uid = $this->userData->getOriginalUid();
$uid = $this->userData->testEncodedObjectGUID($uid);
if(!$userExists && !$autoProvisioningAllowed) {
if (!$userExists && !$autoProvisioningAllowed) {
throw new NoUserFoundException('Auto provisioning not allowed and user ' . $uid . ' does not exist');
} elseif(!$userExists && $autoProvisioningAllowed) {
} elseif (!$userExists && $autoProvisioningAllowed) {
$this->userBackend->createUserIfNotExists($uid, $auth);
$this->userBackend->updateAttributes($uid, $auth);
return;
@ -171,7 +169,7 @@ class SAMLController extends Controller {
*/
public function login($idp) {
$type = $this->config->getAppValue($this->appName, 'type');
switch($type) {
switch ($type) {
case 'saml':
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
$ssoUrl = $auth->login(null, [], false, false, true);
@ -182,7 +180,7 @@ class SAMLController extends Controller {
if ($this->session->get(ClientFlowLoginController::STATE_NAME) !== null) {
$flowData['cf1'] = $this->session->get(ClientFlowLoginController::STATE_NAME);
} else if ($this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME) !== null) {
} elseif ($this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME) !== null) {
$flowData['cf2'] = [
'token' => $this->session->get(ClientFlowLoginV2Controller::TOKEN_NAME),
'state' => $this->session->get(ClientFlowLoginV2Controller::STATE_NAME),
@ -291,18 +289,17 @@ class SAMLController extends Controller {
if (isset($data['flow'])) {
if (isset($data['flow']['cf1'])) {
$this->session->set(ClientFlowLoginController::STATE_NAME, $data['flow']['cf1']);
} else if (isset($data['flow']['cf2'])) {
} elseif (isset($data['flow']['cf2'])) {
$this->session->set(ClientFlowLoginV2Controller::TOKEN_NAME, $data['flow']['cf2']['token']);
$this->session->set(ClientFlowLoginV2Controller::STATE_NAME, $data['flow']['cf2']['state']);
}
}
$AuthNRequestID = $data['AuthNRequestID'];
$idp = $data['Idp'];
// need to keep the IdP config ID during session lifetime (SAMLSettings::getPrefix)
$this->session->set('user_saml.Idp', $idp);
if(is_null($AuthNRequestID) || $AuthNRequestID === '' || is_null($idp)) {
if (is_null($AuthNRequestID) || $AuthNRequestID === '' || is_null($idp)) {
$this->logger->debug('Invalid auth payload', ['app' => 'user_saml']);
return new Http\RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
}
@ -315,7 +312,7 @@ class SAMLController extends Controller {
$errors = $auth->getErrors();
if (!empty($errors)) {
foreach($errors as $error) {
foreach ($errors as $error) {
$this->logger->error($error, ['app' => $this->appName]);
}
$this->logger->error($auth->getLastErrorReason(), ['app' => $this->appName]);
@ -363,14 +360,14 @@ class SAMLController extends Controller {
}
$originalUrl = $data['OriginalUrl'];
if($originalUrl !== null && $originalUrl !== '') {
if ($originalUrl !== null && $originalUrl !== '') {
$response = new Http\RedirectResponse($originalUrl);
} else {
$response = new Http\RedirectResponse(\OC::$server->getURLGenerator()->getAbsoluteURL('/'));
}
// The Nextcloud desktop client expects a cookie with the key of "_shibsession"
// to be there.
if($this->request->isUserAgent(['/^.*(mirall|csyncoC)\/.*$/'])) {
if ($this->request->isUserAgent(['/^.*(mirall|csyncoC)\/.*$/'])) {
$response->addCookie('_shibsession_', 'authenticated');
}
@ -392,17 +389,17 @@ class SAMLController extends Controller {
// Some IDPs send the SLO request via POST, but OneLogin php-saml only handles GET.
// To hack around this issue we copy the request from _POST to _GET.
if(!empty($_POST['SAMLRequest'])) {
if (!empty($_POST['SAMLRequest'])) {
$_GET['SAMLRequest'] = $_POST['SAMLRequest'];
}
$isFromIDP = !$isFromGS && !empty($_GET['SAMLRequest']);
if($isFromIDP) {
if ($isFromIDP) {
// requests comes from the IDP so let it manage the logout
// (or raise Error if request is invalid)
$pass = True ;
} elseif($isFromGS) {
$pass = true ;
} elseif ($isFromGS) {
// Request is from master GlobalScale
// Request validity is check via a JSON Web Token
$jwt = $this->request->getParam('jwt', '');
@ -412,7 +409,7 @@ class SAMLController extends Controller {
$pass = $this->request->passesCSRFCheck();
}
if($pass) {
if ($pass) {
$idp = $this->session->get('user_saml.Idp');
$auth = new Auth($this->SAMLSettings->getOneLoginSettingsArray($idp));
$stay = true ; // $auth will return the redirect URL but won't perform the redirect himself
@ -428,14 +425,14 @@ class SAMLController extends Controller {
$errors = $auth->getErrors();
if (!empty($errors)) {
foreach($errors as $error) {
foreach ($errors as $error) {
$this->logger->error($error, ['app' => $this->appName]);
}
$this->logger->error($auth->getLastErrorReason(), ['app' => $this->appName]);
}
} else {
// If request is not from IDP, we send the logout request to the IDP
$parameters = array();
$parameters = [];
$nameId = $this->session->get('user_saml.samlNameId');
$nameIdFormat = $this->session->get('user_saml.samlNameIdFormat');
$nameIdNameQualifier = $this->session->get('user_saml.samlNameIdNameQualifier');
@ -448,11 +445,11 @@ class SAMLController extends Controller {
$this->userSession->logout();
}
}
if(!empty($targetUrl) && !$auth->getLastErrorReason()){
if (!empty($targetUrl) && !$auth->getLastErrorReason()) {
$this->userSession->logout();
}
}
if(empty($targetUrl)){
if (empty($targetUrl)) {
$targetUrl = $this->urlGenerator->getAbsoluteURL('/');
}
@ -491,7 +488,6 @@ class SAMLController extends Controller {
* @return Http\TemplateResponse
*/
public function selectUserBackEnd($redirectUrl) {
$attributes = ['loginUrls' => []];
if ($this->SAMLSettings->allowMultipleUserBackEnds()) {
@ -543,9 +539,8 @@ class SAMLController extends Controller {
* @return string
*/
private function getSSOUrl($redirectUrl, $idp) {
$originalUrl = '';
if(!empty($redirectUrl)) {
if (!empty($redirectUrl)) {
$originalUrl = $this->urlGenerator->getAbsoluteURL($redirectUrl);
}
@ -561,7 +556,6 @@ class SAMLController extends Controller {
);
return $ssoUrl;
}
/**
@ -612,5 +606,4 @@ class SAMLController extends Controller {
$message = $this->l->t('This page should not be visited directly.');
return new Http\TemplateResponse($this->appName, 'error', ['message' => $message], 'guest');
}
}

View file

@ -116,5 +116,4 @@ class SettingsController extends Controller {
}
return new Response();
}
}

View file

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>

View file

@ -24,11 +24,8 @@ namespace OCA\User_SAML;
use OCA\DAV\Connector\Sabre\Auth;
use OCP\IConfig;
use OCP\ISession;
use Sabre\DAV\CorePlugin;
use Sabre\DAV\FS\Directory;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;

View file

@ -21,7 +21,6 @@
namespace OCA\User_SAML\Middleware;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Utility\IControllerMethodReflector;
@ -61,8 +60,8 @@ class OnlyLoggedInMiddleware extends Middleware {
* @param string $methodName
* @throws \Exception
*/
public function beforeController($controller, $methodName){
if($this->reflector->hasAnnotation('OnlyUnauthenticatedUsers') && $this->userSession->isLoggedIn()) {
public function beforeController($controller, $methodName) {
if ($this->reflector->hasAnnotation('OnlyUnauthenticatedUsers') && $this->userSession->isLoggedIn()) {
throw new \Exception('User is already logged-in');
}
}
@ -75,7 +74,7 @@ class OnlyLoggedInMiddleware extends Middleware {
* @throws \Exception
*/
public function afterException($controller, $methodName, \Exception $exception) {
if($exception->getMessage() === 'User is already logged-in') {
if ($exception->getMessage() === 'User is already logged-in') {
return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
}

View file

@ -21,7 +21,6 @@
namespace OCA\User_SAML;
use OCP\AppFramework\Http;
use OCP\IConfig;
use OCP\IRequest;
use OCP\ISession;
@ -99,7 +98,6 @@ class SAMLSettings {
* @return array
*/
public function getOneLoginSettingsArray($idp) {
$prefix = '';
if ($idp > 1) {
$prefix = $idp . '-';
@ -142,20 +140,20 @@ class SAMLSettings {
$spx509cert = $this->config->getAppValue('user_saml', $prefix . 'sp-x509cert', '');
$spxprivateKey = $this->config->getAppValue('user_saml', $prefix . 'sp-privateKey', '');
if($spx509cert !== '') {
if ($spx509cert !== '') {
$settings['sp']['x509cert'] = $spx509cert;
}
if($spxprivateKey !== '') {
if ($spxprivateKey !== '') {
$settings['sp']['privateKey'] = $spxprivateKey;
}
$idpx509cert = $this->config->getAppValue('user_saml', $prefix . 'idp-x509cert', '');
if($idpx509cert !== '') {
if ($idpx509cert !== '') {
$settings['idp']['x509cert'] = $idpx509cert;
}
$slo = $this->config->getAppValue('user_saml', $prefix . 'idp-singleLogoutService.url', '');
if($slo !== '') {
if ($slo !== '') {
$settings['idp']['singleLogoutService'] = [
'url' => $this->config->getAppValue('user_saml', $prefix . 'idp-singleLogoutService.url', ''),
];
@ -164,7 +162,7 @@ class SAMLSettings {
];
$sloResponseUrl = $this->config->getAppValue('user_saml', $prefix . 'idp-singleLogoutService.responseUrl', '');
if($sloResponseUrl !== '') {
if ($sloResponseUrl !== '') {
$settings['idp']['singleLogoutService']['responseUrl'] = $sloResponseUrl;
}
}
@ -179,7 +177,6 @@ class SAMLSettings {
* @return string
*/
public function getPrefix($setting = '') {
$prefix = '';
if (!empty($setting) && in_array($setting, $this->globalSettings)) {
return $prefix;
@ -192,5 +189,4 @@ class SAMLSettings {
return $prefix;
}
}

View file

@ -64,7 +64,7 @@ class Admin implements ISettings {
$providers[] = [
'id' => $id,
'name' => $name === '' ? $this->l10n->t('Provider ') . $id : $name
];
];
}
$serviceProviderFields = [
'x509cert' => $this->l10n->t('X.509 certificate of the Service Provider'),
@ -86,7 +86,7 @@ class Admin implements ISettings {
'wantXMLValidation' => $this->l10n->t('Indicates if the SP will validate all received XML.'),
];
$securityGeneral = [
'lowercaseUrlencoding' => $this->l10n->t('ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification.'),
'lowercaseUrlencoding' => $this->l10n->t('ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification.'),
'signatureAlgorithm' => [
'type' => 'line',
'text' => $this->l10n->t('Algorithm that the toolkit will use on signing process.')
@ -175,7 +175,7 @@ class Admin implements ISettings {
];
$type = $this->config->getAppValue('user_saml', 'type');
if($type === 'saml') {
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',
@ -226,5 +226,4 @@ class Admin implements ISettings {
public function getPriority() {
return 0;
}
}

View file

@ -35,7 +35,6 @@ use OCP\IConfig;
use OCP\IURLGenerator;
use OCP\ISession;
use Symfony\Component\EventDispatcher\GenericEvent;
use function base64_decode;
class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
/** @var IConfig */
@ -108,8 +107,8 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @param string $uid
* @param array $attributes
*/
public function createUserIfNotExists($uid, array $attributes = array()) {
if(!$this->userExistsInDatabase($uid)) {
public function createUserIfNotExists($uid, array $attributes = []) {
if (!$this->userExistsInDatabase($uid)) {
$values = [
'uid' => $uid,
];
@ -124,12 +123,12 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
if ($home !== '') {
//if attribute's value is an absolute path take this, otherwise append it to data dir
//check for / at the beginning or pattern c:\ resp. c:/
if( '/' !== $home[0]
if ('/' !== $home[0]
&& !(3 < strlen($home) && ctype_alpha($home[0])
&& $home[1] === ':' && ('\\' === $home[2] || '/' === $home[2]))
) {
$home = $this->config->getSystemValue('datadirectory',
\OC::$SERVERROOT.'/data' ) . '/' . $home;
\OC::$SERVERROOT.'/data') . '/' . $home;
}
$values['home'] = $home;
@ -138,13 +137,12 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->insert('user_saml_users');
foreach($values as $column => $value) {
foreach ($values as $column => $value) {
$qb->setValue($column, $qb->createNamedParameter($value));
}
$qb->execute();
$this->initializeHomeDir($uid);
}
}
@ -204,8 +202,8 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
$data = $result->fetchAll();
$result->closeCursor();
foreach($data as $passwords) {
if(password_verify($password, $passwords['token'])) {
foreach ($data as $passwords) {
if (password_verify($password, $passwords['token'])) {
return $uid;
}
}
@ -220,7 +218,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @since 4.5.0
*/
public function deleteUser($uid) {
if($this->userExistsInDatabase($uid)) {
if ($this->userExistsInDatabase($uid)) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('user_saml_users')
@ -238,7 +236,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @return string
*/
public function getHome($uid) {
if($this->userExistsInDatabase($uid)) {
if ($this->userExistsInDatabase($uid)) {
$qb = $this->db->getQueryBuilder();
$qb->select('home')
->from('user_saml_users')
@ -278,7 +276,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @since 4.5.0
*/
public function userExists($uid) {
if($backend = $this->getActualUserBackend($uid)) {
if ($backend = $this->getActualUserBackend($uid)) {
return $backend->userExists($uid);
} else {
return $this->userExistsInDatabase($uid);
@ -286,7 +284,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
}
public function setDisplayName($uid, $displayName) {
if($backend = $this->getActualUserBackend($uid)) {
if ($backend = $this->getActualUserBackend($uid)) {
return $backend->setDisplayName($uid, $displayName);
}
@ -310,10 +308,10 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @since 4.5.0
*/
public function getDisplayName($uid) {
if($backend = $this->getActualUserBackend($uid)) {
if ($backend = $this->getActualUserBackend($uid)) {
return $backend->getDisplayName($uid);
} else {
if($this->userExistsInDatabase($uid)) {
if ($this->userExistsInDatabase($uid)) {
$qb = $this->db->getQueryBuilder();
$qb->select('displayname')
->from('user_saml_users')
@ -375,7 +373,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @since 4.5.0
*/
public function hasUserListings() {
if($this->autoprovisionAllowed()) {
if ($this->autoprovisionAllowed()) {
return true;
}
@ -398,7 +396,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
public function getLogoutUrl() {
$prefix = $this->settings->getPrefix();
$slo = $this->config->getAppValue('user_saml', $prefix . 'idp-singleLogoutService.url', '');
if($slo === '') {
if ($slo === '') {
return '';
}
@ -486,14 +484,14 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
public function getCurrentUserId() {
$user = \OC::$server->getUserSession()->getUser();
if($user instanceof IUser && $this->session->get('user_saml.samlUserData')) {
if ($user instanceof IUser && $this->session->get('user_saml.samlUserData')) {
$uid = $user->getUID();
} else {
$this->userData->setAttributes($this->session->get('user_saml.samlUserData') ?? []);
$uid = $this->userData->getEffectiveUid();
}
if($uid !== '' && $this->userExists($uid)) {
if ($uid !== '' && $this->userExists($uid)) {
$this->session->set('last-password-confirm', strtotime('+4 year', time()));
return $uid;
}
@ -526,8 +524,8 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
* @return null|UserInterface
*/
public function getActualUserBackend($uid) {
foreach(self::$backends as $backend) {
if($backend->userExists($uid)) {
foreach (self::$backends as $backend) {
if ($backend->userExists($uid)) {
return $backend;
}
}
@ -545,8 +543,7 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
self::$backends = $backends;
}
private function getAttributeKeys($name)
{
private function getAttributeKeys($name) {
$prefix = $this->settings->getPrefix($name);
$keys = explode(' ', $this->config->getAppValue('user_saml', $prefix . $name, ''));
@ -560,17 +557,17 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
$keys = $this->getAttributeKeys($name);
$value = '';
foreach($keys as $key) {
foreach ($keys as $key) {
if (isset($attributes[$key])) {
if (is_array($attributes[$key])) {
foreach ($attributes[$key] as $attribute_part_value) {
if($value !== '') {
if ($value !== '') {
$value .= ' ';
}
$value .= $attribute_part_value;
}
} else {
if($value !== '') {
if ($value !== '') {
$value .= ' ';
}
$value .= $attributes[$key];
@ -584,8 +581,8 @@ class UserBackend implements IApacheBackend, UserInterface, IUserBackend {
private function getAttributeArrayValue($name, array $attributes) {
$keys = $this->getAttributeKeys($name);
$value = array();
foreach($keys as $key) {
$value = [];
foreach ($keys as $key) {
if (isset($attributes[$key])) {
if (is_array($attributes[$key])) {
$value = array_merge($value, array_values($attributes[$key]));

View file

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
@ -67,7 +68,7 @@ class UserData {
}
public function getEffectiveUid(): string {
if($this->uid !== null) {
if ($this->uid !== null) {
return $this->uid;
}
$this->assertIsInitialized();
@ -85,7 +86,7 @@ class UserData {
protected function extractSamlUserId(): string {
$prefix = $this->samlSettings->getPrefix();
$uidMapping = $this->config->getAppValue('user_saml', $prefix . 'general-uid_mapping');
if(isset($this->attributes[$uidMapping])) {
if (isset($this->attributes[$uidMapping])) {
if (is_array($this->attributes[$uidMapping])) {
return trim($this->attributes[$uidMapping][0]);
} else {
@ -107,13 +108,13 @@ class UserData {
}
$candidate = base64_decode($uid, true);
if($candidate === false) {
if ($candidate === false) {
return $uid;
}
$candidate = $this->convertObjectGUID2Str($candidate);
// the regex only matches the structure of the UUID, not its semantic
// (i.e. version or variant) simply to be future compatible
if(preg_match('/^[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}$/i', $candidate) === 1) {
if (preg_match('/^[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}$/i', $candidate) === 1) {
$uid = $candidate;
}
return $uid;
@ -125,15 +126,15 @@ class UserData {
protected function convertObjectGUID2Str($oguid): string {
$hex_guid = bin2hex($oguid);
$hex_guid_to_guid_str = '';
for($k = 1; $k <= 4; ++$k) {
for ($k = 1; $k <= 4; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-';
for($k = 1; $k <= 2; ++$k) {
for ($k = 1; $k <= 2; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-';
for($k = 1; $k <= 2; ++$k) {
for ($k = 1; $k <= 2; ++$k) {
$hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
}
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
@ -143,7 +144,7 @@ class UserData {
}
protected function assertIsInitialized() {
if($this->attributes === null) {
if ($this->attributes === null) {
throw new \LogicException('UserData have to be initialized with setAttributes first');
}
}

View file

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
@ -40,18 +41,18 @@ class UserResolver {
* @throws NoUserFoundException
*/
public function findExistingUserId(string $rawUidCandidate, bool $force = false): string {
if($force) {
if ($force) {
$this->ensureUser($rawUidCandidate);
}
if($this->userManager->userExists($rawUidCandidate)) {
if ($this->userManager->userExists($rawUidCandidate)) {
return $rawUidCandidate;
}
try {
$sanitized = $this->sanitizeUserIdCandidate($rawUidCandidate);
} catch(\InvalidArgumentException $e) {
} catch (\InvalidArgumentException $e) {
$sanitized = '';
}
if($this->userManager->userExists($sanitized)) {
if ($this->userManager->userExists($sanitized)) {
return $sanitized;
}
throw new NoUserFoundException('User' . $rawUidCandidate . ' not valid or not found');
@ -63,7 +64,7 @@ class UserResolver {
public function findExistingUser(string $rawUidCandidate): IUser {
$uid = $this->findExistingUserId($rawUidCandidate);
$user = $this->userManager->get($uid);
if($user === null) {
if ($user === null) {
throw new NoUserFoundException('User' . $rawUidCandidate . ' not valid or not found');
}
return $user;
@ -73,7 +74,7 @@ class UserResolver {
try {
$this->findExistingUserId($uid, $force);
return true;
} catch(NoUserFoundException $e) {
} catch (NoUserFoundException $e) {
return false;
}
}
@ -91,7 +92,7 @@ class UserResolver {
// Transliteration to ASCII
$transliterated = @iconv('UTF-8', 'ASCII//TRANSLIT', $sanitized);
if($transliterated !== false) {
if ($transliterated !== false) {
// depending on system config iconv can work or not
$sanitized = $transliterated;
}
@ -102,7 +103,7 @@ class UserResolver {
// Every remaining disallowed characters will be removed
$sanitized = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $sanitized);
if($sanitized === '') {
if ($sanitized === '') {
throw new \InvalidArgumentException('provided name template for username does not contain any allowed characters');
}

View file

@ -52,15 +52,15 @@ style('user_saml', 'admin');
<div id="user-saml-global" class="hidden">
<h3><?php p($l->t('Global settings')) ?></h3>
<?php foreach($_['general'] as $key => $attribute): ?>
<?php if($attribute['type'] === 'checkbox' && $attribute['global']): ?>
<?php foreach ($_['general'] as $key => $attribute): ?>
<?php if ($attribute['type'] === 'checkbox' && $attribute['global']): ?>
<p>
<input type="checkbox" data-key="<?php p($key)?>" id="user-saml-general-<?php p($key)?>" name="<?php p($key)?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '0')) ?>">
<label for="user-saml-general-<?php p($key)?>"><?php p($attribute['text']) ?></label><br/>
</p>
<?php elseif($attribute['type'] === 'line' && isset($attribute['global'])): ?>
<?php elseif ($attribute['type'] === 'line' && isset($attribute['global'])): ?>
<p>
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '')) ?>" type="text" <?php if(isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '')) ?>" type="text" <?php if (isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
</p>
<?php endif; ?>
<?php endforeach; ?>
@ -82,15 +82,15 @@ style('user_saml', 'admin');
<h3>
<?php p($l->t('General')) ?>
</h3>
<?php foreach($_['general'] as $key => $attribute): ?>
<?php if($attribute['type'] === 'checkbox' && !$attribute['global']): ?>
<?php foreach ($_['general'] as $key => $attribute): ?>
<?php if ($attribute['type'] === 'checkbox' && !$attribute['global']): ?>
<p>
<input type="checkbox" data-key="<?php p($key)?>" id="user-saml-general-<?php p($key)?>" name="<?php p($key)?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '0')) ?>">
<label for="user-saml-general-<?php p($key)?>"><?php p($attribute['text']) ?></label><br/>
</p>
<?php elseif($attribute['type'] === 'line' && !isset($attribute['global'])): ?>
<?php elseif ($attribute['type'] === 'line' && !isset($attribute['global'])): ?>
<p>
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '')) ?>" type="text" <?php if(isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'general-'.$key, '')) ?>" type="text" <?php if (isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
</p>
<?php endif; ?>
<?php endforeach; ?>
@ -109,12 +109,14 @@ style('user_saml', 'admin');
<label for="user-saml-nameidformat"><?php p($l->t('Name ID format')) ?></label><br/>
<select id="user-saml-nameidformat"
name="name-id-format">
<?php foreach($_['name-id-formats'] as $key => $value): ?>
<?php foreach ($_['name-id-formats'] as $key => $value): ?>
<option value="<?php p($key) ?>"
<?php if ($value['selected'] ?? false) { p("selected"); } ?> ><?php p($value['label']) ?></option>
<?php if ($value['selected'] ?? false) {
p("selected");
} ?> ><?php p($value['label']) ?></option>
<?php endforeach; ?>
</select>
<?php foreach($_['sp'] as $key => $text): ?>
<?php foreach ($_['sp'] as $key => $text): ?>
<p>
<textarea name="<?php p($key) ?>" placeholder="<?php p($text) ?>"><?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'sp-'.$key, '')) ?></textarea>
</p>
@ -145,11 +147,11 @@ style('user_saml', 'admin');
</p>
<div class="hidden">
<?php foreach($_['attribute-mapping'] as $key => $attribute): ?>
<?php foreach ($_['attribute-mapping'] as $key => $attribute): ?>
<?php
if($attribute['type'] === 'line'): ?>
if ($attribute['type'] === 'line'): ?>
<p>
<input name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'saml-attribute-mapping-'.$key, '')) ?>" type="text" <?php if(isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
<input name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'saml-attribute-mapping-'.$key, '')) ?>" type="text" <?php if (isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="<?php p($attribute['text']) ?>"/>
</p>
<?php endif; ?>
<?php endforeach; ?>
@ -164,26 +166,26 @@ style('user_saml', 'admin');
</p>
<div class="indent hidden">
<h4><?php p($l->t('Signatures and encryption offered')) ?></h4>
<?php foreach($_['security-offer'] as $key => $text): ?>
<?php foreach ($_['security-offer'] as $key => $text): ?>
<p>
<input type="checkbox" id="user-saml-<?php p($key)?>" name="<?php p($key)?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'security-'.$key, '0')) ?>" class="checkbox">
<label for="user-saml-<?php p($key)?>"><?php p($text) ?></label><br/>
</p>
<?php endforeach; ?>
<h4><?php p($l->t('Signatures and encryption required')) ?></h4>
<?php foreach($_['security-required'] as $key => $text): ?>
<?php foreach ($_['security-required'] as $key => $text): ?>
<p>
<input type="checkbox" id="user-saml-<?php p($key)?>" name="<?php p($key)?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'security-'.$key, '0')) ?>" class="checkbox">
<label for="user-saml-<?php p($key)?>"><?php p($text) ?></label>
</p>
<?php endforeach; ?>
<h4><?php p($l->t('General')) ?></h4>
<?php foreach($_['security-general'] as $key => $attribute): ?>
<?php foreach ($_['security-general'] as $key => $attribute): ?>
<?php if (is_array($attribute) && $attribute['type'] === 'line') { ?>
<?php $text = $attribute['text'] ?>
<p>
<label><?php p($attribute['text']) ?></label><br />
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'security-'.$key, '')) ?>" type="text" <?php if(isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<input data-key="<?php p($key)?>" name="<?php p($key) ?>" value="<?php p(\OC::$server->getConfig()->getAppValue('user_saml', 'security-'.$key, '')) ?>" type="text" <?php if (isset($attribute['required']) && $attribute['required'] === true): ?>class="required"<?php endif;?> placeholder="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
</p>
<?php } else { ?>
<?php $text = $attribute ?>

View file

@ -10,21 +10,21 @@ script('user_saml', 'selectUserBackEnd');
<h1><?php p($l->t('Login options:')); ?></h1>
<?php if($_['useCombobox']) { ?>
<?php if ($_['useCombobox']) { ?>
<select class="login-chose-saml-idp" id="av_mode" name="avMode">
<option value=""><?php p($l->t('Choose a authentication provider')); ?></option>
<?php foreach ($_['loginUrls']['ssoLogin'] as $idp) { ?>
<option value="<?php p($idp['url']); ?>"><?php p($idp['display-name']); ?></option>
<?php } ?>
<?php if(isset($_['loginUrls']['directLogin'])) : ?>
<?php if (isset($_['loginUrls']['directLogin'])) : ?>
<option value="<?php p($_['loginUrls']['directLogin']['url']); ?>"><?php p($_['loginUrls']['directLogin']['display-name']); ?></option>
<?php endif; ?>
</select>
<?php } else { ?>
<?php if(isset($_['loginUrls']['directLogin'])) : ?>
<?php if (isset($_['loginUrls']['directLogin'])) : ?>
<div class="login-option">
<a href="<?php p($_['loginUrls']['directLogin']['url']); ?>"><?php p($_['loginUrls']['directLogin']['display-name']); ?></a>
</div>

View file

@ -41,12 +41,10 @@ class FeatureContext implements Context {
'cookies' => $jar,
'verify' => false,
'allow_redirects' => [
'referer' => true,
'referer' => true,
'track_redirects' => true,
],
]);
}
/** @AfterScenario */
@ -55,7 +53,7 @@ class FeatureContext implements Context {
'student1',
];
foreach($users as $user) {
foreach ($users as $user) {
shell_exec(
sprintf(
'sudo -u apache %s %s user:delete %s',
@ -66,7 +64,7 @@ class FeatureContext implements Context {
);
}
foreach($this->changedSettings as $setting) {
foreach ($this->changedSettings as $setting) {
shell_exec(
sprintf(
'sudo -u apache %s %s config:app:delete user_saml %s',
@ -135,10 +133,10 @@ class FeatureContext implements Context {
];
// Remove everything after a comma in the URL since cookies are passed there
list($url['path'])=explode(';', $url['path']);
[$url['path']] = explode(';', $url['path']);
foreach($paramsToCheck as $param) {
if($targetUrl[$param] !== $url[$param]) {
foreach ($paramsToCheck as $param) {
if ($targetUrl[$param] !== $url[$param]) {
throw new InvalidArgumentException(
sprintf(
'Expected %s for parameter %s, got %s',
@ -181,10 +179,9 @@ class FeatureContext implements Context {
$inputElements = $xpath->query('//input');
if (is_object($inputElements)) {
/** @var DOMElement $node */
foreach($inputElements as $node) {
$postData[$node->getAttribute('name')] = $node->getAttribute('value');
foreach ($inputElements as $node) {
$postData[$node->getAttribute('name')] = $node->getAttribute('value');
}
}
$this->response = $this->client->request(
@ -203,7 +200,7 @@ class FeatureContext implements Context {
* @param string $value
* @throws UnexpectedValueException
*/
public function thUserValueShouldBe($key, $value) {
public function thUserValueShouldBe($key, $value) {
$this->response = $this->client->request(
'GET',
'http://localhost/ocs/v1.php/cloud/user',
@ -223,7 +220,7 @@ class FeatureContext implements Context {
}
$actualValue = $responseArray['data'][$key];
if($actualValue !== $value) {
if ($actualValue !== $value) {
throw new UnexpectedValueException(
sprintf(
'Expected %s as value but got %s',
@ -267,7 +264,7 @@ class FeatureContext implements Context {
$response = trim($response);
$expectedStringStart = "$uid`s last login: ";
if(substr($response, 0, strlen($expectedStringStart)) !== $expectedStringStart) {
if (substr($response, 0, strlen($expectedStringStart)) !== $expectedStringStart) {
throw new UnexpectedValueException("Expected last login message, found instead '$response'");
}
}
@ -275,7 +272,7 @@ class FeatureContext implements Context {
/**
* @Given The environment variable :key is set to :value
*/
public function theEnvironmentVariableIsSetTo($key, $value) {
public function theEnvironmentVariableIsSetTo($key, $value) {
file_put_contents(__DIR__ . '/../../../../../../.htaccess', "\nSetEnv $key $value\n", FILE_APPEND);
}
}

View file

@ -25,10 +25,9 @@
namespace OCA\User_SAML\Tests\AppInfo;
use OCA\User_SAML\AppInfo\Application;
use OCA\User_SAML\Controller\SAMLController;
use OCA\User_SAML\Middleware\OnlyLoggedInMiddleware;
class ApplicationTest extends \Test\TestCase {
class ApplicationTest extends \Test\TestCase {
/** @var Application */
protected $app;
/** @var \OCP\AppFramework\IAppContainer */
@ -49,7 +48,6 @@ class ApplicationTest extends \Test\TestCase {
return [
['OnlyLoggedInMiddleware', OnlyLoggedInMiddleware::class],
];
}
/**

View file

@ -23,9 +23,9 @@ namespace OCA\User_SAML\Tests\AppInfo;
use Test\TestCase;
class Test extends TestCase {
class Test extends TestCase {
public function testFile() {
$dir =__DIR__;
$dir = __DIR__;
$routes = require_once __DIR__ . '/../../../appinfo/routes.php';
$expected = [

View file

@ -30,73 +30,72 @@ use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
class GetMetadataTest extends \Test\TestCase {
/** @var GetMetadata|\PHPUnit_Framework_MockObject_MockObject*/
protected $GetMetadata;
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
private $request;
/** @var ISession|\PHPUnit_Framework_MockObject_MockObject */
private $session;
/** @var SAMLSettings|\PHPUnit_Framework_MockObject_MockObject*/
private $samlSettings;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
/** @var GetMetadata|\PHPUnit_Framework_MockObject_MockObject*/
protected $GetMetadata;
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
private $request;
/** @var ISession|\PHPUnit_Framework_MockObject_MockObject */
private $session;
/** @var SAMLSettings|\PHPUnit_Framework_MockObject_MockObject*/
private $samlSettings;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
protected function setUp(): void {
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->config = $this->createMock(IConfig::class);
$this->request = $this->createMock(IRequest::class);
$this->session = $this->createMock(ISession::class);
protected function setUp(): void {
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->config = $this->createMock(IConfig::class);
$this->request = $this->createMock(IRequest::class);
$this->session = $this->createMock(ISession::class);
$this->samlSettings = new SAMLSettings($this->urlGenerator,
$this->config,
$this->request,
$this->session);
$this->GetMetadata = new GetMetadata($this->samlSettings);
$this->samlSettings = new SAMLSettings($this->urlGenerator,
$this->config,
$this->request,
$this->session);
$this->GetMetadata = new GetMetadata($this->samlSettings);
parent::setUp();
}
parent::setUp();
}
public function testGetMetadata(){
$inputInterface = $this->createMock(InputInterface::class);
$outputInterface = $this->createMock(OutputInterface::class);
$this->urlGenerator
->expects($this->at(0))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.base')
->willReturn('https://nextcloud.com/base/');
$this->urlGenerator
->expects($this->at(1))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.getMetadata')
->willReturn('https://nextcloud.com/metadata/');
$this->urlGenerator
->expects($this->at(2))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.assertionConsumerService')
->willReturn('https://nextcloud.com/acs/');
$this->config->expects($this->any())->method('getAppValue')
->willReturnCallback(function($app, $key, $default) {
if ($key == 'idp-entityId') {
return "dummy";
}
if ($key == 'idp-singleSignOnService.url') {
return "https://example.com/sso";
}
if ($key == 'idp-x509cert') {
return "DUMMY CERTIFICATE";
}
return $default;
});
public function testGetMetadata() {
$inputInterface = $this->createMock(InputInterface::class);
$outputInterface = $this->createMock(OutputInterface::class);
$this->urlGenerator
->expects($this->at(0))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.base')
->willReturn('https://nextcloud.com/base/');
$this->urlGenerator
->expects($this->at(1))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.getMetadata')
->willReturn('https://nextcloud.com/metadata/');
$this->urlGenerator
->expects($this->at(2))
->method('linkToRouteAbsolute')
->with('user_saml.SAML.assertionConsumerService')
->willReturn('https://nextcloud.com/acs/');
$this->config->expects($this->any())->method('getAppValue')
->willReturnCallback(function ($app, $key, $default) {
if ($key == 'idp-entityId') {
return "dummy";
}
if ($key == 'idp-singleSignOnService.url') {
return "https://example.com/sso";
}
if ($key == 'idp-x509cert') {
return "DUMMY CERTIFICATE";
}
return $default;
});
$outputInterface->expects($this->once())->method('writeln')
->with($this->stringContains('md:EntityDescriptor'));
$outputInterface->expects($this->once())->method('writeln')
->with($this->stringContains('md:EntityDescriptor'));
$this->invokePrivate($this->GetMetadata, 'execute', [$inputInterface, $outputInterface]);
}
$this->invokePrivate($this->GetMetadata, 'execute', [$inputInterface, $outputInterface]);
}
}

View file

@ -42,7 +42,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use OCP\Security\ICrypto;
use Test\TestCase;
class SAMLControllerTest extends TestCase {
class SAMLControllerTest extends TestCase {
/** @var UserResolver|\PHPUnit\Framework\MockObject\MockObject */
protected $userResolver;
/** @var UserData|\PHPUnit\Framework\MockObject\MockObject */
@ -87,15 +87,15 @@ class SAMLControllerTest extends TestCase {
$this->crypto = $this->createMock(ICrypto::class);
$this->l->expects($this->any())->method('t')->willReturnCallback(
function($param) {
function ($param) {
return $param;
}
);
$this->config->expects($this->any())->method('getSystemValue')
->willReturnCallback(function($key, $default) {
return $default;
});
->willReturnCallback(function ($key, $default) {
return $default;
});
$this->samlController = new SAMLController(
'user_saml',
@ -112,7 +112,6 @@ class SAMLControllerTest extends TestCase {
$this->userData,
$this->crypto
);
}
public function testLoginWithInvalidAppValue() {
@ -217,11 +216,11 @@ class SAMLControllerTest extends TestCase {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(function (string $app, string $key) {
if($app === 'user_saml') {
if($key === 'type') {
if ($app === 'user_saml') {
if ($key === 'type') {
return 'environment-variable';
}
if($key === 'general-uid_mapping') {
if ($key === 'general-uid_mapping') {
return 'uid';
}
}
@ -261,7 +260,7 @@ class SAMLControllerTest extends TestCase {
->method('getEffectiveUid')
->willReturn($userState > 0 ? 'MyUid' : '');
if(strpos($redirect, 'notProvisioned') !== false) {
if (strpos($redirect, 'notProvisioned') !== false) {
$this->urlGenerator
->expects($this->once())
->method('linkToRouteAbsolute')
@ -280,14 +279,14 @@ class SAMLControllerTest extends TestCase {
->with('MyUid')
->willReturn($userState === 1);
if(isset($samlUserData['uid']) && !($userState === 0 && $autoProvision === 0)) {
if (isset($samlUserData['uid']) && !($userState === 0 && $autoProvision === 0)) {
/** @var IUser|MockObject $user */
$user = $this->createMock(IUser::class);
$im = $this->userResolver
->expects($this->once())
->method('findExistingUser')
->with('MyUid');
if($autoProvision < 2) {
if ($autoProvision < 2) {
$im->willReturn($user);
} else {
$im->willThrowException(new NoUserFoundException());
@ -297,13 +296,13 @@ class SAMLControllerTest extends TestCase {
->expects($this->exactly((int)($autoProvision < 2)))
->method('updateLastLoginTimestamp');
if($userState === 0) {
if ($userState === 0) {
$this->userResolver
->expects($this->any())
->method('findExistingUserId')
->with('MyUid', true)
->willThrowException(new NoUserFoundException());
} else if($userState === 2) {
} elseif ($userState === 2) {
$this->userResolver
->expects($this->any())
->method('findExistingUserId')

View file

@ -24,13 +24,12 @@ namespace OCA\User_SAML\Tests\Middleware;
use Exception;
use OCA\User_SAML\Middleware\OnlyLoggedInMiddleware;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Utility\IControllerMethodReflector;
use OCP\IURLGenerator;
use OCP\IUserSession;
class OnlyLoggedInMiddlewareTest extends \Test\TestCase {
class OnlyLoggedInMiddlewareTest extends \Test\TestCase {
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
protected $urlGenerator;
/** @var IControllerMethodReflector|\PHPUnit_Framework_MockObject_MockObject */

View file

@ -27,7 +27,7 @@ use OCP\IConfig;
use OCP\IL10N;
use OneLogin\Saml2\Constants;
class AdminTest extends \Test\TestCase {
class AdminTest extends \Test\TestCase {
/** @var \OCA\User_SAML\Settings\Admin */
private $admin;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
@ -55,7 +55,7 @@ class AdminTest extends \Test\TestCase {
$this->l10n
->expects($this->any())
->method('t')
->will($this->returnCallback(function($text, $parameters = array()) {
->will($this->returnCallback(function ($text, $parameters = []) {
return vsprintf($text, $parameters);
}));

View file

@ -24,7 +24,7 @@ namespace OCA\User_SAML\Tests\Settings;
use OCP\IL10N;
use OCP\IURLGenerator;
class SectionTest extends \Test\TestCase {
class SectionTest extends \Test\TestCase {
/** @var \OCA\User_SAML\Settings\Section */
private $section;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */

View file

@ -35,7 +35,7 @@ use OCP\IUser;
use OCP\IUserManager;
use Test\TestCase;
class UserBackendTest extends TestCase {
class UserBackendTest extends TestCase {
/** @var UserData|\PHPUnit\Framework\MockObject\MockObject */
private $userData;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
@ -72,7 +72,7 @@ class UserBackendTest extends TestCase {
}
public function getMockedBuilder(array $mockedFunctions = []) {
if($mockedFunctions !== []) {
if ($mockedFunctions !== []) {
$this->userBackend = $this->getMockBuilder(UserBackend::class)
->setConstructorArgs([
$this->config,
@ -307,5 +307,4 @@ class UserBackendTest extends TestCase {
->with('ExistingUser', 'New Displayname');
$this->userBackend->updateAttributes('ExistingUser', ['email' => 'new@example.com', 'displayname' => 'New Displayname', 'quota' => '']);
}
}

View file

@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>

View file

@ -25,7 +25,7 @@ if (!defined('PHPUNIT_RUN')) {
require_once __DIR__.'/../../../../lib/base.php';
\OC::$loader->addValidRoot(\OC::$SERVERROOT . '/tests');
\OC_App::loadApp('user_saml');
if(!class_exists('\PHPUnit\Framework\TestCase')) {
if (!class_exists('\PHPUnit\Framework\TestCase')) {
require_once('PHPUnit/Autoload.php');
}
OC_Hook::clear();