Skip to content
This repository was archived by the owner on Sep 19, 2022. It is now read-only.

Commit 903bd6f

Browse files
BaranekDmelanger
authored andcommitted
feat: Custom AttributeMap filter
1 parent d50cac9 commit 903bd6f

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

config-templates/processFilterConfigurations-example.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,18 @@ Example how to enable filter ForceAup:
145145

146146
3.Fill the attributes and set list of required Aups (attr reqAups) and voShortNames (optional) for each facility
147147

148+
## AttributeMap
149+
150+
This filter maps attribute names according to a service specific map from Perun. It can be used to achieve compatibility with a SP which requires specific non-standard attribute names.
151+
152+
Example how to enable filter AttributeMap:
153+
154+
```php
155+
101 => [
156+
'class' => 'perun:AttributeMap',
157+
'attrMapAttr' => 'attrWhichContainsAttrMap', # expected structure: targetAttribute => sourceAttribute
158+
// 'keepSourceAttributes' => true, # optional, whether keep source attributes or remove them, default false
159+
// 'entityid' => 'EntityIdOfTheService', # optional, string or callable, defaults to current SP's entity ID
160+
// 'interface' => 'rpc', # optional, rpc/ldap, default rpc
161+
],
162+
```

lib/Auth/Process/AttributeMap.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\Module\perun\Auth\Process;
6+
7+
use SimpleSAML\Configuration;
8+
use SimpleSAML\Error\Exception;
9+
use SimpleSAML\Logger;
10+
use SimpleSAML\Module\perun\Adapter;
11+
use SimpleSAML\Module\perun\EntitlementUtils;
12+
13+
class AttributeMap extends \SimpleSAML\Auth\ProcessingFilter
14+
{
15+
public const MAP_ATTR_NAME = 'attrMapAttr';
16+
public const KEEP_SOURCE_ATTRIBUTES = 'keepSourceAttributes';
17+
public const ENTITY_ID = 'entityid';
18+
public const INTERFACE_PROPNAME = 'interface';
19+
20+
public const CLASS_PREFIX = 'perun:AttributeMap: ';
21+
public const ATTRIBUTES = 'Attributes';
22+
23+
private $mapAttrName;
24+
private $keepSourceAttributes;
25+
private $entityId;
26+
private $adapter;
27+
28+
public function __construct($config, $reserved)
29+
{
30+
parent::__construct($config, $reserved);
31+
$config = Configuration::loadFromArray($config);
32+
33+
$this->mapAttrName = $config->getString(self::MAP_ATTR_NAME);
34+
$this->keepSourceAttributes = $config->getBoolean(self::KEEP_SOURCE_ATTRIBUTES, false);
35+
$this->entityId = $config->getValue(self::ENTITY_ID);
36+
37+
$interface = $config->getValueValidate(
38+
self::INTERFACE_PROPNAME,
39+
[Adapter::RPC, Adapter::LDAP],
40+
Adapter::RPC
41+
);
42+
43+
$this->adapter = Adapter::getInstance($interface);
44+
}
45+
46+
public function process(&$request)
47+
{
48+
if (null === $this->entityId) {
49+
$this->entityId = EntitlementUtils::getSpEntityId($request);
50+
} elseif (is_callable($this->entityId)) {
51+
$this->entityId = call_user_func($this->entityId, $request);
52+
} elseif (!is_string($this->entityId)) {
53+
throw new Exception(self::CLASS_PREFIX . 'entityid must be a string or a callable');
54+
}
55+
56+
$facility = $this->adapter->getFacilityByEntityId($this->entityId);
57+
58+
if (null === $facility) {
59+
Logger::info(
60+
self::CLASS_PREFIX . 'Facility with entityid ' . $this->entityId . ' not found. Skipping the filter'
61+
);
62+
63+
return;
64+
}
65+
66+
$attrMap = $this->adapter->getFacilityAttributesValues(
67+
$facility,
68+
[$this->mapAttrName]
69+
)[self::MAP_ATTR_NAME] ?? [];
70+
$requestAttributes = &$request[self::ATTRIBUTES];
71+
72+
$mappedSourceAttributes = [];
73+
74+
foreach ($attrMap as $targetAttribute => $sourceAttribute) {
75+
if (isset($requestAttributes[$sourceAttribute])) {
76+
$requestAttributes[$targetAttribute] = $requestAttributes[$sourceAttribute];
77+
78+
if (!$this->keepSourceAttributes && !in_array($sourceAttribute, $mappedSourceAttributes, true)) {
79+
array_push($mappedSourceAttributes, $sourceAttribute);
80+
}
81+
}
82+
}
83+
84+
if (!$this->keepSourceAttributes) {
85+
$requestAttributes = array_diff_key($requestAttributes, array_flip($mappedSourceAttributes));
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)