Passed
Pull Request — master (#280)
by Tim
02:26
created

AttributeAuthorityDescriptor::toXML()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 64
nop 1
dl 0
loc 31
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\Constants;
10
use SimpleSAML\SAML2\XML\saml\Attribute;
11
use SimpleSAML\XML\Exception\InvalidDOMElementException;
12
use SimpleSAML\XML\Exception\MissingElementException;
13
use SimpleSAML\XML\Exception\TooManyElementsException;
14
use SimpleSAML\XML\Utils as XMLUtils;
15
use SimpleSAML\XMLSecurity\XML\ds\Signature;
16
17
use function preg_split;
18
19
/**
20
 * Class representing SAML 2 metadata AttributeAuthorityDescriptor.
21
 *
22
 * @package simplesamlphp/saml2
23
 */
24
final class AttributeAuthorityDescriptor extends AbstractRoleDescriptor
25
{
26
    /**
27
     * List of AttributeService endpoints.
28
     *
29
     * Array with EndpointType objects.
30
     *
31
     * @var \SimpleSAML\SAML2\XML\md\AttributeService[]
32
     */
33
    protected array $AttributeServices = [];
34
35
    /**
36
     * List of AssertionIDRequestService endpoints.
37
     *
38
     * Array with EndpointType objects.
39
     *
40
     * @var \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[]
41
     */
42
    protected array $AssertionIDRequestServices = [];
43
44
    /**
45
     * List of supported NameID formats.
46
     *
47
     * Array of strings.
48
     *
49
     * @var \SimpleSAML\SAML2\XML\md\NameIDFormat[]
50
     */
51
    protected array $NameIDFormats = [];
52
53
    /**
54
     * List of supported attribute profiles.
55
     *
56
     * Array with strings.
57
     *
58
     * @var \SimpleSAML\SAML2\XML\md\AttributeProfile[]
59
     */
60
    protected array $AttributeProfiles = [];
61
62
    /**
63
     * List of supported attributes.
64
     *
65
     * Array with \SimpleSAML\SAML2\XML\saml\Attribute objects.
66
     *
67
     * @var Attribute[]
68
     */
69
    protected array $Attributes = [];
70
71
72
    /**
73
     * AttributeAuthorityDescriptor constructor.
74
     *
75
     * @param \SimpleSAML\SAML2\XML\md\AttributeService[] $attributeServices
76
     * @param string[] $protocolSupportEnumeration
77
     * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestService
78
     * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormats
79
     * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfiles
80
     * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes
81
     * @param string|null $ID
82
     * @param int|null $validUntil
83
     * @param string|null $cacheDuration
84
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
85
     * @param string|null $errorURL
86
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
87
     * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors
88
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts
89
     */
90
    public function __construct(
91
        array $attributeServices,
92
        array $protocolSupportEnumeration,
93
        array $assertionIDRequestService = [],
94
        array $nameIDFormats = [],
95
        array $attributeProfiles = [],
96
        array $attributes = [],
97
        ?string $ID = null,
98
        ?int $validUntil = null,
99
        ?string $cacheDuration = null,
100
        ?Extensions $extensions = null,
101
        ?string $errorURL = null,
102
        ?Organization $organization = null,
103
        array $keyDescriptors = [],
104
        array $contacts = []
105
    ) {
106
        parent::__construct(
107
            $protocolSupportEnumeration,
108
            $ID,
109
            $validUntil,
110
            $cacheDuration,
111
            $extensions,
112
            $errorURL,
113
            $keyDescriptors,
114
            $organization,
115
            $contacts
116
        );
117
        $this->setAttributeServices($attributeServices);
118
        $this->setAssertionIDRequestServices($assertionIDRequestService);
119
        $this->setNameIDFormats($nameIDFormats);
120
        $this->setAttributeProfiles($attributeProfiles);
121
        $this->setAttributes($attributes);
122
    }
123
124
125
    /**
126
     * Collect the value of the AttributeService-property
127
     *
128
     * @return \SimpleSAML\SAML2\XML\md\AttributeService[]
129
     */
130
    public function getAttributeServices(): array
131
    {
132
        return $this->AttributeServices;
133
    }
134
135
136
    /**
137
     * Set the value of the AttributeService-property
138
     *
139
     * @param \SimpleSAML\SAML2\XML\md\AttributeService[] $attributeServices
140
     */
141
    protected function setAttributeServices(array $attributeServices): void
142
    {
143
        Assert::minCount(
144
            $attributeServices,
145
            1,
146
            'AttributeAuthorityDescriptor must contain at least one AttributeService.'
147
        );
148
        Assert::allIsInstanceOf(
149
            $attributeServices,
150
            AttributeService::class,
151
            'AttributeService is not an instance of EndpointType.'
152
        );
153
        $this->AttributeServices = $attributeServices;
154
    }
155
156
157
    /**
158
     * Collect the value of the NameIDFormat-property
159
     *
160
     * @return \SimpleSAML\SAML2\XML\md\NameIDFormat[]
161
     */
162
    public function getNameIDFormats(): array
163
    {
164
        return $this->NameIDFormats;
165
    }
166
167
168
    /**
169
     * Set the value of the NameIDFormat-property
170
     *
171
     * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormats
172
     */
173
    protected function setNameIDFormats(array $nameIDFormats): void
174
    {
175
        Assert::allIsInstanceOf($nameIDFormats, NameIDFormat::class);
176
        $this->NameIDFormats = $nameIDFormats;
177
    }
178
179
180
    /**
181
     * Collect the value of the AssertionIDRequestService-property
182
     *
183
     * @return \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[]
184
     */
185
    public function getAssertionIDRequestServices(): array
186
    {
187
        return $this->AssertionIDRequestServices;
188
    }
189
190
191
    /**
192
     * Set the value of the AssertionIDRequestService-property
193
     *
194
     * @param \SimpleSAML\SAML2\XML\md\AssertionIDRequestService[] $assertionIDRequestServices
195
     */
196
    protected function setAssertionIDRequestServices(array $assertionIDRequestServices): void
197
    {
198
        Assert::allIsInstanceOf($assertionIDRequestServices, AssertionIDRequestService::class);
199
        $this->AssertionIDRequestServices = $assertionIDRequestServices;
200
    }
201
202
203
    /**
204
     * Collect the value of the AttributeProfile-property
205
     *
206
     * @return \SimpleSAML\SAML2\XML\md\AttributeProfile[]
207
     */
208
    public function getAttributeProfiles(): array
209
    {
210
        return $this->AttributeProfiles;
211
    }
212
213
214
    /**
215
     * Set the value of the AttributeProfile-property
216
     *
217
     * @param \SimpleSAML\SAML2\XML\md\AttributeProfile[] $attributeProfiles
218
     */
219
    protected function setAttributeProfiles(array $attributeProfiles): void
220
    {
221
        Assert::allIsInstanceOf($attributeProfiles, AttributeProfile::class);
222
        $this->AttributeProfiles = $attributeProfiles;
223
    }
224
225
226
    /**
227
     * Collect the value of the Attribute-property
228
     *
229
     * @return Attribute[]
230
     */
231
    public function getAttributes(): array
232
    {
233
        return $this->Attributes;
234
    }
235
236
237
    /**
238
     * Set the value of the Attribute-property
239
     *
240
     * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes
241
     */
242
    protected function setAttributes(?array $attributes): void
243
    {
244
        Assert::allIsInstanceOf($attributes, Attribute::class);
245
        $this->Attributes = $attributes;
246
    }
247
248
249
    /**
250
     * Initialize an IDPSSODescriptor.
251
     *
252
     * @param \DOMElement $xml The XML element we should load.
253
     * @return self
254
     *
255
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
256
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
257
     * @throws \SimpleSAML\XML\Exception\MissingElementException if one of the mandatory child-elements is missing
258
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
259
     */
260
    public static function fromXML(DOMElement $xml): object
261
    {
262
        Assert::same($xml->localName, 'AttributeAuthorityDescriptor', InvalidDOMElementException::class);
263
        Assert::same($xml->namespaceURI, AttributeAuthorityDescriptor::NS, InvalidDOMElementException::class);
264
265
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
266
        $validUntil = self::getAttribute($xml, 'validUntil', null);
267
268
        $attrServices = AttributeService::getChildrenOfClass($xml);
269
        Assert::notEmpty(
270
            $attrServices,
271
            'Must have at least one AttributeService in AttributeAuthorityDescriptor.',
272
            MissingElementException::class
273
        );
274
275
        $assertIDReqServices = AssertionIDRequestService::getChildrenOfClass($xml);
276
        $nameIDFormats = NameIDFormat::getChildrenOfClass($xml);
277
        $attrProfiles = AttributeProfile::getChildrenOfClass($xml);
278
        $attributes = Attribute::getChildrenOfClass($xml);
279
280
        $orgs = Organization::getChildrenOfClass($xml);
281
        Assert::maxCount($orgs, 1, 'More than one Organization found in this descriptor', TooManyElementsException::class);
282
283
        $extensions = Extensions::getChildrenOfClass($xml);
284
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
285
286
        $signature = Signature::getChildrenOfClass($xml);
287
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
288
289
        $authority = new self(
290
            $attrServices,
291
            preg_split('/[\s]+/', trim($protocols)),
292
            $assertIDReqServices,
293
            $nameIDFormats,
294
            $attrProfiles,
295
            $attributes,
296
            self::getAttribute($xml, 'ID', null),
297
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
298
            self::getAttribute($xml, 'cacheDuration', null),
299
            !empty($extensions) ? $extensions[0] : null,
300
            self::getAttribute($xml, 'errorURL', null),
301
            !empty($orgs) ? $orgs[0] : null,
302
            KeyDescriptor::getChildrenOfClass($xml),
303
            ContactPerson::getChildrenOfClass($xml)
304
        );
305
        if (!empty($signature)) {
306
            $authority->setSignature($signature[0]);
307
        }
308
        return $authority;
309
    }
310
311
312
    /**
313
     * Add this AttributeAuthorityDescriptor to an EntityDescriptor.
314
     *
315
     * @param \DOMElement|null $parent The EntityDescriptor we should append this IDPSSODescriptor to.
316
     * @return \DOMElement
317
     * @throws \Exception
318
     */
319
    public function toXML(DOMElement $parent = null): DOMElement
320
    {
321
        $e = parent::toXML($parent);
322
323
        foreach ($this->AttributeServices as $ep) {
324
            $ep->toXML($e);
325
        }
326
327
        foreach ($this->AssertionIDRequestServices as $ep) {
328
            $ep->toXML($e);
329
        }
330
331
        foreach ($this->NameIDFormats as $nidFormat) {
332
            $nidFormat->toXML($e);
333
        }
334
335
        foreach ($this->AttributeProfiles as $ap) {
336
            $ap->toXML($e);
337
        }
338
339
        foreach ($this->Attributes as $a) {
340
            $a->toXML($e);
341
        }
342
343
        if ($this->signer !== null) {
344
            $signedXML = $this->doSign($e);
345
            $signedXML->insertBefore($this->signature->toXML($signedXML), $signedXML->firstChild);
346
            return $signedXML;
347
        }
348
349
        return $e;
350
    }
351
}
352