Passed
Pull Request — master (#23)
by
unknown
02:10
created

RealMeSetupTaskTest::testValidateEntityID()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 101

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 101
rs 8
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SilverStripe\RealMe\Tests;
4
5
use ReflectionMethod;
6
use ReflectionProperty;
7
use SilverStripe\Core\Config\Config;
8
use SilverStripe\Dev\SapphireTest;
9
use SilverStripe\RealMe\RealMeService;
10
use SilverStripe\RealMe\Task\RealMeSetupTask;
11
12
/**
13
 * Class RealMeSetupTaskTest
14
 * Setup to unit test the Setup task to make sure metadata is being generated correctly.
15
 */
16
class RealMeSetupTaskTest extends SapphireTest
17
{
18
    /**
19
     * Valid entity id's tobe used for context.
20
     * @var array
21
     */
22
    private static $validEntityIDs = array(
23
        RealMeService::ENV_MTS => "https://dev.your-website.govt.nz/p-realm/s-name",
24
        RealMeService::ENV_ITE => 'https://uat.your-website.govt.nz/p-realm/s-name',
25
        RealMeService::ENV_PROD => 'https://www.your-website.govt.nz/p-realm/s-name'
26
    );
27
28
    private static $authnEnvContexts = array(
29
        RealMeService::ENV_MTS => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength',
30
        RealMeService::ENV_ITE => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength',
31
        RealMeService::ENV_PROD => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength'
32
    );
33
34
    private static $metadata_assertion_urls = array(
0 ignored issues
show
introduced by
The private property $metadata_assertion_urls is not used, and could be removed.
Loading history...
35
        RealMeService::ENV_MTS => "https://dev.your-website.govt.nz/",
36
        RealMeService::ENV_ITE => "https://staging.your-website.govt.nz/",
37
        RealMeService::ENV_PROD => "https://www.your-website.govt.nz/"
38
    );
39
40
    /**
41
     * We need to make sure that if an invalid environment, it raises the correct errors for correction.
42
     * - invalid environment
43
     * - no environment
44
     *
45
     * We must also not raise an error if we pass a correctly configured environment.
46
     */
47
    public function testEnvironmentValidation()
48
    {
49
        // Setup our objects for testing through reflection
50
        $realMeService = new RealMeService();
51
        $realMeSetupTask = new RealMeSetupTask();
52
53
        $errors = new ReflectionProperty($realMeSetupTask, 'errors');
54
        $errors->setAccessible(true);
55
56
        $service = new ReflectionProperty($realMeSetupTask, 'service');
57
        $service->setAccessible(true);
58
        $service->setValue($realMeSetupTask, $realMeService);
59
60
        // Make sure there's no errors to begin.
61
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
62
63
        // Test: Make an error
64
        $invalidEnv = "wrong-environment";
65
        $validateEnvironments = new ReflectionMethod($realMeSetupTask, 'validateRealMeEnvironments');
66
        $validateEnvironments->setAccessible(true);
67
        $validateEnvironments->invoke($realMeSetupTask, $invalidEnv);
68
        $this->assertCount(1, $errors->getValue($realMeSetupTask), "An invalid environment should raise an error");
69
70
        // reset errors & Make sure there's no errors to begin.
71
        $errors->setValue($realMeSetupTask, array());
72
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
73
74
        // Test: No environment passed
75
        $noEnvironment = null;
76
        $validateEnvironments = new ReflectionMethod($realMeSetupTask, 'validateRealMeEnvironments');
77
        $validateEnvironments->setAccessible(true);
78
        $validateEnvironments->invoke($realMeSetupTask, $noEnvironment);
79
        $this->assertCount(1, $errors->getValue($realMeSetupTask), "Missing environment should raise an error");
80
81
        // reset errors &&  Make sure there's no errors to begin.
82
        $errors->setValue($realMeSetupTask, array());
83
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
84
85
        // Test: allowed environments pass without error.
86
        $reflectionMethod = new ReflectionMethod($realMeService, 'getAllowedRealMeEnvironments');
87
        $reflectionMethod->setAccessible(true);
88
        foreach ($reflectionMethod->invoke($realMeService) as $validEnvironment) {
89
            $validateEnvironments->invoke($realMeSetupTask, $validEnvironment);
90
        }
91
92
        // Make sure there's no errors, they should all be valid
93
        $this->assertCount(0, $errors->getValue($realMeSetupTask), "valid environments should not raise an error");
94
    }
95
96
    /**
97
     * We need to make sure that there is an entity ID and that it's in the correct format for realme consumption
98
     * - It's present in the config
99
     * - it's not localhost
100
     * - it's not http (must be https)
101
     * - service name and privacy realm < 10 char.
102
     */
103
    public function testValidateEntityID()
104
    {
105
        $realMeService = new RealMeService();
106
        $realMeSetupTask = new RealMeSetupTask();
107
108
        $errors = new ReflectionProperty($realMeSetupTask, 'errors');
109
        $errors->setAccessible(true);
110
111
        $service = new ReflectionProperty($realMeSetupTask, 'service');
112
        $service->setAccessible(true);
113
        $service->setValue($realMeSetupTask, $realMeService);
114
115
        // Make sure there's no errors to begin.
116
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
117
118
        // Test valid entityIds just in case they're different in this configuration.
119
        $config = Config::inst();
120
        $config->update(RealMeService::class, 'sp_entity_ids', self::$validEntityIDs);
0 ignored issues
show
Bug introduced by
The method update() does not exist on SilverStripe\Config\Coll...nfigCollectionInterface. It seems like you code against a sub-type of SilverStripe\Config\Coll...nfigCollectionInterface such as SilverStripe\Config\Coll...\MemoryConfigCollection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
        $config->/** @scrutinizer ignore-call */ 
121
                 update(RealMeService::class, 'sp_entity_ids', self::$validEntityIDs);
Loading history...
121
122
        // validate our list of valid entity IDs;
123
        $validateEntityId = new ReflectionMethod($realMeSetupTask, 'validateEntityID');
124
        $validateEntityId->setAccessible(true);
125
        $validateEntityId->invoke($realMeSetupTask);
126
127
        // valid entityID's shouldn't have any issues
128
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
129
130
        // TEST entityId missing.
131
        $entityIdList = self::$validEntityIDs;
132
        $entityIdList[RealMeService::ENV_MTS] = 'destroy-humans-with-incorrect-entity-ids';
133
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
134
        $validateEntityId->invoke($realMeSetupTask);
135
        $this->assertCount(1, $errors->getValue($realMeSetupTask), 'validate entity id should fail for an invalid url');
136
137
        // reset errors &&  Make sure there's no errors to begin.
138
        $errors->setValue($realMeSetupTask, array());
139
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
140
141
        // TEST entityId localhost.
142
        $entityIdList = self::$validEntityIDs;
143
        $entityIdList[RealMeService::ENV_MTS] = 'https://localhost/';
144
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
145
        $validateEntityId->invoke($realMeSetupTask);
146
        $this->assertCount(1, $errors->getValue($realMeSetupTask), 'validate entity id should fail for localhost');
147
148
        $errors->setValue($realMeSetupTask, array());
149
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
150
151
        // TEST entityId not http
152
        $entityIdList = self::$validEntityIDs;
153
        $entityIdList[RealMeService::ENV_MTS] = 'http://dev.realme-integration.govt.nz/p-realm/s-name';
154
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
155
        $validateEntityId->invoke($realMeSetupTask);
156
        $this->assertCount(1, $errors->getValue($realMeSetupTask), 'validate entity id should fail for http');
157
158
        $errors->setValue($realMeSetupTask, array());
159
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
160
161
        // TEST privacy realm /service name  missing
162
        $entityIdList = self::$validEntityIDs;
163
        $entityIdList[RealMeService::ENV_MTS] = 'https://dev.realme-integration.govt.nz/';
164
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
165
        $validateEntityId->invoke($realMeSetupTask);
166
        $this->assertCount(
167
            2,
168
            $errors->getValue($realMeSetupTask),
169
            'validate entity id should fail for missing service name and privacy realm'
170
        );
171
172
        $errors->setValue($realMeSetupTask, array());
173
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
174
175
        // TEST privacy realm
176
        // "https://www.domain.govt.nz/<privacy-realm>/<service-name>"
177
        $entityIdList = self::$validEntityIDs;
178
        $entityIdList[RealMeService::ENV_MTS] =
179
            'https://dev.realme-integration.govt.nz/s-name/privacy-realm-is-too-big';
180
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
181
        $validateEntityId->invoke($realMeSetupTask);
182
        $this->assertCount(
183
            1,
184
            $errors->getValue($realMeSetupTask),
185
            'validate entity id should fail for privacy-realm-is-too-big'
186
        );
187
188
        $errors->setValue($realMeSetupTask, array());
189
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
190
191
        // "https://www.domain.govt.nz/<privacy-realm>/<service-name>"
192
        $entityIdList = self::$validEntityIDs;
193
        $entityIdList[RealMeService::ENV_MTS] = 'https://dev.realme-integration.govt.nz/s-name';
194
        $config->update(RealMeService::class, 'sp_entity_ids', $entityIdList);
195
        $validateEntityId->invoke($realMeSetupTask);
196
        $this->assertCount(
197
            1,
198
            $errors->getValue($realMeSetupTask),
199
            'validate entity id should fail if privacy realm is missing'
200
        );
201
202
        $errors->setValue($realMeSetupTask, array());
203
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
204
    }
205
206
207
    /**
208
     * We require an authn context for each environment to determine how secure to ask realme to validate.
209
     * - it should be present for each environment, and one of four pre-determined authncontexts.
210
     */
211
    public function testValidateAuthNContext()
212
    {
213
        $realMeService = new RealMeService();
214
        $realMeSetupTask = new RealMeSetupTask();
215
216
        $errors = new ReflectionProperty($realMeSetupTask, 'errors');
217
        $errors->setAccessible(true);
218
219
        $service = new ReflectionProperty($realMeSetupTask, 'service');
220
        $service->setAccessible(true);
221
        $service->setValue($realMeSetupTask, $realMeService);
222
223
        // Make sure there's no errors to begin.
224
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
225
226
        // Test valid authnContexts just in case they're different in this configuration.
227
        $config = Config::inst();
228
        $config->update(RealMeService::class, 'authn_contexts', self::$authnEnvContexts);
229
230
        // validate our list of valid entity IDs;
231
        $validateAuthNContext = new ReflectionMethod($realMeSetupTask, 'validateAuthNContext');
232
        $validateAuthNContext->setAccessible(true);
233
        $validateAuthNContext->invoke($realMeSetupTask);
234
        $this->assertCount(0, $errors->getValue($realMeSetupTask));
235
236
        $invalidAuthNContextList = self::$authnEnvContexts;
237
        $invalidAuthNContextList[RealMeService::ENV_MTS] = 'im-an-invalid-context';
238
        $config->update(RealMeService::class, 'authn_contexts', $invalidAuthNContextList);
239
240
        $validateAuthNContext->invoke($realMeSetupTask);
241
        $this->assertCount(
242
            1,
243
            $errors->getValue($realMeSetupTask),
244
            "The authncontext validation should fail if invalid."
245
        );
246
    }
247
248
    /**
249
     * Ensure that setting the RealMeSetupTask template_config_dir config value
250
     * can adjust the path that the task looks in for its templates.
251
     * - ensure the default works
252
     * - ensure configuring a bad directory name falls back to the default
253
     * - ensure that configuring a good value uses the configured directory
254
     */
255
    public function testConfigurationTemplateDir()
256
    {
257
        $realMeSetupTask = new RealMeSetupTask();
258
259
        $getConfigurationTemplateDirMethod = new ReflectionMethod(RealMeSetupTask::class, 'getConfigurationTemplateDir');
260
        $getConfigurationTemplateDirMethod->setAccessible(true);
261
262
        $config = Config::inst();
263
264
        $config->update(RealMeSetupTask::class, 'template_config_dir', '');
265
        $this->assertEquals(
266
            BASE_PATH . DIRECTORY_SEPARATOR . REALME_MODULE_PATH . '/templates/saml-conf',
267
            $getConfigurationTemplateDirMethod->invoke($realMeSetupTask),
268
            'Using no configuration for template_config_dir should use the default template directory.'
269
        );
270
271
        $config->update(RealMeSetupTask::class, 'template_config_dir', 'xyzzy');
272
        $this->assertEquals(
273
            BASE_PATH . DIRECTORY_SEPARATOR . REALME_MODULE_PATH . '/templates/saml-conf',
274
            $getConfigurationTemplateDirMethod->invoke($realMeSetupTask),
275
            'Configuring a directory that does not exist should use the default template directory.'
276
        );
277
278
        $config->update(RealMeSetupTask::class, 'template_config_dir', REALME_MODULE_PATH);
279
        $this->assertEquals(
280
            BASE_PATH . DIRECTORY_SEPARATOR . REALME_MODULE_PATH, // doesn't contain templates, but does exist
281
            $getConfigurationTemplateDirMethod->invoke($realMeSetupTask),
282
            'Configuring a directory that exists should use the configured template directory.'
283
        );
284
    }
285
}
286