Skip to content

Commit f4cabfd

Browse files
committed
Inital controller
1 parent 12ce739 commit f4cabfd

File tree

7 files changed

+177
-63
lines changed

7 files changed

+177
-63
lines changed

docs/discopower.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ This causes SimpleSAMLphp to use DiscoPower in preference to the built-in discov
5151
Arranging identity providers onto tabs
5252
--------------------------------------
5353

54-
DiscoPower determines its list of identity providers by parsing the [IdP remote metadata](https://simplesamlphp.org/docs/stable/simplesamlphp-reference-idp-remote) in both the `saml20-idp-remote` and `shib13-idp-remote` sets.
54+
DiscoPower determines its list of identity providers by parsing the [IdP remote metadata](https://simplesamlphp.org/docs/stable/simplesamlphp-reference-idp-remote).
5555

5656
In order to specify which tab(s) an identity provider should be displayed on, you can set the `tabs` attribute in the entity's metadata. If you're using locally hosted metadata, you can do this by simply editing your metadata as follows:
5757

@@ -121,4 +121,4 @@ where the `$entities` parameter is a reference to an array containing the metada
121121
Interacting with metarefresh
122122
----------------------------
123123

124-
If you're making use of the [metarefresh](https://github.com/simplesamlphp/simplesamlphp-module-metarefresh) module for automated metadata management, then you need to add any metadata paramters into the appropriate `template` in `config/config-metarefresh.php` so that they get applied each time metadata is refreshed.
124+
If you're making use of the [metarefresh](https://github.com/simplesamlphp/simplesamlphp-module-metarefresh) module for automated metadata management, then you need to add any metadata paramters into the appropriate `template` in `config/config-metarefresh.php` so that they get applied each time metadata is refreshed.

lib/Controller/DiscoPower.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Module\discopower\Controller;
6+
7+
use Exception;
8+
use SimpleSAML\Configuration;
9+
use SimpleSAML\Error;
10+
use SimpleSAML\HTTP\RunnableResponse;
11+
use SimpleSAML\Module\discopower\PowerIdPDisco;
12+
use SimpleSAML\Session;
13+
use SimpleSAML\XHTML\Template;
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpFoundation\JsonResponse;
17+
18+
class DiscoPower
19+
{
20+
/**
21+
* @param \Symfony\Component\HttpFoundation\Request $request The current request.
22+
* @return \SimpleSAML\HTTP\RunnableResponse
23+
*/
24+
public function main(Request $request): RunnableResponse
25+
{
26+
try {
27+
$discoHandler = new PowerIdPDisco(
28+
['saml20-idp-remote'],
29+
'poweridpdisco'
30+
);
31+
} catch (Exception $exception) {
32+
// An error here should be caused by invalid query parameters
33+
throw new Error\Error('DISCOPARAMS', $exception);
34+
}
35+
36+
try {
37+
return new RunnableResponse([$discoHandler, 'handleRequest'], []);
38+
} catch (Exception $exception) {
39+
// An error here should be caused by metadata
40+
throw new Error\Error('METADATA', $exception);
41+
}
42+
}
43+
44+
/**
45+
* An AJAX handler to retrieve a list of disco tabs from the session.
46+
* This allows us to dynamically update the tab list without inline javascript.
47+
*
48+
* @param \Symfony\Component\HttpFoundation\Request $request The current request.
49+
*/
50+
public function tablist(Request $request): Response
51+
{
52+
$session = Session::getSessionFromRequest();
53+
$tabs = $session->getData('discopower:tabList', 'tabs');
54+
$faventry = $session->getData('discopower:tabList', 'faventry');
55+
$defaulttab = $session->getData('discopower:tabList', 'defaulttab');
56+
57+
if (!is_array($tabs)) {
58+
throw new Error\Exception('Could not get tab list from session');
59+
}
60+
61+
$response = new JsonResponse();
62+
63+
// handle JSONP requests
64+
if ($request->query->has('callback')) {
65+
$callback = $request->query->get('callback');
66+
if (!preg_match('/^[a-z0-9_]+$/i', $callback, $matches)) {
67+
throw new Error\Exception('Unsafe JSONP callback function name "' . $matches[0] . '"');
68+
}
69+
$response->setCallback($callback);
70+
}
71+
72+
$response->setData(
73+
[
74+
'faventry' => $faventry,
75+
'default' => $defaulttab,
76+
'tabs' => $tabs,
77+
]
78+
);
79+
return $response;
80+
}
81+
}

routing/routes/routes.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
discopower-main:
2+
path: /disco.php
3+
defaults: { _controller: 'SimpleSAML\Module\discopower\Controller\DiscoPower::main' }
4+
discopower-tablist:
5+
path: /tablist
6+
defaults: { _controller: 'SimpleSAML\Module\discopower\Controller\DiscoPower::tablist' }
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Test\Module\discopower\Controller;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use SimpleSAML\Configuration;
9+
use SimpleSAML\Error;
10+
use SimpleSAML\Module\discopower\Controller;
11+
use SimpleSAML\Session;
12+
use SimpleSAML\Test\Utils\ClearStateTestCase;
13+
use SimpleSAML\XHTML\Template;
14+
use Symfony\Component\HttpFoundation\Request;
15+
16+
/**
17+
* Set of tests for the controllers in the "discopwer" module.
18+
*
19+
* @covers \SimpleSAML\Module\discopower\Controller\DiscoPower
20+
*/
21+
class DiscoPowerTest extends ClearStateTestCase
22+
{
23+
/**
24+
* Set up for each test.
25+
*/
26+
protected function setUp(): void
27+
{
28+
parent::setUp();
29+
30+
$this->config = Configuration::loadFromArray(
31+
[
32+
'module.enable' => ['discopower' => true],
33+
],
34+
'[ARRAY]',
35+
'simplesaml'
36+
);
37+
38+
Configuration::setPreLoadedConfig($this->config, 'config.php');
39+
}
40+
41+
public function testDiscoPowerNoDiscoParams(): void
42+
{
43+
$request = Request::create(
44+
'/disco.php',
45+
'GET'
46+
);
47+
48+
$c = new Controller\DiscoPower();
49+
50+
$this->expectException(Error\Error::class);
51+
$this->expectExceptionMessage("DISCOPARAMS");
52+
$r = $c->main($request);
53+
}
54+
55+
public function testTablistJson(): void
56+
{
57+
$session = Session::getSessionFromRequest();
58+
$session->setData('discopower:tabList', 'faventry', 'http://example.org/idp');
59+
$session->setData('discopower:tabList', 'tabs', ['Frankrijk', 'Nederland', 'Duitsland']);
60+
$session->setData('discopower:tabList', 'defaulttab', 'Nederland');
61+
62+
$request = Request::create(
63+
'/tablist',
64+
'GET'
65+
);
66+
67+
$c = new Controller\DiscoPower();
68+
69+
$r = $c->tablist($request);
70+
$this->assertTrue($r->isSuccessful());
71+
$this->assertEquals('application/json', $r->headers->get('Content-Type'));
72+
$this->assertEquals('{"faventry":"http:\/\/example.org\/idp","default":"Nederland","tabs":["Frankrijk","Nederland","Duitsland"]}', $r->getContent());
73+
74+
$request = Request::create(
75+
'/tablist',
76+
'GET',
77+
['callback' => 'aapnoot'],
78+
);
79+
80+
$c = new Controller\DiscoPower();
81+
82+
$r = $c->tablist($request);
83+
$this->assertTrue($r->isSuccessful());
84+
$this->assertEquals('text/javascript', $r->headers->get('Content-Type'));
85+
$this->assertEquals('/**/aapnoot({"faventry":"http:\/\/example.org\/idp","default":"Nederland","tabs":["Frankrijk","Nederland","Duitsland"]});', $r->getContent());
86+
}
87+
}

www/assets/js/tablist.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
$(document).ready(function () {
22
$("#tabdiv").tabs();
3-
$.getJSON("tablist.php", function (data) {
3+
$.getJSON("tablist", function (data) {
44
$("#tabdiv").select(data["default"]);
55
for (var i = 0; i < data["tabs"].length; i++) {
66
var tab = data["tabs"][i];

www/disco.php

Lines changed: 0 additions & 18 deletions
This file was deleted.

www/tablist.php

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)