Completed
Push — master ( ca1fc2...aba39c )
by Joas
31:19 queued 16s
created
tests/Core/Controller/WipeControllerTest.php 2 patches
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -17,87 +17,87 @@
 block discarded – undo
17 17
 use Test\TestCase;
18 18
 
19 19
 class WipeControllerTest extends TestCase {
20
-	/** @var RemoteWipe|MockObject */
21
-	private $remoteWipe;
20
+    /** @var RemoteWipe|MockObject */
21
+    private $remoteWipe;
22 22
 
23
-	/** @var WipeController */
24
-	private $controller;
23
+    /** @var WipeController */
24
+    private $controller;
25 25
 
26
-	protected function setUp(): void {
27
-		parent::setUp();
26
+    protected function setUp(): void {
27
+        parent::setUp();
28 28
 
29
-		$this->remoteWipe = $this->createMock(RemoteWipe::class);
30
-		$this->controller = new WipeController(
31
-			'core',
32
-			$this->createMock(IRequest::class),
33
-			$this->remoteWipe);
34
-	}
29
+        $this->remoteWipe = $this->createMock(RemoteWipe::class);
30
+        $this->controller = new WipeController(
31
+            'core',
32
+            $this->createMock(IRequest::class),
33
+            $this->remoteWipe);
34
+    }
35 35
 
36
-	public static function dataTest(): array {
37
-		return [
38
-			// valid token, could perform operation, valid result
39
-			[ true,  true,  true],
40
-			[ true, false, false],
41
-			[false,  true, false],
42
-			[false, false, false],
43
-		];
44
-	}
36
+    public static function dataTest(): array {
37
+        return [
38
+            // valid token, could perform operation, valid result
39
+            [ true,  true,  true],
40
+            [ true, false, false],
41
+            [false,  true, false],
42
+            [false, false, false],
43
+        ];
44
+    }
45 45
 
46
-	/**
47
-	 * @param bool $valid
48
-	 * @param bool $couldPerform
49
-	 * @param bool $result
50
-	 *
51
-	 * @dataProvider dataTest
52
-	 */
53
-	public function testCheckWipe(bool $valid, bool $couldPerform, bool $result): void {
54
-		if (!$valid) {
55
-			$this->remoteWipe->method('start')
56
-				->with('mytoken')
57
-				->willThrowException(new InvalidTokenException());
58
-		} else {
59
-			$this->remoteWipe->method('start')
60
-				->with('mytoken')
61
-				->willReturn($couldPerform);
62
-		}
46
+    /**
47
+     * @param bool $valid
48
+     * @param bool $couldPerform
49
+     * @param bool $result
50
+     *
51
+     * @dataProvider dataTest
52
+     */
53
+    public function testCheckWipe(bool $valid, bool $couldPerform, bool $result): void {
54
+        if (!$valid) {
55
+            $this->remoteWipe->method('start')
56
+                ->with('mytoken')
57
+                ->willThrowException(new InvalidTokenException());
58
+        } else {
59
+            $this->remoteWipe->method('start')
60
+                ->with('mytoken')
61
+                ->willReturn($couldPerform);
62
+        }
63 63
 
64
-		$result = $this->controller->checkWipe('mytoken');
64
+        $result = $this->controller->checkWipe('mytoken');
65 65
 
66
-		if (!$valid || !$couldPerform) {
67
-			$this->assertSame(Http::STATUS_NOT_FOUND, $result->getStatus());
68
-			$this->assertSame([], $result->getData());
69
-		} else {
70
-			$this->assertSame(Http::STATUS_OK, $result->getStatus());
71
-			$this->assertSame(['wipe' => true], $result->getData());
72
-		}
73
-	}
66
+        if (!$valid || !$couldPerform) {
67
+            $this->assertSame(Http::STATUS_NOT_FOUND, $result->getStatus());
68
+            $this->assertSame([], $result->getData());
69
+        } else {
70
+            $this->assertSame(Http::STATUS_OK, $result->getStatus());
71
+            $this->assertSame(['wipe' => true], $result->getData());
72
+        }
73
+    }
74 74
 
75
-	/**
76
-	 * @param bool $valid
77
-	 * @param bool $couldPerform
78
-	 * @param bool $result
79
-	 *
80
-	 * @dataProvider dataTest
81
-	 */
82
-	public function testWipeDone(bool $valid, bool $couldPerform, bool $result): void {
83
-		if (!$valid) {
84
-			$this->remoteWipe->method('finish')
85
-				->with('mytoken')
86
-				->willThrowException(new InvalidTokenException());
87
-		} else {
88
-			$this->remoteWipe->method('finish')
89
-				->with('mytoken')
90
-				->willReturn($couldPerform);
91
-		}
75
+    /**
76
+     * @param bool $valid
77
+     * @param bool $couldPerform
78
+     * @param bool $result
79
+     *
80
+     * @dataProvider dataTest
81
+     */
82
+    public function testWipeDone(bool $valid, bool $couldPerform, bool $result): void {
83
+        if (!$valid) {
84
+            $this->remoteWipe->method('finish')
85
+                ->with('mytoken')
86
+                ->willThrowException(new InvalidTokenException());
87
+        } else {
88
+            $this->remoteWipe->method('finish')
89
+                ->with('mytoken')
90
+                ->willReturn($couldPerform);
91
+        }
92 92
 
93
-		$result = $this->controller->wipeDone('mytoken');
93
+        $result = $this->controller->wipeDone('mytoken');
94 94
 
95
-		if (!$valid || !$couldPerform) {
96
-			$this->assertSame(Http::STATUS_NOT_FOUND, $result->getStatus());
97
-			$this->assertSame([], $result->getData());
98
-		} else {
99
-			$this->assertSame(Http::STATUS_OK, $result->getStatus());
100
-			$this->assertSame([], $result->getData());
101
-		}
102
-	}
95
+        if (!$valid || !$couldPerform) {
96
+            $this->assertSame(Http::STATUS_NOT_FOUND, $result->getStatus());
97
+            $this->assertSame([], $result->getData());
98
+        } else {
99
+            $this->assertSame(Http::STATUS_OK, $result->getStatus());
100
+            $this->assertSame([], $result->getData());
101
+        }
102
+    }
103 103
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -36,9 +36,9 @@
 block discarded – undo
36 36
 	public static function dataTest(): array {
37 37
 		return [
38 38
 			// valid token, could perform operation, valid result
39
-			[ true,  true,  true],
40
-			[ true, false, false],
41
-			[false,  true, false],
39
+			[true, true, true],
40
+			[true, false, false],
41
+			[false, true, false],
42 42
 			[false, false, false],
43 43
 		];
44 44
 	}
Please login to merge, or discard this patch.
tests/Core/Controller/AutoCompleteControllerTest.php 2 patches
Indentation   +148 added lines, -148 removed lines patch added patch discarded remove patch
@@ -15,160 +15,160 @@
 block discarded – undo
15 15
 use Test\TestCase;
16 16
 
17 17
 class AutoCompleteControllerTest extends TestCase {
18
-	/** @var ISearch|MockObject */
19
-	protected $collaboratorSearch;
20
-	/** @var IManager|MockObject */
21
-	protected $autoCompleteManager;
22
-	/** @var IEventDispatcher|MockObject */
23
-	protected $dispatcher;
24
-	/** @var AutoCompleteController */
25
-	protected $controller;
18
+    /** @var ISearch|MockObject */
19
+    protected $collaboratorSearch;
20
+    /** @var IManager|MockObject */
21
+    protected $autoCompleteManager;
22
+    /** @var IEventDispatcher|MockObject */
23
+    protected $dispatcher;
24
+    /** @var AutoCompleteController */
25
+    protected $controller;
26 26
 
27
-	protected function setUp(): void {
28
-		parent::setUp();
27
+    protected function setUp(): void {
28
+        parent::setUp();
29 29
 
30
-		/** @var IRequest $request */
31
-		$request = $this->createMock(IRequest::class);
32
-		$this->collaboratorSearch = $this->createMock(ISearch::class);
33
-		$this->autoCompleteManager = $this->createMock(IManager::class);
34
-		$this->dispatcher = $this->createMock(IEventDispatcher::class);
30
+        /** @var IRequest $request */
31
+        $request = $this->createMock(IRequest::class);
32
+        $this->collaboratorSearch = $this->createMock(ISearch::class);
33
+        $this->autoCompleteManager = $this->createMock(IManager::class);
34
+        $this->dispatcher = $this->createMock(IEventDispatcher::class);
35 35
 
36
-		$this->controller = new AutoCompleteController(
37
-			'core',
38
-			$request,
39
-			$this->collaboratorSearch,
40
-			$this->autoCompleteManager,
41
-			$this->dispatcher
42
-		);
43
-	}
36
+        $this->controller = new AutoCompleteController(
37
+            'core',
38
+            $request,
39
+            $this->collaboratorSearch,
40
+            $this->autoCompleteManager,
41
+            $this->dispatcher
42
+        );
43
+    }
44 44
 
45
-	public static function searchDataProvider(): array {
46
-		return [
47
-			[ #0 – regular search
48
-				// searchResults
49
-				[
50
-					'exact' => [
51
-						'users' => [],
52
-						'robots' => [],
53
-					],
54
-					'users' => [
55
-						['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
56
-						['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
57
-					],
58
-				],
59
-				// expected
60
-				[
61
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
62
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
63
-				],
64
-				'',
65
-				'files',
66
-				'42',
67
-				null
68
-			],
69
-			[ #1 – missing itemtype and id
70
-				[
71
-					'exact' => [
72
-						'users' => [],
73
-						'robots' => [],
74
-					],
75
-					'users' => [
76
-						['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
77
-						['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
78
-					],
79
-				],
80
-				// expected
81
-				[
82
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
83
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
84
-				],
85
-				'',
86
-				null,
87
-				null,
88
-				null
89
-			],
90
-			[ #2 – with sorter
91
-				[
92
-					'exact' => [
93
-						'users' => [],
94
-						'robots' => [],
95
-					],
96
-					'users' => [
97
-						['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
98
-						['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
99
-					],
100
-				],
101
-				// expected
102
-				[
103
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
104
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
105
-				],
106
-				'',
107
-				'files',
108
-				'42',
109
-				'karma|bus-factor'
110
-			],
111
-			[ #3 – exact Match
112
-				[
113
-					'exact' => [
114
-						'users' => [
115
-							['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
116
-						],
117
-						'robots' => [],
118
-					],
119
-					'users' => [
120
-						['label' => 'Robert R.', 'value' => ['shareWith' => 'bobby']],
121
-					],
122
-				],
123
-				[
124
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
125
-					[ 'id' => 'bobby', 'label' => 'Robert R.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
126
-				],
127
-				'bob',
128
-				'files',
129
-				'42',
130
-				null
131
-			],
132
-			[ #4 – with unique name
133
-				[
134
-					'exact' => [
135
-						'users' => [],
136
-						'robots' => [],
137
-					],
138
-					'users' => [
139
-						['label' => 'Alice A.', 'value' => ['shareWith' => 'alice'], 'shareWithDisplayNameUnique' => '[email protected]'],
140
-						['label' => 'Alice A.', 'value' => ['shareWith' => 'alicea'], 'shareWithDisplayNameUnique' => '[email protected]'],
141
-					],
142
-				],
143
-				// expected
144
-				[
145
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
146
-					[ 'id' => 'alicea', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
147
-				],
148
-				'',
149
-				'files',
150
-				'42',
151
-				'karma|bus-factor'
152
-			],
153
-		];
154
-	}
45
+    public static function searchDataProvider(): array {
46
+        return [
47
+            [ #0 – regular search
48
+                // searchResults
49
+                [
50
+                    'exact' => [
51
+                        'users' => [],
52
+                        'robots' => [],
53
+                    ],
54
+                    'users' => [
55
+                        ['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
56
+                        ['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
57
+                    ],
58
+                ],
59
+                // expected
60
+                [
61
+                    [ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
62
+                    [ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
63
+                ],
64
+                '',
65
+                'files',
66
+                '42',
67
+                null
68
+            ],
69
+            [ #1 – missing itemtype and id
70
+                [
71
+                    'exact' => [
72
+                        'users' => [],
73
+                        'robots' => [],
74
+                    ],
75
+                    'users' => [
76
+                        ['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
77
+                        ['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
78
+                    ],
79
+                ],
80
+                // expected
81
+                [
82
+                    [ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
83
+                    [ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
84
+                ],
85
+                '',
86
+                null,
87
+                null,
88
+                null
89
+            ],
90
+            [ #2 – with sorter
91
+                [
92
+                    'exact' => [
93
+                        'users' => [],
94
+                        'robots' => [],
95
+                    ],
96
+                    'users' => [
97
+                        ['label' => 'Alice A.', 'value' => ['shareWith' => 'alice']],
98
+                        ['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
99
+                    ],
100
+                ],
101
+                // expected
102
+                [
103
+                    [ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
104
+                    [ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
105
+                ],
106
+                '',
107
+                'files',
108
+                '42',
109
+                'karma|bus-factor'
110
+            ],
111
+            [ #3 – exact Match
112
+                [
113
+                    'exact' => [
114
+                        'users' => [
115
+                            ['label' => 'Bob Y.', 'value' => ['shareWith' => 'bob']],
116
+                        ],
117
+                        'robots' => [],
118
+                    ],
119
+                    'users' => [
120
+                        ['label' => 'Robert R.', 'value' => ['shareWith' => 'bobby']],
121
+                    ],
122
+                ],
123
+                [
124
+                    [ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
125
+                    [ 'id' => 'bobby', 'label' => 'Robert R.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
126
+                ],
127
+                'bob',
128
+                'files',
129
+                '42',
130
+                null
131
+            ],
132
+            [ #4 – with unique name
133
+                [
134
+                    'exact' => [
135
+                        'users' => [],
136
+                        'robots' => [],
137
+                    ],
138
+                    'users' => [
139
+                        ['label' => 'Alice A.', 'value' => ['shareWith' => 'alice'], 'shareWithDisplayNameUnique' => '[email protected]'],
140
+                        ['label' => 'Alice A.', 'value' => ['shareWith' => 'alicea'], 'shareWithDisplayNameUnique' => '[email protected]'],
141
+                    ],
142
+                ],
143
+                // expected
144
+                [
145
+                    [ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
146
+                    [ 'id' => 'alicea', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
147
+                ],
148
+                '',
149
+                'files',
150
+                '42',
151
+                'karma|bus-factor'
152
+            ],
153
+        ];
154
+    }
155 155
 
156
-	/**
157
-	 * @dataProvider searchDataProvider
158
-	 */
159
-	public function testGet(array $searchResults, array $expected, string $searchTerm, ?string $itemType, ?string $itemId, ?string $sorter): void {
160
-		$this->collaboratorSearch->expects($this->once())
161
-			->method('search')
162
-			->willReturn([$searchResults, false]);
156
+    /**
157
+     * @dataProvider searchDataProvider
158
+     */
159
+    public function testGet(array $searchResults, array $expected, string $searchTerm, ?string $itemType, ?string $itemId, ?string $sorter): void {
160
+        $this->collaboratorSearch->expects($this->once())
161
+            ->method('search')
162
+            ->willReturn([$searchResults, false]);
163 163
 
164
-		$runSorterFrequency = $sorter === null ? $this->never() : $this->once();
165
-		$this->autoCompleteManager->expects($runSorterFrequency)
166
-			->method('runSorters');
164
+        $runSorterFrequency = $sorter === null ? $this->never() : $this->once();
165
+        $this->autoCompleteManager->expects($runSorterFrequency)
166
+            ->method('runSorters');
167 167
 
168
-		$response = $this->controller->get($searchTerm, $itemType, $itemId, $sorter);
168
+        $response = $this->controller->get($searchTerm, $itemType, $itemId, $sorter);
169 169
 
170
-		$list = $response->getData();
171
-		$this->assertEquals($expected, $list);	// has better error output…
172
-		$this->assertSame($expected, $list);
173
-	}
170
+        $list = $response->getData();
171
+        $this->assertEquals($expected, $list);	// has better error output…
172
+        $this->assertSame($expected, $list);
173
+    }
174 174
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 
45 45
 	public static function searchDataProvider(): array {
46 46
 		return [
47
-			[ #0 – regular search
47
+			[#0 – regular search
48 48
 				// searchResults
49 49
 				[
50 50
 					'exact' => [
@@ -58,15 +58,15 @@  discard block
 block discarded – undo
58 58
 				],
59 59
 				// expected
60 60
 				[
61
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
62
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
61
+					['id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
62
+					['id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
63 63
 				],
64 64
 				'',
65 65
 				'files',
66 66
 				'42',
67 67
 				null
68 68
 			],
69
-			[ #1 – missing itemtype and id
69
+			[#1 – missing itemtype and id
70 70
 				[
71 71
 					'exact' => [
72 72
 						'users' => [],
@@ -79,15 +79,15 @@  discard block
 block discarded – undo
79 79
 				],
80 80
 				// expected
81 81
 				[
82
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
83
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
82
+					['id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
83
+					['id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
84 84
 				],
85 85
 				'',
86 86
 				null,
87 87
 				null,
88 88
 				null
89 89
 			],
90
-			[ #2 – with sorter
90
+			[#2 – with sorter
91 91
 				[
92 92
 					'exact' => [
93 93
 						'users' => [],
@@ -100,15 +100,15 @@  discard block
 block discarded – undo
100 100
 				],
101 101
 				// expected
102 102
 				[
103
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
104
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
103
+					['id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
104
+					['id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
105 105
 				],
106 106
 				'',
107 107
 				'files',
108 108
 				'42',
109 109
 				'karma|bus-factor'
110 110
 			],
111
-			[ #3 – exact Match
111
+			[#3 – exact Match
112 112
 				[
113 113
 					'exact' => [
114 114
 						'users' => [
@@ -121,15 +121,15 @@  discard block
 block discarded – undo
121 121
 					],
122 122
 				],
123 123
 				[
124
-					[ 'id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
125
-					[ 'id' => 'bobby', 'label' => 'Robert R.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
124
+					['id' => 'bob', 'label' => 'Bob Y.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
125
+					['id' => 'bobby', 'label' => 'Robert R.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => ''],
126 126
 				],
127 127
 				'bob',
128 128
 				'files',
129 129
 				'42',
130 130
 				null
131 131
 			],
132
-			[ #4 – with unique name
132
+			[#4 – with unique name
133 133
 				[
134 134
 					'exact' => [
135 135
 						'users' => [],
@@ -142,8 +142,8 @@  discard block
 block discarded – undo
142 142
 				],
143 143
 				// expected
144 144
 				[
145
-					[ 'id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
146
-					[ 'id' => 'alicea', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
145
+					['id' => 'alice', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
146
+					['id' => 'alicea', 'label' => 'Alice A.', 'icon' => '', 'source' => 'users', 'status' => '', 'subline' => '', 'shareWithDisplayNameUnique' => '[email protected]'],
147 147
 				],
148 148
 				'',
149 149
 				'files',
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
 		$response = $this->controller->get($searchTerm, $itemType, $itemId, $sorter);
169 169
 
170 170
 		$list = $response->getData();
171
-		$this->assertEquals($expected, $list);	// has better error output…
171
+		$this->assertEquals($expected, $list); // has better error output…
172 172
 		$this->assertSame($expected, $list);
173 173
 	}
174 174
 }
Please login to merge, or discard this patch.
tests/Core/Controller/TwoFactorChallengeControllerTest.php 2 patches
Indentation   +416 added lines, -416 removed lines patch added patch discarded remove patch
@@ -27,420 +27,420 @@
 block discarded – undo
27 27
 use Test\TestCase;
28 28
 
29 29
 class TwoFactorChallengeControllerTest extends TestCase {
30
-	/** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
31
-	private $request;
32
-
33
-	/** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
34
-	private $twoFactorManager;
35
-
36
-	/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
37
-	private $userSession;
38
-
39
-	/** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
40
-	private $session;
41
-
42
-	/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
43
-	private $urlGenerator;
44
-
45
-	/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
46
-	private $logger;
47
-
48
-	/** @var TwoFactorChallengeController|\PHPUnit\Framework\MockObject\MockObject */
49
-	private $controller;
50
-
51
-	protected function setUp(): void {
52
-		parent::setUp();
53
-
54
-		$this->request = $this->createMock(IRequest::class);
55
-		$this->twoFactorManager = $this->createMock(Manager::class);
56
-		$this->userSession = $this->createMock(IUserSession::class);
57
-		$this->session = $this->createMock(ISession::class);
58
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
59
-		$this->logger = $this->createMock(LoggerInterface::class);
60
-
61
-		$this->controller = $this->getMockBuilder(TwoFactorChallengeController::class)
62
-			->setConstructorArgs([
63
-				'core',
64
-				$this->request,
65
-				$this->twoFactorManager,
66
-				$this->userSession,
67
-				$this->session,
68
-				$this->urlGenerator,
69
-				$this->logger,
70
-			])
71
-			->onlyMethods(['getLogoutUrl'])
72
-			->getMock();
73
-		$this->controller->expects($this->any())
74
-			->method('getLogoutUrl')
75
-			->willReturn('logoutAttribute');
76
-	}
77
-
78
-	public function testSelectChallenge(): void {
79
-		$user = $this->getMockBuilder(IUser::class)->getMock();
80
-		$p1 = $this->createMock(IActivatableAtLogin::class);
81
-		$p1->method('getId')->willReturn('p1');
82
-		$backupProvider = $this->createMock(IProvider::class);
83
-		$backupProvider->method('getId')->willReturn('backup_codes');
84
-		$providerSet = new ProviderSet([$p1, $backupProvider], true);
85
-		$this->twoFactorManager->expects($this->once())
86
-			->method('getLoginSetupProviders')
87
-			->with($user)
88
-			->willReturn([$p1]);
89
-
90
-		$this->userSession->expects($this->once())
91
-			->method('getUser')
92
-			->willReturn($user);
93
-		$this->twoFactorManager->expects($this->once())
94
-			->method('getProviderSet')
95
-			->with($user)
96
-			->willReturn($providerSet);
97
-
98
-		$expected = new StandaloneTemplateResponse('core', 'twofactorselectchallenge', [
99
-			'providers' => [
100
-				$p1,
101
-			],
102
-			'providerMissing' => true,
103
-			'backupProvider' => $backupProvider,
104
-			'redirect_url' => '/some/url',
105
-			'logout_url' => 'logoutAttribute',
106
-			'hasSetupProviders' => true,
107
-		], 'guest');
108
-
109
-		$this->assertEquals($expected, $this->controller->selectChallenge('/some/url'));
110
-	}
111
-
112
-	public function testShowChallenge(): void {
113
-		$user = $this->createMock(IUser::class);
114
-		$provider = $this->createMock(IProvider::class);
115
-		$provider->method('getId')->willReturn('myprovider');
116
-		$backupProvider = $this->createMock(IProvider::class);
117
-		$backupProvider->method('getId')->willReturn('backup_codes');
118
-		$tmpl = $this->createMock(ITemplate::class);
119
-		$providerSet = new ProviderSet([$provider, $backupProvider], true);
120
-
121
-		$this->userSession->expects($this->once())
122
-			->method('getUser')
123
-			->willReturn($user);
124
-		$this->twoFactorManager->expects($this->once())
125
-			->method('getProviderSet')
126
-			->with($user)
127
-			->willReturn($providerSet);
128
-		$provider->expects($this->once())
129
-			->method('getId')
130
-			->willReturn('u2f');
131
-		$backupProvider->expects($this->once())
132
-			->method('getId')
133
-			->willReturn('backup_codes');
134
-
135
-		$this->session->expects($this->once())
136
-			->method('exists')
137
-			->with('two_factor_auth_error')
138
-			->willReturn(true);
139
-		$this->session->expects($this->exactly(2))
140
-			->method('remove')
141
-			->with($this->logicalOr($this->equalTo('two_factor_auth_error'), $this->equalTo('two_factor_auth_error_message')));
142
-		$provider->expects($this->once())
143
-			->method('getTemplate')
144
-			->with($user)
145
-			->willReturn($tmpl);
146
-		$tmpl->expects($this->once())
147
-			->method('fetchPage')
148
-			->willReturn('<html/>');
149
-
150
-		$expected = new StandaloneTemplateResponse('core', 'twofactorshowchallenge', [
151
-			'error' => true,
152
-			'provider' => $provider,
153
-			'backupProvider' => $backupProvider,
154
-			'logout_url' => 'logoutAttribute',
155
-			'template' => '<html/>',
156
-			'redirect_url' => '/re/dir/ect/url',
157
-			'error_message' => null,
158
-		], 'guest');
159
-
160
-		$this->assertEquals($expected, $this->controller->showChallenge('myprovider', '/re/dir/ect/url'));
161
-	}
162
-
163
-	public function testShowInvalidChallenge(): void {
164
-		$user = $this->createMock(IUser::class);
165
-		$providerSet = new ProviderSet([], false);
166
-
167
-		$this->userSession->expects($this->once())
168
-			->method('getUser')
169
-			->willReturn($user);
170
-		$this->twoFactorManager->expects($this->once())
171
-			->method('getProviderSet')
172
-			->with($user)
173
-			->willReturn($providerSet);
174
-		$this->urlGenerator->expects($this->once())
175
-			->method('linkToRoute')
176
-			->with('core.TwoFactorChallenge.selectChallenge')
177
-			->willReturn('select/challenge/url');
178
-
179
-		$expected = new RedirectResponse('select/challenge/url');
180
-
181
-		$this->assertEquals($expected, $this->controller->showChallenge('myprovider', 'redirect/url'));
182
-	}
183
-
184
-	public function testSolveChallenge(): void {
185
-		$user = $this->createMock(IUser::class);
186
-		$provider = $this->createMock(IProvider::class);
187
-
188
-		$this->userSession->expects($this->once())
189
-			->method('getUser')
190
-			->willReturn($user);
191
-		$this->twoFactorManager->expects($this->once())
192
-			->method('getProvider')
193
-			->with($user, 'myprovider')
194
-			->willReturn($provider);
195
-
196
-		$this->twoFactorManager->expects($this->once())
197
-			->method('verifyChallenge')
198
-			->with('myprovider', $user, 'token')
199
-			->willReturn(true);
200
-		$this->urlGenerator
201
-			->expects($this->once())
202
-			->method('linkToDefaultPageUrl')
203
-			->willReturn('/default/foo');
204
-
205
-		$expected = new RedirectResponse('/default/foo');
206
-		$this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token'));
207
-	}
208
-
209
-	public function testSolveValidChallengeAndRedirect(): void {
210
-		$user = $this->createMock(IUser::class);
211
-		$provider = $this->createMock(IProvider::class);
212
-
213
-		$this->userSession->expects($this->once())
214
-			->method('getUser')
215
-			->willReturn($user);
216
-		$this->twoFactorManager->expects($this->once())
217
-			->method('getProvider')
218
-			->with($user, 'myprovider')
219
-			->willReturn($provider);
220
-
221
-		$this->twoFactorManager->expects($this->once())
222
-			->method('verifyChallenge')
223
-			->with('myprovider', $user, 'token')
224
-			->willReturn(true);
225
-		$this->urlGenerator->expects($this->once())
226
-			->method('getAbsoluteURL')
227
-			->with('redirect url')
228
-			->willReturn('redirect/url');
229
-
230
-		$expected = new RedirectResponse('redirect/url');
231
-		$this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', 'redirect%20url'));
232
-	}
233
-
234
-	public function testSolveChallengeInvalidProvider(): void {
235
-		$user = $this->getMockBuilder(IUser::class)->getMock();
236
-
237
-		$this->userSession->expects($this->once())
238
-			->method('getUser')
239
-			->willReturn($user);
240
-		$this->twoFactorManager->expects($this->once())
241
-			->method('getProvider')
242
-			->with($user, 'myprovider')
243
-			->willReturn(null);
244
-		$this->urlGenerator->expects($this->once())
245
-			->method('linkToRoute')
246
-			->with('core.TwoFactorChallenge.selectChallenge')
247
-			->willReturn('select/challenge/url');
248
-
249
-		$expected = new RedirectResponse('select/challenge/url');
250
-
251
-		$this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token'));
252
-	}
253
-
254
-	public function testSolveInvalidChallenge(): void {
255
-		$user = $this->createMock(IUser::class);
256
-		$provider = $this->createMock(IProvider::class);
257
-
258
-		$this->userSession->expects($this->once())
259
-			->method('getUser')
260
-			->willReturn($user);
261
-		$this->twoFactorManager->expects($this->once())
262
-			->method('getProvider')
263
-			->with($user, 'myprovider')
264
-			->willReturn($provider);
265
-
266
-		$this->twoFactorManager->expects($this->once())
267
-			->method('verifyChallenge')
268
-			->with('myprovider', $user, 'token')
269
-			->willReturn(false);
270
-		$this->session->expects($this->once())
271
-			->method('set')
272
-			->with('two_factor_auth_error', true);
273
-		$this->urlGenerator->expects($this->once())
274
-			->method('linkToRoute')
275
-			->with('core.TwoFactorChallenge.showChallenge', [
276
-				'challengeProviderId' => 'myprovider',
277
-				'redirect_url' => '/url',
278
-			])
279
-			->willReturn('files/index/url');
280
-		$provider->expects($this->once())
281
-			->method('getId')
282
-			->willReturn('myprovider');
283
-
284
-		$expected = new RedirectResponse('files/index/url');
285
-		$this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url'));
286
-	}
287
-
288
-	public function testSolveChallengeTwoFactorException(): void {
289
-		$user = $this->createMock(IUser::class);
290
-		$provider = $this->createMock(IProvider::class);
291
-		$exception = new TwoFactorException('2FA failed');
292
-
293
-		$this->userSession->expects($this->once())
294
-			->method('getUser')
295
-			->willReturn($user);
296
-		$this->twoFactorManager->expects($this->once())
297
-			->method('getProvider')
298
-			->with($user, 'myprovider')
299
-			->willReturn($provider);
300
-
301
-		$this->twoFactorManager->expects($this->once())
302
-			->method('verifyChallenge')
303
-			->with('myprovider', $user, 'token')
304
-			->will($this->throwException($exception));
305
-		$calls = [
306
-			['two_factor_auth_error_message', '2FA failed'],
307
-			['two_factor_auth_error', true],
308
-		];
309
-		$this->session->expects($this->exactly(2))
310
-			->method('set')
311
-			->willReturnCallback(function () use (&$calls) {
312
-				$expected = array_shift($calls);
313
-				$this->assertEquals($expected, func_get_args());
314
-			});
315
-		$this->urlGenerator->expects($this->once())
316
-			->method('linkToRoute')
317
-			->with('core.TwoFactorChallenge.showChallenge', [
318
-				'challengeProviderId' => 'myprovider',
319
-				'redirect_url' => '/url',
320
-			])
321
-			->willReturn('files/index/url');
322
-		$provider->expects($this->once())
323
-			->method('getId')
324
-			->willReturn('myprovider');
325
-
326
-		$expected = new RedirectResponse('files/index/url');
327
-		$this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url'));
328
-	}
329
-
330
-	public function testSetUpProviders(): void {
331
-		$user = $this->createMock(IUser::class);
332
-		$this->userSession->expects($this->once())
333
-			->method('getUser')
334
-			->willReturn($user);
335
-		$provider = $this->createMock(IActivatableAtLogin::class);
336
-		$this->twoFactorManager->expects($this->once())
337
-			->method('getLoginSetupProviders')
338
-			->with($user)
339
-			->willReturn([
340
-				$provider,
341
-			]);
342
-		$expected = new StandaloneTemplateResponse(
343
-			'core',
344
-			'twofactorsetupselection',
345
-			[
346
-				'providers' => [
347
-					$provider,
348
-				],
349
-				'logout_url' => 'logoutAttribute',
350
-				'redirect_url' => null,
351
-			],
352
-			'guest'
353
-		);
354
-
355
-		$response = $this->controller->setupProviders();
356
-
357
-		$this->assertEquals($expected, $response);
358
-	}
359
-
360
-	public function testSetUpInvalidProvider(): void {
361
-		$user = $this->createMock(IUser::class);
362
-		$this->userSession->expects($this->once())
363
-			->method('getUser')
364
-			->willReturn($user);
365
-		$provider = $this->createMock(IActivatableAtLogin::class);
366
-		$provider->expects($this->any())
367
-			->method('getId')
368
-			->willReturn('prov1');
369
-		$this->twoFactorManager->expects($this->once())
370
-			->method('getLoginSetupProviders')
371
-			->with($user)
372
-			->willReturn([
373
-				$provider,
374
-			]);
375
-		$this->urlGenerator->expects($this->once())
376
-			->method('linkToRoute')
377
-			->with('core.TwoFactorChallenge.selectChallenge')
378
-			->willReturn('2fa/select/page');
379
-		$expected = new RedirectResponse('2fa/select/page');
380
-
381
-		$response = $this->controller->setupProvider('prov2');
382
-
383
-		$this->assertEquals($expected, $response);
384
-	}
385
-
386
-	public function testSetUpProvider(): void {
387
-		$user = $this->createMock(IUser::class);
388
-		$this->userSession->expects($this->once())
389
-			->method('getUser')
390
-			->willReturn($user);
391
-		$provider = $this->createMock(IActivatableAtLogin::class);
392
-		$provider->expects($this->any())
393
-			->method('getId')
394
-			->willReturn('prov1');
395
-		$this->twoFactorManager->expects($this->once())
396
-			->method('getLoginSetupProviders')
397
-			->with($user)
398
-			->willReturn([
399
-				$provider,
400
-			]);
401
-		$loginSetup = $this->createMock(ILoginSetupProvider::class);
402
-		$provider->expects($this->any())
403
-			->method('getLoginSetup')
404
-			->with($user)
405
-			->willReturn($loginSetup);
406
-		$tmpl = $this->createMock(ITemplate::class);
407
-		$loginSetup->expects($this->once())
408
-			->method('getBody')
409
-			->willReturn($tmpl);
410
-		$tmpl->expects($this->once())
411
-			->method('fetchPage')
412
-			->willReturn('tmpl');
413
-		$expected = new StandaloneTemplateResponse(
414
-			'core',
415
-			'twofactorsetupchallenge',
416
-			[
417
-				'provider' => $provider,
418
-				'logout_url' => 'logoutAttribute',
419
-				'template' => 'tmpl',
420
-				'redirect_url' => null,
421
-			],
422
-			'guest'
423
-		);
424
-
425
-		$response = $this->controller->setupProvider('prov1');
426
-
427
-		$this->assertEquals($expected, $response);
428
-	}
429
-
430
-	public function testConfirmProviderSetup(): void {
431
-		$this->urlGenerator->expects($this->once())
432
-			->method('linkToRoute')
433
-			->with(
434
-				'core.TwoFactorChallenge.showChallenge',
435
-				[
436
-					'challengeProviderId' => 'totp',
437
-					'redirect_url' => null,
438
-				])
439
-			->willReturn('2fa/select/page');
440
-		$expected = new RedirectResponse('2fa/select/page');
441
-
442
-		$response = $this->controller->confirmProviderSetup('totp');
443
-
444
-		$this->assertEquals($expected, $response);
445
-	}
30
+    /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
31
+    private $request;
32
+
33
+    /** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
34
+    private $twoFactorManager;
35
+
36
+    /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
37
+    private $userSession;
38
+
39
+    /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
40
+    private $session;
41
+
42
+    /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
43
+    private $urlGenerator;
44
+
45
+    /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
46
+    private $logger;
47
+
48
+    /** @var TwoFactorChallengeController|\PHPUnit\Framework\MockObject\MockObject */
49
+    private $controller;
50
+
51
+    protected function setUp(): void {
52
+        parent::setUp();
53
+
54
+        $this->request = $this->createMock(IRequest::class);
55
+        $this->twoFactorManager = $this->createMock(Manager::class);
56
+        $this->userSession = $this->createMock(IUserSession::class);
57
+        $this->session = $this->createMock(ISession::class);
58
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
59
+        $this->logger = $this->createMock(LoggerInterface::class);
60
+
61
+        $this->controller = $this->getMockBuilder(TwoFactorChallengeController::class)
62
+            ->setConstructorArgs([
63
+                'core',
64
+                $this->request,
65
+                $this->twoFactorManager,
66
+                $this->userSession,
67
+                $this->session,
68
+                $this->urlGenerator,
69
+                $this->logger,
70
+            ])
71
+            ->onlyMethods(['getLogoutUrl'])
72
+            ->getMock();
73
+        $this->controller->expects($this->any())
74
+            ->method('getLogoutUrl')
75
+            ->willReturn('logoutAttribute');
76
+    }
77
+
78
+    public function testSelectChallenge(): void {
79
+        $user = $this->getMockBuilder(IUser::class)->getMock();
80
+        $p1 = $this->createMock(IActivatableAtLogin::class);
81
+        $p1->method('getId')->willReturn('p1');
82
+        $backupProvider = $this->createMock(IProvider::class);
83
+        $backupProvider->method('getId')->willReturn('backup_codes');
84
+        $providerSet = new ProviderSet([$p1, $backupProvider], true);
85
+        $this->twoFactorManager->expects($this->once())
86
+            ->method('getLoginSetupProviders')
87
+            ->with($user)
88
+            ->willReturn([$p1]);
89
+
90
+        $this->userSession->expects($this->once())
91
+            ->method('getUser')
92
+            ->willReturn($user);
93
+        $this->twoFactorManager->expects($this->once())
94
+            ->method('getProviderSet')
95
+            ->with($user)
96
+            ->willReturn($providerSet);
97
+
98
+        $expected = new StandaloneTemplateResponse('core', 'twofactorselectchallenge', [
99
+            'providers' => [
100
+                $p1,
101
+            ],
102
+            'providerMissing' => true,
103
+            'backupProvider' => $backupProvider,
104
+            'redirect_url' => '/some/url',
105
+            'logout_url' => 'logoutAttribute',
106
+            'hasSetupProviders' => true,
107
+        ], 'guest');
108
+
109
+        $this->assertEquals($expected, $this->controller->selectChallenge('/some/url'));
110
+    }
111
+
112
+    public function testShowChallenge(): void {
113
+        $user = $this->createMock(IUser::class);
114
+        $provider = $this->createMock(IProvider::class);
115
+        $provider->method('getId')->willReturn('myprovider');
116
+        $backupProvider = $this->createMock(IProvider::class);
117
+        $backupProvider->method('getId')->willReturn('backup_codes');
118
+        $tmpl = $this->createMock(ITemplate::class);
119
+        $providerSet = new ProviderSet([$provider, $backupProvider], true);
120
+
121
+        $this->userSession->expects($this->once())
122
+            ->method('getUser')
123
+            ->willReturn($user);
124
+        $this->twoFactorManager->expects($this->once())
125
+            ->method('getProviderSet')
126
+            ->with($user)
127
+            ->willReturn($providerSet);
128
+        $provider->expects($this->once())
129
+            ->method('getId')
130
+            ->willReturn('u2f');
131
+        $backupProvider->expects($this->once())
132
+            ->method('getId')
133
+            ->willReturn('backup_codes');
134
+
135
+        $this->session->expects($this->once())
136
+            ->method('exists')
137
+            ->with('two_factor_auth_error')
138
+            ->willReturn(true);
139
+        $this->session->expects($this->exactly(2))
140
+            ->method('remove')
141
+            ->with($this->logicalOr($this->equalTo('two_factor_auth_error'), $this->equalTo('two_factor_auth_error_message')));
142
+        $provider->expects($this->once())
143
+            ->method('getTemplate')
144
+            ->with($user)
145
+            ->willReturn($tmpl);
146
+        $tmpl->expects($this->once())
147
+            ->method('fetchPage')
148
+            ->willReturn('<html/>');
149
+
150
+        $expected = new StandaloneTemplateResponse('core', 'twofactorshowchallenge', [
151
+            'error' => true,
152
+            'provider' => $provider,
153
+            'backupProvider' => $backupProvider,
154
+            'logout_url' => 'logoutAttribute',
155
+            'template' => '<html/>',
156
+            'redirect_url' => '/re/dir/ect/url',
157
+            'error_message' => null,
158
+        ], 'guest');
159
+
160
+        $this->assertEquals($expected, $this->controller->showChallenge('myprovider', '/re/dir/ect/url'));
161
+    }
162
+
163
+    public function testShowInvalidChallenge(): void {
164
+        $user = $this->createMock(IUser::class);
165
+        $providerSet = new ProviderSet([], false);
166
+
167
+        $this->userSession->expects($this->once())
168
+            ->method('getUser')
169
+            ->willReturn($user);
170
+        $this->twoFactorManager->expects($this->once())
171
+            ->method('getProviderSet')
172
+            ->with($user)
173
+            ->willReturn($providerSet);
174
+        $this->urlGenerator->expects($this->once())
175
+            ->method('linkToRoute')
176
+            ->with('core.TwoFactorChallenge.selectChallenge')
177
+            ->willReturn('select/challenge/url');
178
+
179
+        $expected = new RedirectResponse('select/challenge/url');
180
+
181
+        $this->assertEquals($expected, $this->controller->showChallenge('myprovider', 'redirect/url'));
182
+    }
183
+
184
+    public function testSolveChallenge(): void {
185
+        $user = $this->createMock(IUser::class);
186
+        $provider = $this->createMock(IProvider::class);
187
+
188
+        $this->userSession->expects($this->once())
189
+            ->method('getUser')
190
+            ->willReturn($user);
191
+        $this->twoFactorManager->expects($this->once())
192
+            ->method('getProvider')
193
+            ->with($user, 'myprovider')
194
+            ->willReturn($provider);
195
+
196
+        $this->twoFactorManager->expects($this->once())
197
+            ->method('verifyChallenge')
198
+            ->with('myprovider', $user, 'token')
199
+            ->willReturn(true);
200
+        $this->urlGenerator
201
+            ->expects($this->once())
202
+            ->method('linkToDefaultPageUrl')
203
+            ->willReturn('/default/foo');
204
+
205
+        $expected = new RedirectResponse('/default/foo');
206
+        $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token'));
207
+    }
208
+
209
+    public function testSolveValidChallengeAndRedirect(): void {
210
+        $user = $this->createMock(IUser::class);
211
+        $provider = $this->createMock(IProvider::class);
212
+
213
+        $this->userSession->expects($this->once())
214
+            ->method('getUser')
215
+            ->willReturn($user);
216
+        $this->twoFactorManager->expects($this->once())
217
+            ->method('getProvider')
218
+            ->with($user, 'myprovider')
219
+            ->willReturn($provider);
220
+
221
+        $this->twoFactorManager->expects($this->once())
222
+            ->method('verifyChallenge')
223
+            ->with('myprovider', $user, 'token')
224
+            ->willReturn(true);
225
+        $this->urlGenerator->expects($this->once())
226
+            ->method('getAbsoluteURL')
227
+            ->with('redirect url')
228
+            ->willReturn('redirect/url');
229
+
230
+        $expected = new RedirectResponse('redirect/url');
231
+        $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', 'redirect%20url'));
232
+    }
233
+
234
+    public function testSolveChallengeInvalidProvider(): void {
235
+        $user = $this->getMockBuilder(IUser::class)->getMock();
236
+
237
+        $this->userSession->expects($this->once())
238
+            ->method('getUser')
239
+            ->willReturn($user);
240
+        $this->twoFactorManager->expects($this->once())
241
+            ->method('getProvider')
242
+            ->with($user, 'myprovider')
243
+            ->willReturn(null);
244
+        $this->urlGenerator->expects($this->once())
245
+            ->method('linkToRoute')
246
+            ->with('core.TwoFactorChallenge.selectChallenge')
247
+            ->willReturn('select/challenge/url');
248
+
249
+        $expected = new RedirectResponse('select/challenge/url');
250
+
251
+        $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token'));
252
+    }
253
+
254
+    public function testSolveInvalidChallenge(): void {
255
+        $user = $this->createMock(IUser::class);
256
+        $provider = $this->createMock(IProvider::class);
257
+
258
+        $this->userSession->expects($this->once())
259
+            ->method('getUser')
260
+            ->willReturn($user);
261
+        $this->twoFactorManager->expects($this->once())
262
+            ->method('getProvider')
263
+            ->with($user, 'myprovider')
264
+            ->willReturn($provider);
265
+
266
+        $this->twoFactorManager->expects($this->once())
267
+            ->method('verifyChallenge')
268
+            ->with('myprovider', $user, 'token')
269
+            ->willReturn(false);
270
+        $this->session->expects($this->once())
271
+            ->method('set')
272
+            ->with('two_factor_auth_error', true);
273
+        $this->urlGenerator->expects($this->once())
274
+            ->method('linkToRoute')
275
+            ->with('core.TwoFactorChallenge.showChallenge', [
276
+                'challengeProviderId' => 'myprovider',
277
+                'redirect_url' => '/url',
278
+            ])
279
+            ->willReturn('files/index/url');
280
+        $provider->expects($this->once())
281
+            ->method('getId')
282
+            ->willReturn('myprovider');
283
+
284
+        $expected = new RedirectResponse('files/index/url');
285
+        $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url'));
286
+    }
287
+
288
+    public function testSolveChallengeTwoFactorException(): void {
289
+        $user = $this->createMock(IUser::class);
290
+        $provider = $this->createMock(IProvider::class);
291
+        $exception = new TwoFactorException('2FA failed');
292
+
293
+        $this->userSession->expects($this->once())
294
+            ->method('getUser')
295
+            ->willReturn($user);
296
+        $this->twoFactorManager->expects($this->once())
297
+            ->method('getProvider')
298
+            ->with($user, 'myprovider')
299
+            ->willReturn($provider);
300
+
301
+        $this->twoFactorManager->expects($this->once())
302
+            ->method('verifyChallenge')
303
+            ->with('myprovider', $user, 'token')
304
+            ->will($this->throwException($exception));
305
+        $calls = [
306
+            ['two_factor_auth_error_message', '2FA failed'],
307
+            ['two_factor_auth_error', true],
308
+        ];
309
+        $this->session->expects($this->exactly(2))
310
+            ->method('set')
311
+            ->willReturnCallback(function () use (&$calls) {
312
+                $expected = array_shift($calls);
313
+                $this->assertEquals($expected, func_get_args());
314
+            });
315
+        $this->urlGenerator->expects($this->once())
316
+            ->method('linkToRoute')
317
+            ->with('core.TwoFactorChallenge.showChallenge', [
318
+                'challengeProviderId' => 'myprovider',
319
+                'redirect_url' => '/url',
320
+            ])
321
+            ->willReturn('files/index/url');
322
+        $provider->expects($this->once())
323
+            ->method('getId')
324
+            ->willReturn('myprovider');
325
+
326
+        $expected = new RedirectResponse('files/index/url');
327
+        $this->assertEquals($expected, $this->controller->solveChallenge('myprovider', 'token', '/url'));
328
+    }
329
+
330
+    public function testSetUpProviders(): void {
331
+        $user = $this->createMock(IUser::class);
332
+        $this->userSession->expects($this->once())
333
+            ->method('getUser')
334
+            ->willReturn($user);
335
+        $provider = $this->createMock(IActivatableAtLogin::class);
336
+        $this->twoFactorManager->expects($this->once())
337
+            ->method('getLoginSetupProviders')
338
+            ->with($user)
339
+            ->willReturn([
340
+                $provider,
341
+            ]);
342
+        $expected = new StandaloneTemplateResponse(
343
+            'core',
344
+            'twofactorsetupselection',
345
+            [
346
+                'providers' => [
347
+                    $provider,
348
+                ],
349
+                'logout_url' => 'logoutAttribute',
350
+                'redirect_url' => null,
351
+            ],
352
+            'guest'
353
+        );
354
+
355
+        $response = $this->controller->setupProviders();
356
+
357
+        $this->assertEquals($expected, $response);
358
+    }
359
+
360
+    public function testSetUpInvalidProvider(): void {
361
+        $user = $this->createMock(IUser::class);
362
+        $this->userSession->expects($this->once())
363
+            ->method('getUser')
364
+            ->willReturn($user);
365
+        $provider = $this->createMock(IActivatableAtLogin::class);
366
+        $provider->expects($this->any())
367
+            ->method('getId')
368
+            ->willReturn('prov1');
369
+        $this->twoFactorManager->expects($this->once())
370
+            ->method('getLoginSetupProviders')
371
+            ->with($user)
372
+            ->willReturn([
373
+                $provider,
374
+            ]);
375
+        $this->urlGenerator->expects($this->once())
376
+            ->method('linkToRoute')
377
+            ->with('core.TwoFactorChallenge.selectChallenge')
378
+            ->willReturn('2fa/select/page');
379
+        $expected = new RedirectResponse('2fa/select/page');
380
+
381
+        $response = $this->controller->setupProvider('prov2');
382
+
383
+        $this->assertEquals($expected, $response);
384
+    }
385
+
386
+    public function testSetUpProvider(): void {
387
+        $user = $this->createMock(IUser::class);
388
+        $this->userSession->expects($this->once())
389
+            ->method('getUser')
390
+            ->willReturn($user);
391
+        $provider = $this->createMock(IActivatableAtLogin::class);
392
+        $provider->expects($this->any())
393
+            ->method('getId')
394
+            ->willReturn('prov1');
395
+        $this->twoFactorManager->expects($this->once())
396
+            ->method('getLoginSetupProviders')
397
+            ->with($user)
398
+            ->willReturn([
399
+                $provider,
400
+            ]);
401
+        $loginSetup = $this->createMock(ILoginSetupProvider::class);
402
+        $provider->expects($this->any())
403
+            ->method('getLoginSetup')
404
+            ->with($user)
405
+            ->willReturn($loginSetup);
406
+        $tmpl = $this->createMock(ITemplate::class);
407
+        $loginSetup->expects($this->once())
408
+            ->method('getBody')
409
+            ->willReturn($tmpl);
410
+        $tmpl->expects($this->once())
411
+            ->method('fetchPage')
412
+            ->willReturn('tmpl');
413
+        $expected = new StandaloneTemplateResponse(
414
+            'core',
415
+            'twofactorsetupchallenge',
416
+            [
417
+                'provider' => $provider,
418
+                'logout_url' => 'logoutAttribute',
419
+                'template' => 'tmpl',
420
+                'redirect_url' => null,
421
+            ],
422
+            'guest'
423
+        );
424
+
425
+        $response = $this->controller->setupProvider('prov1');
426
+
427
+        $this->assertEquals($expected, $response);
428
+    }
429
+
430
+    public function testConfirmProviderSetup(): void {
431
+        $this->urlGenerator->expects($this->once())
432
+            ->method('linkToRoute')
433
+            ->with(
434
+                'core.TwoFactorChallenge.showChallenge',
435
+                [
436
+                    'challengeProviderId' => 'totp',
437
+                    'redirect_url' => null,
438
+                ])
439
+            ->willReturn('2fa/select/page');
440
+        $expected = new RedirectResponse('2fa/select/page');
441
+
442
+        $response = $this->controller->confirmProviderSetup('totp');
443
+
444
+        $this->assertEquals($expected, $response);
445
+    }
446 446
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -308,7 +308,7 @@
 block discarded – undo
308 308
 		];
309 309
 		$this->session->expects($this->exactly(2))
310 310
 			->method('set')
311
-			->willReturnCallback(function () use (&$calls) {
311
+			->willReturnCallback(function() use (&$calls) {
312 312
 				$expected = array_shift($calls);
313 313
 				$this->assertEquals($expected, func_get_args());
314 314
 			});
Please login to merge, or discard this patch.
tests/Core/Controller/ClientFlowLoginControllerTest.php 2 patches
Indentation   +643 added lines, -643 removed lines patch added patch discarded remove patch
@@ -36,647 +36,647 @@
 block discarded – undo
36 36
 use Test\TestCase;
37 37
 
38 38
 class ClientFlowLoginControllerTest extends TestCase {
39
-	private IRequest&MockObject $request;
40
-	private IUserSession&MockObject $userSession;
41
-	private IL10N&MockObject $l10n;
42
-	private Defaults&MockObject $defaults;
43
-	private ISession&MockObject $session;
44
-	private IProvider&MockObject $tokenProvider;
45
-	private ISecureRandom&MockObject $random;
46
-	private IURLGenerator&MockObject $urlGenerator;
47
-	private ClientMapper&MockObject $clientMapper;
48
-	private AccessTokenMapper&MockObject $accessTokenMapper;
49
-	private ICrypto&MockObject $crypto;
50
-	private IEventDispatcher&MockObject $eventDispatcher;
51
-	private ITimeFactory&MockObject $timeFactory;
52
-	private IConfig&MockObject $config;
53
-
54
-	private ClientFlowLoginController $clientFlowLoginController;
55
-
56
-	protected function setUp(): void {
57
-		parent::setUp();
58
-
59
-		$this->request = $this->createMock(IRequest::class);
60
-		$this->userSession = $this->createMock(IUserSession::class);
61
-		$this->l10n = $this->createMock(IL10N::class);
62
-		$this->l10n
63
-			->expects($this->any())
64
-			->method('t')
65
-			->willReturnCallback(function ($text, $parameters = []) {
66
-				return vsprintf($text, $parameters);
67
-			});
68
-		$this->defaults = $this->createMock(Defaults::class);
69
-		$this->session = $this->createMock(ISession::class);
70
-		$this->tokenProvider = $this->createMock(IProvider::class);
71
-		$this->random = $this->createMock(ISecureRandom::class);
72
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
73
-		$this->clientMapper = $this->createMock(ClientMapper::class);
74
-		$this->accessTokenMapper = $this->createMock(AccessTokenMapper::class);
75
-		$this->crypto = $this->createMock(ICrypto::class);
76
-		$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
77
-		$this->timeFactory = $this->createMock(ITimeFactory::class);
78
-		$this->config = $this->createMock(IConfig::class);
79
-
80
-		$this->clientFlowLoginController = new ClientFlowLoginController(
81
-			'core',
82
-			$this->request,
83
-			$this->userSession,
84
-			$this->l10n,
85
-			$this->defaults,
86
-			$this->session,
87
-			$this->tokenProvider,
88
-			$this->random,
89
-			$this->urlGenerator,
90
-			$this->clientMapper,
91
-			$this->accessTokenMapper,
92
-			$this->crypto,
93
-			$this->eventDispatcher,
94
-			$this->timeFactory,
95
-			$this->config,
96
-		);
97
-	}
98
-
99
-	public function testShowAuthPickerPageNoClientOrOauthRequest(): void {
100
-		$expected = new StandaloneTemplateResponse(
101
-			'core',
102
-			'error',
103
-			[
104
-				'errors' =>
105
-					[
106
-						[
107
-							'error' => 'Access Forbidden',
108
-							'hint' => 'Invalid request',
109
-						],
110
-					],
111
-			],
112
-			'guest'
113
-		);
114
-
115
-		$this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage());
116
-	}
117
-
118
-	public function testShowAuthPickerPageWithOcsHeader(): void {
119
-		$this->request
120
-			->method('getHeader')
121
-			->willReturnMap([
122
-				['USER_AGENT', 'Mac OS X Sync Client'],
123
-				['OCS-APIREQUEST', 'true'],
124
-			]);
125
-		$this->random
126
-			->expects($this->once())
127
-			->method('generate')
128
-			->with(
129
-				64,
130
-				ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
131
-			)
132
-			->willReturn('StateToken');
133
-		$this->session
134
-			->expects($this->once())
135
-			->method('set')
136
-			->with('client.flow.state.token', 'StateToken');
137
-		$this->session
138
-			->expects($this->once())
139
-			->method('get')
140
-			->with('oauth.state')
141
-			->willReturn('OauthStateToken');
142
-		$this->defaults
143
-			->expects($this->once())
144
-			->method('getName')
145
-			->willReturn('ExampleCloud');
146
-		$this->request
147
-			->expects($this->once())
148
-			->method('getServerHost')
149
-			->willReturn('example.com');
150
-		$this->request
151
-			->method('getServerProtocol')
152
-			->willReturn('https');
153
-
154
-		$expected = new StandaloneTemplateResponse(
155
-			'core',
156
-			'loginflow/authpicker',
157
-			[
158
-				'client' => 'Mac OS X Sync Client',
159
-				'clientIdentifier' => '',
160
-				'instanceName' => 'ExampleCloud',
161
-				'urlGenerator' => $this->urlGenerator,
162
-				'stateToken' => 'StateToken',
163
-				'serverHost' => 'https://example.com',
164
-				'oauthState' => 'OauthStateToken',
165
-				'user' => '',
166
-				'direct' => 0,
167
-				'providedRedirectUri' => '',
168
-			],
169
-			'guest'
170
-		);
171
-		$csp = new Http\ContentSecurityPolicy();
172
-		$csp->addAllowedFormActionDomain('nc://*');
173
-		$expected->setContentSecurityPolicy($csp);
174
-		$this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage());
175
-	}
176
-
177
-	public function testShowAuthPickerPageWithOauth(): void {
178
-		$this->request
179
-			->method('getHeader')
180
-			->willReturnMap([
181
-				['USER_AGENT', 'Mac OS X Sync Client'],
182
-				['OCS-APIREQUEST', 'false'],
183
-			]);
184
-		$client = new Client();
185
-		$client->setName('My external service');
186
-		$client->setRedirectUri('https://example.com/redirect.php');
187
-		$this->clientMapper
188
-			->expects($this->once())
189
-			->method('getByIdentifier')
190
-			->with('MyClientIdentifier')
191
-			->willReturn($client);
192
-		$this->random
193
-			->expects($this->once())
194
-			->method('generate')
195
-			->with(
196
-				64,
197
-				ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
198
-			)
199
-			->willReturn('StateToken');
200
-		$this->session
201
-			->expects($this->once())
202
-			->method('set')
203
-			->with('client.flow.state.token', 'StateToken');
204
-		$this->session
205
-			->expects($this->once())
206
-			->method('get')
207
-			->with('oauth.state')
208
-			->willReturn('OauthStateToken');
209
-		$this->defaults
210
-			->expects($this->once())
211
-			->method('getName')
212
-			->willReturn('ExampleCloud');
213
-		$this->request
214
-			->expects($this->once())
215
-			->method('getServerHost')
216
-			->willReturn('example.com');
217
-		$this->request
218
-			->method('getServerProtocol')
219
-			->willReturn('https');
220
-
221
-		$expected = new StandaloneTemplateResponse(
222
-			'core',
223
-			'loginflow/authpicker',
224
-			[
225
-				'client' => 'My external service',
226
-				'clientIdentifier' => 'MyClientIdentifier',
227
-				'instanceName' => 'ExampleCloud',
228
-				'urlGenerator' => $this->urlGenerator,
229
-				'stateToken' => 'StateToken',
230
-				'serverHost' => 'https://example.com',
231
-				'oauthState' => 'OauthStateToken',
232
-				'user' => '',
233
-				'direct' => 0,
234
-				'providedRedirectUri' => '',
235
-			],
236
-			'guest'
237
-		);
238
-		$csp = new Http\ContentSecurityPolicy();
239
-		$csp->addAllowedFormActionDomain('https://example.com/redirect.php');
240
-		$expected->setContentSecurityPolicy($csp);
241
-		$this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage('MyClientIdentifier'));
242
-	}
243
-
244
-	public function testGenerateAppPasswordWithInvalidToken(): void {
245
-		$this->session
246
-			->expects($this->once())
247
-			->method('get')
248
-			->with('client.flow.state.token')
249
-			->willReturn('OtherToken');
250
-		$this->session
251
-			->expects($this->once())
252
-			->method('remove')
253
-			->with('client.flow.state.token');
254
-
255
-		$expected = new StandaloneTemplateResponse(
256
-			'core',
257
-			'403',
258
-			[
259
-				'message' => 'State token does not match',
260
-			],
261
-			'guest'
262
-		);
263
-		$expected->setStatus(Http::STATUS_FORBIDDEN);
264
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
265
-	}
266
-
267
-	public function testGenerateAppPasswordWithSessionNotAvailableException(): void {
268
-		$this->session
269
-			->expects($this->once())
270
-			->method('get')
271
-			->with('client.flow.state.token')
272
-			->willReturn('MyStateToken');
273
-		$this->session
274
-			->expects($this->once())
275
-			->method('remove')
276
-			->with('client.flow.state.token');
277
-		$this->session
278
-			->expects($this->once())
279
-			->method('getId')
280
-			->willThrowException(new SessionNotAvailableException());
281
-
282
-		$expected = new Http\Response();
283
-		$expected->setStatus(Http::STATUS_FORBIDDEN);
284
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
285
-	}
286
-
287
-	public function testGenerateAppPasswordWithInvalidTokenException(): void {
288
-		$this->session
289
-			->expects($this->once())
290
-			->method('get')
291
-			->with('client.flow.state.token')
292
-			->willReturn('MyStateToken');
293
-		$this->session
294
-			->expects($this->once())
295
-			->method('remove')
296
-			->with('client.flow.state.token');
297
-		$this->session
298
-			->expects($this->once())
299
-			->method('getId')
300
-			->willReturn('SessionId');
301
-		$this->tokenProvider
302
-			->expects($this->once())
303
-			->method('getToken')
304
-			->with('SessionId')
305
-			->willThrowException(new InvalidTokenException());
306
-
307
-		$expected = new Http\Response();
308
-		$expected->setStatus(Http::STATUS_FORBIDDEN);
309
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
310
-	}
311
-
312
-	public function testGeneratePasswordWithPassword(): void {
313
-		$this->session
314
-			->expects($this->once())
315
-			->method('get')
316
-			->with('client.flow.state.token')
317
-			->willReturn('MyStateToken');
318
-		$this->session
319
-			->expects($this->once())
320
-			->method('remove')
321
-			->with('client.flow.state.token');
322
-		$this->session
323
-			->expects($this->once())
324
-			->method('getId')
325
-			->willReturn('SessionId');
326
-		$myToken = $this->createMock(IToken::class);
327
-		$myToken
328
-			->expects($this->once())
329
-			->method('getLoginName')
330
-			->willReturn('MyLoginName');
331
-		$this->tokenProvider
332
-			->expects($this->once())
333
-			->method('getToken')
334
-			->with('SessionId')
335
-			->willReturn($myToken);
336
-		$this->tokenProvider
337
-			->expects($this->once())
338
-			->method('getPassword')
339
-			->with($myToken, 'SessionId')
340
-			->willReturn('MyPassword');
341
-		$this->random
342
-			->expects($this->once())
343
-			->method('generate')
344
-			->with(72)
345
-			->willReturn('MyGeneratedToken');
346
-		$user = $this->createMock(IUser::class);
347
-		$user
348
-			->expects($this->once())
349
-			->method('getUID')
350
-			->willReturn('MyUid');
351
-		$this->userSession
352
-			->expects($this->once())
353
-			->method('getUser')
354
-			->willReturn($user);
355
-		$this->tokenProvider
356
-			->expects($this->once())
357
-			->method('generateToken')
358
-			->with(
359
-				'MyGeneratedToken',
360
-				'MyUid',
361
-				'MyLoginName',
362
-				'MyPassword',
363
-				'unknown',
364
-				IToken::PERMANENT_TOKEN,
365
-				IToken::DO_NOT_REMEMBER
366
-			);
367
-		$this->request
368
-			->expects($this->once())
369
-			->method('getServerProtocol')
370
-			->willReturn('http');
371
-		$this->request
372
-			->expects($this->once())
373
-			->method('getServerHost')
374
-			->willReturn('example.com');
375
-		$this->request
376
-			->expects($this->any())
377
-			->method('getHeader')
378
-			->willReturn('');
379
-
380
-		$this->eventDispatcher->expects($this->once())
381
-			->method('dispatchTyped');
382
-
383
-		$expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken');
384
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
385
-	}
386
-
387
-	/**
388
-	 * @param string $redirectUri
389
-	 * @param string $redirectUrl
390
-	 *
391
-	 * @testWith
392
-	 * ["https://example.com/redirect.php", "https://example.com/redirect.php?state=MyOauthState&code=MyAccessCode"]
393
-	 * ["https://example.com/redirect.php?hello=world", "https://example.com/redirect.php?hello=world&state=MyOauthState&code=MyAccessCode"]
394
-	 *
395
-	 */
396
-	public function testGeneratePasswordWithPasswordForOauthClient($redirectUri, $redirectUrl): void {
397
-		$this->session
398
-			->method('get')
399
-			->willReturnMap([
400
-				['client.flow.state.token', 'MyStateToken'],
401
-				['oauth.state', 'MyOauthState'],
402
-			]);
403
-		$calls = [
404
-			'client.flow.state.token',
405
-			'oauth.state',
406
-		];
407
-		$this->session
408
-			->method('remove')
409
-			->willReturnCallback(function ($key) use (&$calls) {
410
-				$expected = array_shift($calls);
411
-				$this->assertEquals($expected, $key);
412
-			});
413
-		$this->session
414
-			->expects($this->once())
415
-			->method('getId')
416
-			->willReturn('SessionId');
417
-		$myToken = $this->createMock(IToken::class);
418
-		$myToken
419
-			->expects($this->once())
420
-			->method('getLoginName')
421
-			->willReturn('MyLoginName');
422
-		$this->tokenProvider
423
-			->expects($this->once())
424
-			->method('getToken')
425
-			->with('SessionId')
426
-			->willReturn($myToken);
427
-		$this->tokenProvider
428
-			->expects($this->once())
429
-			->method('getPassword')
430
-			->with($myToken, 'SessionId')
431
-			->willReturn('MyPassword');
432
-		$this->random
433
-			->method('generate')
434
-			->willReturnMap([
435
-				[72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'],
436
-				[128, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyAccessCode'],
437
-			]);
438
-		$user = $this->createMock(IUser::class);
439
-		$user
440
-			->expects($this->once())
441
-			->method('getUID')
442
-			->willReturn('MyUid');
443
-		$this->userSession
444
-			->expects($this->once())
445
-			->method('getUser')
446
-			->willReturn($user);
447
-		$token = $this->createMock(IToken::class);
448
-		$this->tokenProvider
449
-			->expects($this->once())
450
-			->method('generateToken')
451
-			->with(
452
-				'MyGeneratedToken',
453
-				'MyUid',
454
-				'MyLoginName',
455
-				'MyPassword',
456
-				'My OAuth client',
457
-				IToken::PERMANENT_TOKEN,
458
-				IToken::DO_NOT_REMEMBER
459
-			)
460
-			->willReturn($token);
461
-		$client = new Client();
462
-		$client->setName('My OAuth client');
463
-		$client->setRedirectUri($redirectUri);
464
-		$this->clientMapper
465
-			->expects($this->once())
466
-			->method('getByIdentifier')
467
-			->with('MyClientIdentifier')
468
-			->willReturn($client);
469
-
470
-		$this->eventDispatcher->expects($this->once())
471
-			->method('dispatchTyped');
472
-
473
-		$expected = new Http\RedirectResponse($redirectUrl);
474
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken', 'MyClientIdentifier'));
475
-	}
476
-
477
-	public function testGeneratePasswordWithoutPassword(): void {
478
-		$this->session
479
-			->expects($this->once())
480
-			->method('get')
481
-			->with('client.flow.state.token')
482
-			->willReturn('MyStateToken');
483
-		$this->session
484
-			->expects($this->once())
485
-			->method('remove')
486
-			->with('client.flow.state.token');
487
-		$this->session
488
-			->expects($this->once())
489
-			->method('getId')
490
-			->willReturn('SessionId');
491
-		$myToken = $this->createMock(IToken::class);
492
-		$myToken
493
-			->expects($this->once())
494
-			->method('getLoginName')
495
-			->willReturn('MyLoginName');
496
-		$this->tokenProvider
497
-			->expects($this->once())
498
-			->method('getToken')
499
-			->with('SessionId')
500
-			->willReturn($myToken);
501
-		$this->tokenProvider
502
-			->expects($this->once())
503
-			->method('getPassword')
504
-			->with($myToken, 'SessionId')
505
-			->willThrowException(new PasswordlessTokenException());
506
-		$this->random
507
-			->expects($this->once())
508
-			->method('generate')
509
-			->with(72)
510
-			->willReturn('MyGeneratedToken');
511
-		$user = $this->createMock(IUser::class);
512
-		$user
513
-			->expects($this->once())
514
-			->method('getUID')
515
-			->willReturn('MyUid');
516
-		$this->userSession
517
-			->expects($this->once())
518
-			->method('getUser')
519
-			->willReturn($user);
520
-		$this->tokenProvider
521
-			->expects($this->once())
522
-			->method('generateToken')
523
-			->with(
524
-				'MyGeneratedToken',
525
-				'MyUid',
526
-				'MyLoginName',
527
-				null,
528
-				'unknown',
529
-				IToken::PERMANENT_TOKEN,
530
-				IToken::DO_NOT_REMEMBER
531
-			);
532
-		$this->request
533
-			->expects($this->once())
534
-			->method('getServerProtocol')
535
-			->willReturn('http');
536
-		$this->request
537
-			->expects($this->once())
538
-			->method('getServerHost')
539
-			->willReturn('example.com');
540
-		$this->request
541
-			->expects($this->any())
542
-			->method('getHeader')
543
-			->willReturn('');
544
-
545
-		$this->eventDispatcher->expects($this->once())
546
-			->method('dispatchTyped');
547
-
548
-		$expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken');
549
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
550
-	}
551
-
552
-	public static function dataGeneratePasswordWithHttpsProxy(): array {
553
-		return [
554
-			[
555
-				[
556
-					['X-Forwarded-Proto', 'http'],
557
-					['X-Forwarded-Ssl', 'off'],
558
-					['USER_AGENT', ''],
559
-				],
560
-				'http',
561
-				'http',
562
-			],
563
-			[
564
-				[
565
-					['X-Forwarded-Proto', 'http'],
566
-					['X-Forwarded-Ssl', 'off'],
567
-					['USER_AGENT', ''],
568
-				],
569
-				'https',
570
-				'https',
571
-			],
572
-			[
573
-				[
574
-					['X-Forwarded-Proto', 'https'],
575
-					['X-Forwarded-Ssl', 'off'],
576
-					['USER_AGENT', ''],
577
-				],
578
-				'http',
579
-				'https',
580
-			],
581
-			[
582
-				[
583
-					['X-Forwarded-Proto', 'https'],
584
-					['X-Forwarded-Ssl', 'on'],
585
-					['USER_AGENT', ''],
586
-				],
587
-				'http',
588
-				'https',
589
-			],
590
-			[
591
-				[
592
-					['X-Forwarded-Proto', 'http'],
593
-					['X-Forwarded-Ssl', 'on'],
594
-					['USER_AGENT', ''],
595
-				],
596
-				'http',
597
-				'https',
598
-			],
599
-		];
600
-	}
601
-
602
-	/**
603
-	 * @dataProvider dataGeneratePasswordWithHttpsProxy
604
-	 * @param array $headers
605
-	 * @param string $protocol
606
-	 * @param string $expected
607
-	 */
608
-	public function testGeneratePasswordWithHttpsProxy(array $headers, $protocol, $expected): void {
609
-		$this->session
610
-			->expects($this->once())
611
-			->method('get')
612
-			->with('client.flow.state.token')
613
-			->willReturn('MyStateToken');
614
-		$this->session
615
-			->expects($this->once())
616
-			->method('remove')
617
-			->with('client.flow.state.token');
618
-		$this->session
619
-			->expects($this->once())
620
-			->method('getId')
621
-			->willReturn('SessionId');
622
-		$myToken = $this->createMock(IToken::class);
623
-		$myToken
624
-			->expects($this->once())
625
-			->method('getLoginName')
626
-			->willReturn('MyLoginName');
627
-		$this->tokenProvider
628
-			->expects($this->once())
629
-			->method('getToken')
630
-			->with('SessionId')
631
-			->willReturn($myToken);
632
-		$this->tokenProvider
633
-			->expects($this->once())
634
-			->method('getPassword')
635
-			->with($myToken, 'SessionId')
636
-			->willReturn('MyPassword');
637
-		$this->random
638
-			->expects($this->once())
639
-			->method('generate')
640
-			->with(72)
641
-			->willReturn('MyGeneratedToken');
642
-		$user = $this->createMock(IUser::class);
643
-		$user
644
-			->expects($this->once())
645
-			->method('getUID')
646
-			->willReturn('MyUid');
647
-		$this->userSession
648
-			->expects($this->once())
649
-			->method('getUser')
650
-			->willReturn($user);
651
-		$this->tokenProvider
652
-			->expects($this->once())
653
-			->method('generateToken')
654
-			->with(
655
-				'MyGeneratedToken',
656
-				'MyUid',
657
-				'MyLoginName',
658
-				'MyPassword',
659
-				'unknown',
660
-				IToken::PERMANENT_TOKEN,
661
-				IToken::DO_NOT_REMEMBER
662
-			);
663
-		$this->request
664
-			->expects($this->once())
665
-			->method('getServerProtocol')
666
-			->willReturn($protocol);
667
-		$this->request
668
-			->expects($this->once())
669
-			->method('getServerHost')
670
-			->willReturn('example.com');
671
-		$this->request
672
-			->expects($this->atLeastOnce())
673
-			->method('getHeader')
674
-			->willReturnMap($headers);
675
-
676
-		$this->eventDispatcher->expects($this->once())
677
-			->method('dispatchTyped');
678
-
679
-		$expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken');
680
-		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
681
-	}
39
+    private IRequest&MockObject $request;
40
+    private IUserSession&MockObject $userSession;
41
+    private IL10N&MockObject $l10n;
42
+    private Defaults&MockObject $defaults;
43
+    private ISession&MockObject $session;
44
+    private IProvider&MockObject $tokenProvider;
45
+    private ISecureRandom&MockObject $random;
46
+    private IURLGenerator&MockObject $urlGenerator;
47
+    private ClientMapper&MockObject $clientMapper;
48
+    private AccessTokenMapper&MockObject $accessTokenMapper;
49
+    private ICrypto&MockObject $crypto;
50
+    private IEventDispatcher&MockObject $eventDispatcher;
51
+    private ITimeFactory&MockObject $timeFactory;
52
+    private IConfig&MockObject $config;
53
+
54
+    private ClientFlowLoginController $clientFlowLoginController;
55
+
56
+    protected function setUp(): void {
57
+        parent::setUp();
58
+
59
+        $this->request = $this->createMock(IRequest::class);
60
+        $this->userSession = $this->createMock(IUserSession::class);
61
+        $this->l10n = $this->createMock(IL10N::class);
62
+        $this->l10n
63
+            ->expects($this->any())
64
+            ->method('t')
65
+            ->willReturnCallback(function ($text, $parameters = []) {
66
+                return vsprintf($text, $parameters);
67
+            });
68
+        $this->defaults = $this->createMock(Defaults::class);
69
+        $this->session = $this->createMock(ISession::class);
70
+        $this->tokenProvider = $this->createMock(IProvider::class);
71
+        $this->random = $this->createMock(ISecureRandom::class);
72
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
73
+        $this->clientMapper = $this->createMock(ClientMapper::class);
74
+        $this->accessTokenMapper = $this->createMock(AccessTokenMapper::class);
75
+        $this->crypto = $this->createMock(ICrypto::class);
76
+        $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
77
+        $this->timeFactory = $this->createMock(ITimeFactory::class);
78
+        $this->config = $this->createMock(IConfig::class);
79
+
80
+        $this->clientFlowLoginController = new ClientFlowLoginController(
81
+            'core',
82
+            $this->request,
83
+            $this->userSession,
84
+            $this->l10n,
85
+            $this->defaults,
86
+            $this->session,
87
+            $this->tokenProvider,
88
+            $this->random,
89
+            $this->urlGenerator,
90
+            $this->clientMapper,
91
+            $this->accessTokenMapper,
92
+            $this->crypto,
93
+            $this->eventDispatcher,
94
+            $this->timeFactory,
95
+            $this->config,
96
+        );
97
+    }
98
+
99
+    public function testShowAuthPickerPageNoClientOrOauthRequest(): void {
100
+        $expected = new StandaloneTemplateResponse(
101
+            'core',
102
+            'error',
103
+            [
104
+                'errors' =>
105
+                    [
106
+                        [
107
+                            'error' => 'Access Forbidden',
108
+                            'hint' => 'Invalid request',
109
+                        ],
110
+                    ],
111
+            ],
112
+            'guest'
113
+        );
114
+
115
+        $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage());
116
+    }
117
+
118
+    public function testShowAuthPickerPageWithOcsHeader(): void {
119
+        $this->request
120
+            ->method('getHeader')
121
+            ->willReturnMap([
122
+                ['USER_AGENT', 'Mac OS X Sync Client'],
123
+                ['OCS-APIREQUEST', 'true'],
124
+            ]);
125
+        $this->random
126
+            ->expects($this->once())
127
+            ->method('generate')
128
+            ->with(
129
+                64,
130
+                ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
131
+            )
132
+            ->willReturn('StateToken');
133
+        $this->session
134
+            ->expects($this->once())
135
+            ->method('set')
136
+            ->with('client.flow.state.token', 'StateToken');
137
+        $this->session
138
+            ->expects($this->once())
139
+            ->method('get')
140
+            ->with('oauth.state')
141
+            ->willReturn('OauthStateToken');
142
+        $this->defaults
143
+            ->expects($this->once())
144
+            ->method('getName')
145
+            ->willReturn('ExampleCloud');
146
+        $this->request
147
+            ->expects($this->once())
148
+            ->method('getServerHost')
149
+            ->willReturn('example.com');
150
+        $this->request
151
+            ->method('getServerProtocol')
152
+            ->willReturn('https');
153
+
154
+        $expected = new StandaloneTemplateResponse(
155
+            'core',
156
+            'loginflow/authpicker',
157
+            [
158
+                'client' => 'Mac OS X Sync Client',
159
+                'clientIdentifier' => '',
160
+                'instanceName' => 'ExampleCloud',
161
+                'urlGenerator' => $this->urlGenerator,
162
+                'stateToken' => 'StateToken',
163
+                'serverHost' => 'https://example.com',
164
+                'oauthState' => 'OauthStateToken',
165
+                'user' => '',
166
+                'direct' => 0,
167
+                'providedRedirectUri' => '',
168
+            ],
169
+            'guest'
170
+        );
171
+        $csp = new Http\ContentSecurityPolicy();
172
+        $csp->addAllowedFormActionDomain('nc://*');
173
+        $expected->setContentSecurityPolicy($csp);
174
+        $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage());
175
+    }
176
+
177
+    public function testShowAuthPickerPageWithOauth(): void {
178
+        $this->request
179
+            ->method('getHeader')
180
+            ->willReturnMap([
181
+                ['USER_AGENT', 'Mac OS X Sync Client'],
182
+                ['OCS-APIREQUEST', 'false'],
183
+            ]);
184
+        $client = new Client();
185
+        $client->setName('My external service');
186
+        $client->setRedirectUri('https://example.com/redirect.php');
187
+        $this->clientMapper
188
+            ->expects($this->once())
189
+            ->method('getByIdentifier')
190
+            ->with('MyClientIdentifier')
191
+            ->willReturn($client);
192
+        $this->random
193
+            ->expects($this->once())
194
+            ->method('generate')
195
+            ->with(
196
+                64,
197
+                ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
198
+            )
199
+            ->willReturn('StateToken');
200
+        $this->session
201
+            ->expects($this->once())
202
+            ->method('set')
203
+            ->with('client.flow.state.token', 'StateToken');
204
+        $this->session
205
+            ->expects($this->once())
206
+            ->method('get')
207
+            ->with('oauth.state')
208
+            ->willReturn('OauthStateToken');
209
+        $this->defaults
210
+            ->expects($this->once())
211
+            ->method('getName')
212
+            ->willReturn('ExampleCloud');
213
+        $this->request
214
+            ->expects($this->once())
215
+            ->method('getServerHost')
216
+            ->willReturn('example.com');
217
+        $this->request
218
+            ->method('getServerProtocol')
219
+            ->willReturn('https');
220
+
221
+        $expected = new StandaloneTemplateResponse(
222
+            'core',
223
+            'loginflow/authpicker',
224
+            [
225
+                'client' => 'My external service',
226
+                'clientIdentifier' => 'MyClientIdentifier',
227
+                'instanceName' => 'ExampleCloud',
228
+                'urlGenerator' => $this->urlGenerator,
229
+                'stateToken' => 'StateToken',
230
+                'serverHost' => 'https://example.com',
231
+                'oauthState' => 'OauthStateToken',
232
+                'user' => '',
233
+                'direct' => 0,
234
+                'providedRedirectUri' => '',
235
+            ],
236
+            'guest'
237
+        );
238
+        $csp = new Http\ContentSecurityPolicy();
239
+        $csp->addAllowedFormActionDomain('https://example.com/redirect.php');
240
+        $expected->setContentSecurityPolicy($csp);
241
+        $this->assertEquals($expected, $this->clientFlowLoginController->showAuthPickerPage('MyClientIdentifier'));
242
+    }
243
+
244
+    public function testGenerateAppPasswordWithInvalidToken(): void {
245
+        $this->session
246
+            ->expects($this->once())
247
+            ->method('get')
248
+            ->with('client.flow.state.token')
249
+            ->willReturn('OtherToken');
250
+        $this->session
251
+            ->expects($this->once())
252
+            ->method('remove')
253
+            ->with('client.flow.state.token');
254
+
255
+        $expected = new StandaloneTemplateResponse(
256
+            'core',
257
+            '403',
258
+            [
259
+                'message' => 'State token does not match',
260
+            ],
261
+            'guest'
262
+        );
263
+        $expected->setStatus(Http::STATUS_FORBIDDEN);
264
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
265
+    }
266
+
267
+    public function testGenerateAppPasswordWithSessionNotAvailableException(): void {
268
+        $this->session
269
+            ->expects($this->once())
270
+            ->method('get')
271
+            ->with('client.flow.state.token')
272
+            ->willReturn('MyStateToken');
273
+        $this->session
274
+            ->expects($this->once())
275
+            ->method('remove')
276
+            ->with('client.flow.state.token');
277
+        $this->session
278
+            ->expects($this->once())
279
+            ->method('getId')
280
+            ->willThrowException(new SessionNotAvailableException());
281
+
282
+        $expected = new Http\Response();
283
+        $expected->setStatus(Http::STATUS_FORBIDDEN);
284
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
285
+    }
286
+
287
+    public function testGenerateAppPasswordWithInvalidTokenException(): void {
288
+        $this->session
289
+            ->expects($this->once())
290
+            ->method('get')
291
+            ->with('client.flow.state.token')
292
+            ->willReturn('MyStateToken');
293
+        $this->session
294
+            ->expects($this->once())
295
+            ->method('remove')
296
+            ->with('client.flow.state.token');
297
+        $this->session
298
+            ->expects($this->once())
299
+            ->method('getId')
300
+            ->willReturn('SessionId');
301
+        $this->tokenProvider
302
+            ->expects($this->once())
303
+            ->method('getToken')
304
+            ->with('SessionId')
305
+            ->willThrowException(new InvalidTokenException());
306
+
307
+        $expected = new Http\Response();
308
+        $expected->setStatus(Http::STATUS_FORBIDDEN);
309
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
310
+    }
311
+
312
+    public function testGeneratePasswordWithPassword(): void {
313
+        $this->session
314
+            ->expects($this->once())
315
+            ->method('get')
316
+            ->with('client.flow.state.token')
317
+            ->willReturn('MyStateToken');
318
+        $this->session
319
+            ->expects($this->once())
320
+            ->method('remove')
321
+            ->with('client.flow.state.token');
322
+        $this->session
323
+            ->expects($this->once())
324
+            ->method('getId')
325
+            ->willReturn('SessionId');
326
+        $myToken = $this->createMock(IToken::class);
327
+        $myToken
328
+            ->expects($this->once())
329
+            ->method('getLoginName')
330
+            ->willReturn('MyLoginName');
331
+        $this->tokenProvider
332
+            ->expects($this->once())
333
+            ->method('getToken')
334
+            ->with('SessionId')
335
+            ->willReturn($myToken);
336
+        $this->tokenProvider
337
+            ->expects($this->once())
338
+            ->method('getPassword')
339
+            ->with($myToken, 'SessionId')
340
+            ->willReturn('MyPassword');
341
+        $this->random
342
+            ->expects($this->once())
343
+            ->method('generate')
344
+            ->with(72)
345
+            ->willReturn('MyGeneratedToken');
346
+        $user = $this->createMock(IUser::class);
347
+        $user
348
+            ->expects($this->once())
349
+            ->method('getUID')
350
+            ->willReturn('MyUid');
351
+        $this->userSession
352
+            ->expects($this->once())
353
+            ->method('getUser')
354
+            ->willReturn($user);
355
+        $this->tokenProvider
356
+            ->expects($this->once())
357
+            ->method('generateToken')
358
+            ->with(
359
+                'MyGeneratedToken',
360
+                'MyUid',
361
+                'MyLoginName',
362
+                'MyPassword',
363
+                'unknown',
364
+                IToken::PERMANENT_TOKEN,
365
+                IToken::DO_NOT_REMEMBER
366
+            );
367
+        $this->request
368
+            ->expects($this->once())
369
+            ->method('getServerProtocol')
370
+            ->willReturn('http');
371
+        $this->request
372
+            ->expects($this->once())
373
+            ->method('getServerHost')
374
+            ->willReturn('example.com');
375
+        $this->request
376
+            ->expects($this->any())
377
+            ->method('getHeader')
378
+            ->willReturn('');
379
+
380
+        $this->eventDispatcher->expects($this->once())
381
+            ->method('dispatchTyped');
382
+
383
+        $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken');
384
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
385
+    }
386
+
387
+    /**
388
+     * @param string $redirectUri
389
+     * @param string $redirectUrl
390
+     *
391
+     * @testWith
392
+     * ["https://example.com/redirect.php", "https://example.com/redirect.php?state=MyOauthState&code=MyAccessCode"]
393
+     * ["https://example.com/redirect.php?hello=world", "https://example.com/redirect.php?hello=world&state=MyOauthState&code=MyAccessCode"]
394
+     *
395
+     */
396
+    public function testGeneratePasswordWithPasswordForOauthClient($redirectUri, $redirectUrl): void {
397
+        $this->session
398
+            ->method('get')
399
+            ->willReturnMap([
400
+                ['client.flow.state.token', 'MyStateToken'],
401
+                ['oauth.state', 'MyOauthState'],
402
+            ]);
403
+        $calls = [
404
+            'client.flow.state.token',
405
+            'oauth.state',
406
+        ];
407
+        $this->session
408
+            ->method('remove')
409
+            ->willReturnCallback(function ($key) use (&$calls) {
410
+                $expected = array_shift($calls);
411
+                $this->assertEquals($expected, $key);
412
+            });
413
+        $this->session
414
+            ->expects($this->once())
415
+            ->method('getId')
416
+            ->willReturn('SessionId');
417
+        $myToken = $this->createMock(IToken::class);
418
+        $myToken
419
+            ->expects($this->once())
420
+            ->method('getLoginName')
421
+            ->willReturn('MyLoginName');
422
+        $this->tokenProvider
423
+            ->expects($this->once())
424
+            ->method('getToken')
425
+            ->with('SessionId')
426
+            ->willReturn($myToken);
427
+        $this->tokenProvider
428
+            ->expects($this->once())
429
+            ->method('getPassword')
430
+            ->with($myToken, 'SessionId')
431
+            ->willReturn('MyPassword');
432
+        $this->random
433
+            ->method('generate')
434
+            ->willReturnMap([
435
+                [72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'],
436
+                [128, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyAccessCode'],
437
+            ]);
438
+        $user = $this->createMock(IUser::class);
439
+        $user
440
+            ->expects($this->once())
441
+            ->method('getUID')
442
+            ->willReturn('MyUid');
443
+        $this->userSession
444
+            ->expects($this->once())
445
+            ->method('getUser')
446
+            ->willReturn($user);
447
+        $token = $this->createMock(IToken::class);
448
+        $this->tokenProvider
449
+            ->expects($this->once())
450
+            ->method('generateToken')
451
+            ->with(
452
+                'MyGeneratedToken',
453
+                'MyUid',
454
+                'MyLoginName',
455
+                'MyPassword',
456
+                'My OAuth client',
457
+                IToken::PERMANENT_TOKEN,
458
+                IToken::DO_NOT_REMEMBER
459
+            )
460
+            ->willReturn($token);
461
+        $client = new Client();
462
+        $client->setName('My OAuth client');
463
+        $client->setRedirectUri($redirectUri);
464
+        $this->clientMapper
465
+            ->expects($this->once())
466
+            ->method('getByIdentifier')
467
+            ->with('MyClientIdentifier')
468
+            ->willReturn($client);
469
+
470
+        $this->eventDispatcher->expects($this->once())
471
+            ->method('dispatchTyped');
472
+
473
+        $expected = new Http\RedirectResponse($redirectUrl);
474
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken', 'MyClientIdentifier'));
475
+    }
476
+
477
+    public function testGeneratePasswordWithoutPassword(): void {
478
+        $this->session
479
+            ->expects($this->once())
480
+            ->method('get')
481
+            ->with('client.flow.state.token')
482
+            ->willReturn('MyStateToken');
483
+        $this->session
484
+            ->expects($this->once())
485
+            ->method('remove')
486
+            ->with('client.flow.state.token');
487
+        $this->session
488
+            ->expects($this->once())
489
+            ->method('getId')
490
+            ->willReturn('SessionId');
491
+        $myToken = $this->createMock(IToken::class);
492
+        $myToken
493
+            ->expects($this->once())
494
+            ->method('getLoginName')
495
+            ->willReturn('MyLoginName');
496
+        $this->tokenProvider
497
+            ->expects($this->once())
498
+            ->method('getToken')
499
+            ->with('SessionId')
500
+            ->willReturn($myToken);
501
+        $this->tokenProvider
502
+            ->expects($this->once())
503
+            ->method('getPassword')
504
+            ->with($myToken, 'SessionId')
505
+            ->willThrowException(new PasswordlessTokenException());
506
+        $this->random
507
+            ->expects($this->once())
508
+            ->method('generate')
509
+            ->with(72)
510
+            ->willReturn('MyGeneratedToken');
511
+        $user = $this->createMock(IUser::class);
512
+        $user
513
+            ->expects($this->once())
514
+            ->method('getUID')
515
+            ->willReturn('MyUid');
516
+        $this->userSession
517
+            ->expects($this->once())
518
+            ->method('getUser')
519
+            ->willReturn($user);
520
+        $this->tokenProvider
521
+            ->expects($this->once())
522
+            ->method('generateToken')
523
+            ->with(
524
+                'MyGeneratedToken',
525
+                'MyUid',
526
+                'MyLoginName',
527
+                null,
528
+                'unknown',
529
+                IToken::PERMANENT_TOKEN,
530
+                IToken::DO_NOT_REMEMBER
531
+            );
532
+        $this->request
533
+            ->expects($this->once())
534
+            ->method('getServerProtocol')
535
+            ->willReturn('http');
536
+        $this->request
537
+            ->expects($this->once())
538
+            ->method('getServerHost')
539
+            ->willReturn('example.com');
540
+        $this->request
541
+            ->expects($this->any())
542
+            ->method('getHeader')
543
+            ->willReturn('');
544
+
545
+        $this->eventDispatcher->expects($this->once())
546
+            ->method('dispatchTyped');
547
+
548
+        $expected = new Http\RedirectResponse('nc://login/server:http://example.com&user:MyLoginName&password:MyGeneratedToken');
549
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
550
+    }
551
+
552
+    public static function dataGeneratePasswordWithHttpsProxy(): array {
553
+        return [
554
+            [
555
+                [
556
+                    ['X-Forwarded-Proto', 'http'],
557
+                    ['X-Forwarded-Ssl', 'off'],
558
+                    ['USER_AGENT', ''],
559
+                ],
560
+                'http',
561
+                'http',
562
+            ],
563
+            [
564
+                [
565
+                    ['X-Forwarded-Proto', 'http'],
566
+                    ['X-Forwarded-Ssl', 'off'],
567
+                    ['USER_AGENT', ''],
568
+                ],
569
+                'https',
570
+                'https',
571
+            ],
572
+            [
573
+                [
574
+                    ['X-Forwarded-Proto', 'https'],
575
+                    ['X-Forwarded-Ssl', 'off'],
576
+                    ['USER_AGENT', ''],
577
+                ],
578
+                'http',
579
+                'https',
580
+            ],
581
+            [
582
+                [
583
+                    ['X-Forwarded-Proto', 'https'],
584
+                    ['X-Forwarded-Ssl', 'on'],
585
+                    ['USER_AGENT', ''],
586
+                ],
587
+                'http',
588
+                'https',
589
+            ],
590
+            [
591
+                [
592
+                    ['X-Forwarded-Proto', 'http'],
593
+                    ['X-Forwarded-Ssl', 'on'],
594
+                    ['USER_AGENT', ''],
595
+                ],
596
+                'http',
597
+                'https',
598
+            ],
599
+        ];
600
+    }
601
+
602
+    /**
603
+     * @dataProvider dataGeneratePasswordWithHttpsProxy
604
+     * @param array $headers
605
+     * @param string $protocol
606
+     * @param string $expected
607
+     */
608
+    public function testGeneratePasswordWithHttpsProxy(array $headers, $protocol, $expected): void {
609
+        $this->session
610
+            ->expects($this->once())
611
+            ->method('get')
612
+            ->with('client.flow.state.token')
613
+            ->willReturn('MyStateToken');
614
+        $this->session
615
+            ->expects($this->once())
616
+            ->method('remove')
617
+            ->with('client.flow.state.token');
618
+        $this->session
619
+            ->expects($this->once())
620
+            ->method('getId')
621
+            ->willReturn('SessionId');
622
+        $myToken = $this->createMock(IToken::class);
623
+        $myToken
624
+            ->expects($this->once())
625
+            ->method('getLoginName')
626
+            ->willReturn('MyLoginName');
627
+        $this->tokenProvider
628
+            ->expects($this->once())
629
+            ->method('getToken')
630
+            ->with('SessionId')
631
+            ->willReturn($myToken);
632
+        $this->tokenProvider
633
+            ->expects($this->once())
634
+            ->method('getPassword')
635
+            ->with($myToken, 'SessionId')
636
+            ->willReturn('MyPassword');
637
+        $this->random
638
+            ->expects($this->once())
639
+            ->method('generate')
640
+            ->with(72)
641
+            ->willReturn('MyGeneratedToken');
642
+        $user = $this->createMock(IUser::class);
643
+        $user
644
+            ->expects($this->once())
645
+            ->method('getUID')
646
+            ->willReturn('MyUid');
647
+        $this->userSession
648
+            ->expects($this->once())
649
+            ->method('getUser')
650
+            ->willReturn($user);
651
+        $this->tokenProvider
652
+            ->expects($this->once())
653
+            ->method('generateToken')
654
+            ->with(
655
+                'MyGeneratedToken',
656
+                'MyUid',
657
+                'MyLoginName',
658
+                'MyPassword',
659
+                'unknown',
660
+                IToken::PERMANENT_TOKEN,
661
+                IToken::DO_NOT_REMEMBER
662
+            );
663
+        $this->request
664
+            ->expects($this->once())
665
+            ->method('getServerProtocol')
666
+            ->willReturn($protocol);
667
+        $this->request
668
+            ->expects($this->once())
669
+            ->method('getServerHost')
670
+            ->willReturn('example.com');
671
+        $this->request
672
+            ->expects($this->atLeastOnce())
673
+            ->method('getHeader')
674
+            ->willReturnMap($headers);
675
+
676
+        $this->eventDispatcher->expects($this->once())
677
+            ->method('dispatchTyped');
678
+
679
+        $expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken');
680
+        $this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
681
+    }
682 682
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
 		$this->l10n
63 63
 			->expects($this->any())
64 64
 			->method('t')
65
-			->willReturnCallback(function ($text, $parameters = []) {
65
+			->willReturnCallback(function($text, $parameters = []) {
66 66
 				return vsprintf($text, $parameters);
67 67
 			});
68 68
 		$this->defaults = $this->createMock(Defaults::class);
@@ -127,7 +127,7 @@  discard block
 block discarded – undo
127 127
 			->method('generate')
128 128
 			->with(
129 129
 				64,
130
-				ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
130
+				ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS
131 131
 			)
132 132
 			->willReturn('StateToken');
133 133
 		$this->session
@@ -194,7 +194,7 @@  discard block
 block discarded – undo
194 194
 			->method('generate')
195 195
 			->with(
196 196
 				64,
197
-				ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS
197
+				ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS
198 198
 			)
199 199
 			->willReturn('StateToken');
200 200
 		$this->session
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
 		];
407 407
 		$this->session
408 408
 			->method('remove')
409
-			->willReturnCallback(function ($key) use (&$calls) {
409
+			->willReturnCallback(function($key) use (&$calls) {
410 410
 				$expected = array_shift($calls);
411 411
 				$this->assertEquals($expected, $key);
412 412
 			});
@@ -432,8 +432,8 @@  discard block
 block discarded – undo
432 432
 		$this->random
433 433
 			->method('generate')
434 434
 			->willReturnMap([
435
-				[72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'],
436
-				[128, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS, 'MyAccessCode'],
435
+				[72, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS, 'MyGeneratedToken'],
436
+				[128, ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_DIGITS, 'MyAccessCode'],
437 437
 			]);
438 438
 		$user = $this->createMock(IUser::class);
439 439
 		$user
@@ -676,7 +676,7 @@  discard block
 block discarded – undo
676 676
 		$this->eventDispatcher->expects($this->once())
677 677
 			->method('dispatchTyped');
678 678
 
679
-		$expected = new Http\RedirectResponse('nc://login/server:' . $expected . '://example.com&user:MyLoginName&password:MyGeneratedToken');
679
+		$expected = new Http\RedirectResponse('nc://login/server:'.$expected.'://example.com&user:MyLoginName&password:MyGeneratedToken');
680 680
 		$this->assertEquals($expected, $this->clientFlowLoginController->generateAppPassword('MyStateToken'));
681 681
 	}
682 682
 }
Please login to merge, or discard this patch.
tests/Core/Middleware/TwoFactorMiddlewareTest.php 2 patches
Indentation   +253 added lines, -253 removed lines patch added patch discarded remove patch
@@ -32,257 +32,257 @@
 block discarded – undo
32 32
 use Test\TestCase;
33 33
 
34 34
 class TwoFactorMiddlewareTest extends TestCase {
35
-	/** @var Manager|MockObject */
36
-	private $twoFactorManager;
37
-
38
-	/** @var IUserSession|MockObject */
39
-	private $userSession;
40
-
41
-	/** @var ISession|MockObject */
42
-	private $session;
43
-
44
-	/** @var IURLGenerator|MockObject */
45
-	private $urlGenerator;
46
-
47
-	/** @var IControllerMethodReflector|MockObject */
48
-	private $reflector;
49
-
50
-	/** @var IRequest|MockObject */
51
-	private $request;
52
-
53
-	/** @var TwoFactorMiddleware */
54
-	private $middleware;
55
-
56
-	/** @var Controller */
57
-	private $controller;
58
-
59
-	protected function setUp(): void {
60
-		parent::setUp();
61
-
62
-		$this->twoFactorManager = $this->getMockBuilder(Manager::class)
63
-			->disableOriginalConstructor()
64
-			->getMock();
65
-		$this->userSession = $this->getMockBuilder(Session::class)
66
-			->disableOriginalConstructor()
67
-			->getMock();
68
-		$this->session = $this->createMock(ISession::class);
69
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
70
-		$this->reflector = $this->createMock(IControllerMethodReflector::class);
71
-		$this->request = new Request(
72
-			[
73
-				'server' => [
74
-					'REQUEST_URI' => 'test/url'
75
-				]
76
-			],
77
-			$this->createMock(IRequestId::class),
78
-			$this->createMock(IConfig::class)
79
-		);
80
-
81
-		$this->middleware = new TwoFactorMiddleware($this->twoFactorManager, $this->userSession, $this->session, $this->urlGenerator, $this->reflector, $this->request);
82
-		$this->controller = $this->createMock(Controller::class);
83
-	}
84
-
85
-	public function testBeforeControllerNotLoggedIn(): void {
86
-		$this->userSession->expects($this->once())
87
-			->method('isLoggedIn')
88
-			->willReturn(false);
89
-
90
-		$this->userSession->expects($this->never())
91
-			->method('getUser');
92
-
93
-		$this->middleware->beforeController($this->controller, 'index');
94
-	}
95
-
96
-	public function testBeforeSetupController(): void {
97
-		$user = $this->createMock(IUser::class);
98
-		$controller = $this->createMock(ALoginSetupController::class);
99
-		$this->userSession->expects($this->any())
100
-			->method('getUser')
101
-			->willReturn($user);
102
-		$this->twoFactorManager->expects($this->once())
103
-			->method('needsSecondFactor')
104
-			->willReturn(true);
105
-		$this->userSession->expects($this->never())
106
-			->method('isLoggedIn');
107
-
108
-		$this->middleware->beforeController($controller, 'create');
109
-	}
110
-
111
-	public function testBeforeControllerNoTwoFactorCheckNeeded(): void {
112
-		$user = $this->createMock(IUser::class);
113
-
114
-		$this->userSession->expects($this->once())
115
-			->method('isLoggedIn')
116
-			->willReturn(true);
117
-		$this->userSession->expects($this->once())
118
-			->method('getUser')
119
-			->willReturn($user);
120
-		$this->twoFactorManager->expects($this->once())
121
-			->method('isTwoFactorAuthenticated')
122
-			->with($user)
123
-			->willReturn(false);
124
-
125
-		$this->middleware->beforeController($this->controller, 'index');
126
-	}
127
-
128
-
129
-	public function testBeforeControllerTwoFactorAuthRequired(): void {
130
-		$this->expectException(TwoFactorAuthRequiredException::class);
131
-
132
-		$user = $this->createMock(IUser::class);
133
-
134
-		$this->userSession->expects($this->once())
135
-			->method('isLoggedIn')
136
-			->willReturn(true);
137
-		$this->userSession->expects($this->once())
138
-			->method('getUser')
139
-			->willReturn($user);
140
-		$this->twoFactorManager->expects($this->once())
141
-			->method('isTwoFactorAuthenticated')
142
-			->with($user)
143
-			->willReturn(true);
144
-		$this->twoFactorManager->expects($this->once())
145
-			->method('needsSecondFactor')
146
-			->with($user)
147
-			->willReturn(true);
148
-
149
-		$this->middleware->beforeController($this->controller, 'index');
150
-	}
151
-
152
-
153
-	public function testBeforeControllerUserAlreadyLoggedIn(): void {
154
-		$this->expectException(UserAlreadyLoggedInException::class);
155
-
156
-		$user = $this->createMock(IUser::class);
157
-
158
-		$this->reflector
159
-			->method('hasAnnotation')
160
-			->willReturn(false);
161
-		$this->userSession->expects($this->once())
162
-			->method('isLoggedIn')
163
-			->willReturn(true);
164
-		$this->userSession
165
-			->method('getUser')
166
-			->willReturn($user);
167
-		$this->twoFactorManager->expects($this->once())
168
-			->method('isTwoFactorAuthenticated')
169
-			->with($user)
170
-			->willReturn(true);
171
-		$this->twoFactorManager->expects($this->once())
172
-			->method('needsSecondFactor')
173
-			->with($user)
174
-			->willReturn(false);
175
-
176
-		$twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
177
-			->disableOriginalConstructor()
178
-			->getMock();
179
-		$this->middleware->beforeController($twoFactorChallengeController, 'index');
180
-	}
181
-
182
-	public function testAfterExceptionTwoFactorAuthRequired(): void {
183
-		$ex = new TwoFactorAuthRequiredException();
184
-
185
-		$this->urlGenerator->expects($this->once())
186
-			->method('linkToRoute')
187
-			->with('core.TwoFactorChallenge.selectChallenge')
188
-			->willReturn('test/url');
189
-		$expected = new RedirectResponse('test/url');
190
-
191
-		$this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex));
192
-	}
193
-
194
-	public function testAfterException(): void {
195
-		$ex = new UserAlreadyLoggedInException();
196
-
197
-		$this->urlGenerator->expects($this->once())
198
-			->method('linkToRoute')
199
-			->with('files.view.index')
200
-			->willReturn('redirect/url');
201
-		$expected = new RedirectResponse('redirect/url');
202
-
203
-		$this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex));
204
-	}
205
-
206
-	public function testRequires2FASetupDoneAnnotated(): void {
207
-		$user = $this->createMock(IUser::class);
208
-
209
-		$this->reflector
210
-			->method('hasAnnotation')
211
-			->willReturnCallback(function (string $annotation) {
212
-				return $annotation === 'TwoFactorSetUpDoneRequired';
213
-			});
214
-		$this->userSession->expects($this->once())
215
-			->method('isLoggedIn')
216
-			->willReturn(true);
217
-		$this->userSession
218
-			->method('getUser')
219
-			->willReturn($user);
220
-		$this->twoFactorManager->expects($this->once())
221
-			->method('isTwoFactorAuthenticated')
222
-			->with($user)
223
-			->willReturn(true);
224
-		$this->twoFactorManager->expects($this->once())
225
-			->method('needsSecondFactor')
226
-			->with($user)
227
-			->willReturn(false);
228
-
229
-		$this->expectException(UserAlreadyLoggedInException::class);
230
-
231
-		$twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
232
-			->disableOriginalConstructor()
233
-			->getMock();
234
-		$this->middleware->beforeController($twoFactorChallengeController, 'index');
235
-	}
236
-
237
-	public static function dataRequires2FASetupDone(): array {
238
-		return [
239
-			[false, false, false],
240
-			[false,  true,  true],
241
-			[true, false, true],
242
-			[true, true,  true],
243
-		];
244
-	}
245
-
246
-	/**
247
-	 * @dataProvider dataRequires2FASetupDone
248
-	 */
249
-	public function testRequires2FASetupDone(bool $hasProvider, bool $missingProviders, bool $expectEception): void {
250
-		if ($hasProvider) {
251
-			$provider = $this->createMock(IProvider::class);
252
-			$provider->method('getId')
253
-				->willReturn('2FAftw');
254
-			$providers = [$provider];
255
-		} else {
256
-			$providers = [];
257
-		}
258
-
259
-
260
-		$user = $this->createMock(IUser::class);
261
-
262
-		$this->reflector
263
-			->method('hasAnnotation')
264
-			->willReturn(false);
265
-		$this->userSession
266
-			->method('getUser')
267
-			->willReturn($user);
268
-		$providerSet = new ProviderSet($providers, $missingProviders);
269
-		$this->twoFactorManager->method('getProviderSet')
270
-			->with($user)
271
-			->willReturn($providerSet);
272
-		$this->userSession
273
-			->method('isLoggedIn')
274
-			->willReturn(false);
275
-
276
-		if ($expectEception) {
277
-			$this->expectException(TwoFactorAuthRequiredException::class);
278
-		} else {
279
-			// hack to make phpunit shut up. Since we don't expect an exception here...
280
-			$this->assertTrue(true);
281
-		}
282
-
283
-		$twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
284
-			->disableOriginalConstructor()
285
-			->getMock();
286
-		$this->middleware->beforeController($twoFactorChallengeController, 'index');
287
-	}
35
+    /** @var Manager|MockObject */
36
+    private $twoFactorManager;
37
+
38
+    /** @var IUserSession|MockObject */
39
+    private $userSession;
40
+
41
+    /** @var ISession|MockObject */
42
+    private $session;
43
+
44
+    /** @var IURLGenerator|MockObject */
45
+    private $urlGenerator;
46
+
47
+    /** @var IControllerMethodReflector|MockObject */
48
+    private $reflector;
49
+
50
+    /** @var IRequest|MockObject */
51
+    private $request;
52
+
53
+    /** @var TwoFactorMiddleware */
54
+    private $middleware;
55
+
56
+    /** @var Controller */
57
+    private $controller;
58
+
59
+    protected function setUp(): void {
60
+        parent::setUp();
61
+
62
+        $this->twoFactorManager = $this->getMockBuilder(Manager::class)
63
+            ->disableOriginalConstructor()
64
+            ->getMock();
65
+        $this->userSession = $this->getMockBuilder(Session::class)
66
+            ->disableOriginalConstructor()
67
+            ->getMock();
68
+        $this->session = $this->createMock(ISession::class);
69
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
70
+        $this->reflector = $this->createMock(IControllerMethodReflector::class);
71
+        $this->request = new Request(
72
+            [
73
+                'server' => [
74
+                    'REQUEST_URI' => 'test/url'
75
+                ]
76
+            ],
77
+            $this->createMock(IRequestId::class),
78
+            $this->createMock(IConfig::class)
79
+        );
80
+
81
+        $this->middleware = new TwoFactorMiddleware($this->twoFactorManager, $this->userSession, $this->session, $this->urlGenerator, $this->reflector, $this->request);
82
+        $this->controller = $this->createMock(Controller::class);
83
+    }
84
+
85
+    public function testBeforeControllerNotLoggedIn(): void {
86
+        $this->userSession->expects($this->once())
87
+            ->method('isLoggedIn')
88
+            ->willReturn(false);
89
+
90
+        $this->userSession->expects($this->never())
91
+            ->method('getUser');
92
+
93
+        $this->middleware->beforeController($this->controller, 'index');
94
+    }
95
+
96
+    public function testBeforeSetupController(): void {
97
+        $user = $this->createMock(IUser::class);
98
+        $controller = $this->createMock(ALoginSetupController::class);
99
+        $this->userSession->expects($this->any())
100
+            ->method('getUser')
101
+            ->willReturn($user);
102
+        $this->twoFactorManager->expects($this->once())
103
+            ->method('needsSecondFactor')
104
+            ->willReturn(true);
105
+        $this->userSession->expects($this->never())
106
+            ->method('isLoggedIn');
107
+
108
+        $this->middleware->beforeController($controller, 'create');
109
+    }
110
+
111
+    public function testBeforeControllerNoTwoFactorCheckNeeded(): void {
112
+        $user = $this->createMock(IUser::class);
113
+
114
+        $this->userSession->expects($this->once())
115
+            ->method('isLoggedIn')
116
+            ->willReturn(true);
117
+        $this->userSession->expects($this->once())
118
+            ->method('getUser')
119
+            ->willReturn($user);
120
+        $this->twoFactorManager->expects($this->once())
121
+            ->method('isTwoFactorAuthenticated')
122
+            ->with($user)
123
+            ->willReturn(false);
124
+
125
+        $this->middleware->beforeController($this->controller, 'index');
126
+    }
127
+
128
+
129
+    public function testBeforeControllerTwoFactorAuthRequired(): void {
130
+        $this->expectException(TwoFactorAuthRequiredException::class);
131
+
132
+        $user = $this->createMock(IUser::class);
133
+
134
+        $this->userSession->expects($this->once())
135
+            ->method('isLoggedIn')
136
+            ->willReturn(true);
137
+        $this->userSession->expects($this->once())
138
+            ->method('getUser')
139
+            ->willReturn($user);
140
+        $this->twoFactorManager->expects($this->once())
141
+            ->method('isTwoFactorAuthenticated')
142
+            ->with($user)
143
+            ->willReturn(true);
144
+        $this->twoFactorManager->expects($this->once())
145
+            ->method('needsSecondFactor')
146
+            ->with($user)
147
+            ->willReturn(true);
148
+
149
+        $this->middleware->beforeController($this->controller, 'index');
150
+    }
151
+
152
+
153
+    public function testBeforeControllerUserAlreadyLoggedIn(): void {
154
+        $this->expectException(UserAlreadyLoggedInException::class);
155
+
156
+        $user = $this->createMock(IUser::class);
157
+
158
+        $this->reflector
159
+            ->method('hasAnnotation')
160
+            ->willReturn(false);
161
+        $this->userSession->expects($this->once())
162
+            ->method('isLoggedIn')
163
+            ->willReturn(true);
164
+        $this->userSession
165
+            ->method('getUser')
166
+            ->willReturn($user);
167
+        $this->twoFactorManager->expects($this->once())
168
+            ->method('isTwoFactorAuthenticated')
169
+            ->with($user)
170
+            ->willReturn(true);
171
+        $this->twoFactorManager->expects($this->once())
172
+            ->method('needsSecondFactor')
173
+            ->with($user)
174
+            ->willReturn(false);
175
+
176
+        $twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
177
+            ->disableOriginalConstructor()
178
+            ->getMock();
179
+        $this->middleware->beforeController($twoFactorChallengeController, 'index');
180
+    }
181
+
182
+    public function testAfterExceptionTwoFactorAuthRequired(): void {
183
+        $ex = new TwoFactorAuthRequiredException();
184
+
185
+        $this->urlGenerator->expects($this->once())
186
+            ->method('linkToRoute')
187
+            ->with('core.TwoFactorChallenge.selectChallenge')
188
+            ->willReturn('test/url');
189
+        $expected = new RedirectResponse('test/url');
190
+
191
+        $this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex));
192
+    }
193
+
194
+    public function testAfterException(): void {
195
+        $ex = new UserAlreadyLoggedInException();
196
+
197
+        $this->urlGenerator->expects($this->once())
198
+            ->method('linkToRoute')
199
+            ->with('files.view.index')
200
+            ->willReturn('redirect/url');
201
+        $expected = new RedirectResponse('redirect/url');
202
+
203
+        $this->assertEquals($expected, $this->middleware->afterException($this->controller, 'index', $ex));
204
+    }
205
+
206
+    public function testRequires2FASetupDoneAnnotated(): void {
207
+        $user = $this->createMock(IUser::class);
208
+
209
+        $this->reflector
210
+            ->method('hasAnnotation')
211
+            ->willReturnCallback(function (string $annotation) {
212
+                return $annotation === 'TwoFactorSetUpDoneRequired';
213
+            });
214
+        $this->userSession->expects($this->once())
215
+            ->method('isLoggedIn')
216
+            ->willReturn(true);
217
+        $this->userSession
218
+            ->method('getUser')
219
+            ->willReturn($user);
220
+        $this->twoFactorManager->expects($this->once())
221
+            ->method('isTwoFactorAuthenticated')
222
+            ->with($user)
223
+            ->willReturn(true);
224
+        $this->twoFactorManager->expects($this->once())
225
+            ->method('needsSecondFactor')
226
+            ->with($user)
227
+            ->willReturn(false);
228
+
229
+        $this->expectException(UserAlreadyLoggedInException::class);
230
+
231
+        $twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
232
+            ->disableOriginalConstructor()
233
+            ->getMock();
234
+        $this->middleware->beforeController($twoFactorChallengeController, 'index');
235
+    }
236
+
237
+    public static function dataRequires2FASetupDone(): array {
238
+        return [
239
+            [false, false, false],
240
+            [false,  true,  true],
241
+            [true, false, true],
242
+            [true, true,  true],
243
+        ];
244
+    }
245
+
246
+    /**
247
+     * @dataProvider dataRequires2FASetupDone
248
+     */
249
+    public function testRequires2FASetupDone(bool $hasProvider, bool $missingProviders, bool $expectEception): void {
250
+        if ($hasProvider) {
251
+            $provider = $this->createMock(IProvider::class);
252
+            $provider->method('getId')
253
+                ->willReturn('2FAftw');
254
+            $providers = [$provider];
255
+        } else {
256
+            $providers = [];
257
+        }
258
+
259
+
260
+        $user = $this->createMock(IUser::class);
261
+
262
+        $this->reflector
263
+            ->method('hasAnnotation')
264
+            ->willReturn(false);
265
+        $this->userSession
266
+            ->method('getUser')
267
+            ->willReturn($user);
268
+        $providerSet = new ProviderSet($providers, $missingProviders);
269
+        $this->twoFactorManager->method('getProviderSet')
270
+            ->with($user)
271
+            ->willReturn($providerSet);
272
+        $this->userSession
273
+            ->method('isLoggedIn')
274
+            ->willReturn(false);
275
+
276
+        if ($expectEception) {
277
+            $this->expectException(TwoFactorAuthRequiredException::class);
278
+        } else {
279
+            // hack to make phpunit shut up. Since we don't expect an exception here...
280
+            $this->assertTrue(true);
281
+        }
282
+
283
+        $twoFactorChallengeController = $this->getMockBuilder(TwoFactorChallengeController::class)
284
+            ->disableOriginalConstructor()
285
+            ->getMock();
286
+        $this->middleware->beforeController($twoFactorChallengeController, 'index');
287
+    }
288 288
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
 
209 209
 		$this->reflector
210 210
 			->method('hasAnnotation')
211
-			->willReturnCallback(function (string $annotation) {
211
+			->willReturnCallback(function(string $annotation) {
212 212
 				return $annotation === 'TwoFactorSetUpDoneRequired';
213 213
 			});
214 214
 		$this->userSession->expects($this->once())
@@ -237,9 +237,9 @@  discard block
 block discarded – undo
237 237
 	public static function dataRequires2FASetupDone(): array {
238 238
 		return [
239 239
 			[false, false, false],
240
-			[false,  true,  true],
240
+			[false, true, true],
241 241
 			[true, false, true],
242
-			[true, true,  true],
242
+			[true, true, true],
243 243
 		];
244 244
 	}
245 245
 
Please login to merge, or discard this patch.
tests/Core/Service/LoginFlowV2ServiceUnitTest.php 1 patch
Indentation   +335 added lines, -335 removed lines patch added patch discarded remove patch
@@ -31,402 +31,402 @@
 block discarded – undo
31 31
  * Unit tests for \OC\Core\Service\LoginFlowV2Service
32 32
  */
33 33
 class LoginFlowV2ServiceUnitTest extends TestCase {
34
-	/** @var \OCP\IConfig */
35
-	private $config;
36
-
37
-	/** @var \OCP\Security\ICrypto */
38
-	private $crypto;
39
-
40
-	/** @var LoggerInterface|MockObject */
41
-	private $logger;
42
-
43
-	/** @var \OC\Core\Db\LoginFlowV2Mapper */
44
-	private $mapper;
45
-
46
-	/** @var \OCP\Security\ISecureRandom */
47
-	private $secureRandom;
48
-
49
-	/** @var \OC\Core\Service\LoginFlowV2Service */
50
-	private $subjectUnderTest;
51
-
52
-	/** @var \OCP\AppFramework\Utility\ITimeFactory */
53
-	private $timeFactory;
54
-
55
-	/** @var \OC\Authentication\Token\IProvider */
56
-	private $tokenProvider;
57
-
58
-	public function setUp(): void {
59
-		parent::setUp();
60
-
61
-		$this->setupSubjectUnderTest();
62
-	}
63
-
64
-	/**
65
-	 * Setup subject under test with mocked constructor arguments.
66
-	 *
67
-	 * Code was moved to separate function to keep setUp function small and clear.
68
-	 */
69
-	private function setupSubjectUnderTest(): void {
70
-		$this->config = $this->createMock(IConfig::class);
71
-		$this->crypto = $this->createMock(ICrypto::class);
72
-		$this->mapper = $this->createMock(LoginFlowV2Mapper::class);
73
-		$this->logger = $this->createMock(LoggerInterface::class);
74
-		$this->tokenProvider = $this->createMock(IProvider::class);
75
-		$this->secureRandom = $this->createMock(ISecureRandom::class);
76
-		$this->timeFactory = $this->createMock(ITimeFactory::class);
77
-
78
-		$this->subjectUnderTest = new LoginFlowV2Service(
79
-			$this->mapper,
80
-			$this->secureRandom,
81
-			$this->timeFactory,
82
-			$this->config,
83
-			$this->crypto,
84
-			$this->logger,
85
-			$this->tokenProvider
86
-		);
87
-	}
88
-
89
-	/**
90
-	 * Generates for a given password required OpenSSL parts.
91
-	 *
92
-	 * @return array Array contains encrypted password, private key and public key.
93
-	 */
94
-	private function getOpenSSLEncryptedPublicAndPrivateKey(string $appPassword): array {
95
-		// Create the private and public key
96
-		$res = openssl_pkey_new([
97
-			'digest_alg' => 'md5', // take fast algorithm for testing purposes
98
-			'private_key_bits' => 512,
99
-			'private_key_type' => OPENSSL_KEYTYPE_RSA,
100
-		]);
101
-
102
-		// Extract the private key from $res
103
-		openssl_pkey_export($res, $privateKey);
104
-
105
-		// Extract the public key from $res
106
-		$publicKey = openssl_pkey_get_details($res);
107
-		$publicKey = $publicKey['key'];
108
-
109
-		// Encrypt the data to $encrypted using the public key
110
-		openssl_public_encrypt($appPassword, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
111
-
112
-		return [$encrypted, $privateKey, $publicKey];
113
-	}
114
-
115
-	/*
34
+    /** @var \OCP\IConfig */
35
+    private $config;
36
+
37
+    /** @var \OCP\Security\ICrypto */
38
+    private $crypto;
39
+
40
+    /** @var LoggerInterface|MockObject */
41
+    private $logger;
42
+
43
+    /** @var \OC\Core\Db\LoginFlowV2Mapper */
44
+    private $mapper;
45
+
46
+    /** @var \OCP\Security\ISecureRandom */
47
+    private $secureRandom;
48
+
49
+    /** @var \OC\Core\Service\LoginFlowV2Service */
50
+    private $subjectUnderTest;
51
+
52
+    /** @var \OCP\AppFramework\Utility\ITimeFactory */
53
+    private $timeFactory;
54
+
55
+    /** @var \OC\Authentication\Token\IProvider */
56
+    private $tokenProvider;
57
+
58
+    public function setUp(): void {
59
+        parent::setUp();
60
+
61
+        $this->setupSubjectUnderTest();
62
+    }
63
+
64
+    /**
65
+     * Setup subject under test with mocked constructor arguments.
66
+     *
67
+     * Code was moved to separate function to keep setUp function small and clear.
68
+     */
69
+    private function setupSubjectUnderTest(): void {
70
+        $this->config = $this->createMock(IConfig::class);
71
+        $this->crypto = $this->createMock(ICrypto::class);
72
+        $this->mapper = $this->createMock(LoginFlowV2Mapper::class);
73
+        $this->logger = $this->createMock(LoggerInterface::class);
74
+        $this->tokenProvider = $this->createMock(IProvider::class);
75
+        $this->secureRandom = $this->createMock(ISecureRandom::class);
76
+        $this->timeFactory = $this->createMock(ITimeFactory::class);
77
+
78
+        $this->subjectUnderTest = new LoginFlowV2Service(
79
+            $this->mapper,
80
+            $this->secureRandom,
81
+            $this->timeFactory,
82
+            $this->config,
83
+            $this->crypto,
84
+            $this->logger,
85
+            $this->tokenProvider
86
+        );
87
+    }
88
+
89
+    /**
90
+     * Generates for a given password required OpenSSL parts.
91
+     *
92
+     * @return array Array contains encrypted password, private key and public key.
93
+     */
94
+    private function getOpenSSLEncryptedPublicAndPrivateKey(string $appPassword): array {
95
+        // Create the private and public key
96
+        $res = openssl_pkey_new([
97
+            'digest_alg' => 'md5', // take fast algorithm for testing purposes
98
+            'private_key_bits' => 512,
99
+            'private_key_type' => OPENSSL_KEYTYPE_RSA,
100
+        ]);
101
+
102
+        // Extract the private key from $res
103
+        openssl_pkey_export($res, $privateKey);
104
+
105
+        // Extract the public key from $res
106
+        $publicKey = openssl_pkey_get_details($res);
107
+        $publicKey = $publicKey['key'];
108
+
109
+        // Encrypt the data to $encrypted using the public key
110
+        openssl_public_encrypt($appPassword, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
111
+
112
+        return [$encrypted, $privateKey, $publicKey];
113
+    }
114
+
115
+    /*
116 116
 	 * Tests for poll
117 117
 	 */
118 118
 
119
-	public function testPollApptokenCouldNotBeDecrypted(): void {
120
-		$this->expectException(LoginFlowV2NotFoundException::class);
121
-		$this->expectExceptionMessage('Apptoken could not be decrypted');
119
+    public function testPollApptokenCouldNotBeDecrypted(): void {
120
+        $this->expectException(LoginFlowV2NotFoundException::class);
121
+        $this->expectExceptionMessage('Apptoken could not be decrypted');
122 122
 
123
-		/*
123
+        /*
124 124
 		 * Cannot be mocked, because functions like getLoginName are magic functions.
125 125
 		 * To be able to set internal properties, we have to use the real class here.
126 126
 		 */
127
-		$loginFlowV2 = new LoginFlowV2();
128
-		$loginFlowV2->setLoginName('test');
129
-		$loginFlowV2->setServer('test');
130
-		$loginFlowV2->setAppPassword('test');
131
-		$loginFlowV2->setPrivateKey('test');
127
+        $loginFlowV2 = new LoginFlowV2();
128
+        $loginFlowV2->setLoginName('test');
129
+        $loginFlowV2->setServer('test');
130
+        $loginFlowV2->setAppPassword('test');
131
+        $loginFlowV2->setPrivateKey('test');
132 132
 
133
-		$this->mapper->expects($this->once())
134
-			->method('getByPollToken')
135
-			->willReturn($loginFlowV2);
133
+        $this->mapper->expects($this->once())
134
+            ->method('getByPollToken')
135
+            ->willReturn($loginFlowV2);
136 136
 
137
-		$this->subjectUnderTest->poll('');
138
-	}
137
+        $this->subjectUnderTest->poll('');
138
+    }
139 139
 
140
-	public function testPollInvalidToken(): void {
141
-		$this->expectException(LoginFlowV2NotFoundException::class);
142
-		$this->expectExceptionMessage('Invalid token');
140
+    public function testPollInvalidToken(): void {
141
+        $this->expectException(LoginFlowV2NotFoundException::class);
142
+        $this->expectExceptionMessage('Invalid token');
143 143
 
144
-		$this->mapper->expects($this->once())
145
-			->method('getByPollToken')
146
-			->willThrowException(new DoesNotExistException(''));
144
+        $this->mapper->expects($this->once())
145
+            ->method('getByPollToken')
146
+            ->willThrowException(new DoesNotExistException(''));
147 147
 
148
-		$this->subjectUnderTest->poll('');
149
-	}
148
+        $this->subjectUnderTest->poll('');
149
+    }
150 150
 
151
-	public function testPollTokenNotYetReady(): void {
152
-		$this->expectException(LoginFlowV2NotFoundException::class);
153
-		$this->expectExceptionMessage('Token not yet ready');
151
+    public function testPollTokenNotYetReady(): void {
152
+        $this->expectException(LoginFlowV2NotFoundException::class);
153
+        $this->expectExceptionMessage('Token not yet ready');
154 154
 
155
-		$this->subjectUnderTest->poll('');
156
-	}
155
+        $this->subjectUnderTest->poll('');
156
+    }
157 157
 
158
-	public function testPollRemoveDataFromDb(): void {
159
-		[$encrypted, $privateKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass');
158
+    public function testPollRemoveDataFromDb(): void {
159
+        [$encrypted, $privateKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass');
160 160
 
161
-		$this->crypto->expects($this->once())
162
-			->method('decrypt')
163
-			->willReturn($privateKey);
161
+        $this->crypto->expects($this->once())
162
+            ->method('decrypt')
163
+            ->willReturn($privateKey);
164 164
 
165
-		/*
165
+        /*
166 166
 		 * Cannot be mocked, because functions like getLoginName are magic functions.
167 167
 		 * To be able to set internal properties, we have to use the real class here.
168 168
 		 */
169
-		$loginFlowV2 = new LoginFlowV2();
170
-		$loginFlowV2->setLoginName('test_login');
171
-		$loginFlowV2->setServer('test_server');
172
-		$loginFlowV2->setAppPassword(base64_encode($encrypted));
173
-		$loginFlowV2->setPrivateKey($privateKey);
174
-
175
-		$this->mapper->expects($this->once())
176
-			->method('delete')
177
-			->with($this->equalTo($loginFlowV2));
178
-
179
-		$this->mapper->expects($this->once())
180
-			->method('getByPollToken')
181
-			->willReturn($loginFlowV2);
182
-
183
-		$credentials = $this->subjectUnderTest->poll('');
184
-
185
-		$this->assertTrue($credentials instanceof LoginFlowV2Credentials);
186
-		$this->assertEquals(
187
-			[
188
-				'server' => 'test_server',
189
-				'loginName' => 'test_login',
190
-				'appPassword' => 'test_pass',
191
-			],
192
-			$credentials->jsonSerialize()
193
-		);
194
-	}
195
-
196
-	/*
169
+        $loginFlowV2 = new LoginFlowV2();
170
+        $loginFlowV2->setLoginName('test_login');
171
+        $loginFlowV2->setServer('test_server');
172
+        $loginFlowV2->setAppPassword(base64_encode($encrypted));
173
+        $loginFlowV2->setPrivateKey($privateKey);
174
+
175
+        $this->mapper->expects($this->once())
176
+            ->method('delete')
177
+            ->with($this->equalTo($loginFlowV2));
178
+
179
+        $this->mapper->expects($this->once())
180
+            ->method('getByPollToken')
181
+            ->willReturn($loginFlowV2);
182
+
183
+        $credentials = $this->subjectUnderTest->poll('');
184
+
185
+        $this->assertTrue($credentials instanceof LoginFlowV2Credentials);
186
+        $this->assertEquals(
187
+            [
188
+                'server' => 'test_server',
189
+                'loginName' => 'test_login',
190
+                'appPassword' => 'test_pass',
191
+            ],
192
+            $credentials->jsonSerialize()
193
+        );
194
+    }
195
+
196
+    /*
197 197
 	 * Tests for getByLoginToken
198 198
 	 */
199 199
 
200
-	public function testGetByLoginToken(): void {
201
-		$loginFlowV2 = new LoginFlowV2();
202
-		$loginFlowV2->setLoginName('test_login');
203
-		$loginFlowV2->setServer('test_server');
204
-		$loginFlowV2->setAppPassword('test');
200
+    public function testGetByLoginToken(): void {
201
+        $loginFlowV2 = new LoginFlowV2();
202
+        $loginFlowV2->setLoginName('test_login');
203
+        $loginFlowV2->setServer('test_server');
204
+        $loginFlowV2->setAppPassword('test');
205 205
 
206
-		$this->mapper->expects($this->once())
207
-			->method('getByLoginToken')
208
-			->willReturn($loginFlowV2);
206
+        $this->mapper->expects($this->once())
207
+            ->method('getByLoginToken')
208
+            ->willReturn($loginFlowV2);
209 209
 
210
-		$result = $this->subjectUnderTest->getByLoginToken('test_token');
210
+        $result = $this->subjectUnderTest->getByLoginToken('test_token');
211 211
 
212
-		$this->assertTrue($result instanceof LoginFlowV2);
213
-		$this->assertEquals('test_server', $result->getServer());
214
-		$this->assertEquals('test_login', $result->getLoginName());
215
-		$this->assertEquals('test', $result->getAppPassword());
216
-	}
212
+        $this->assertTrue($result instanceof LoginFlowV2);
213
+        $this->assertEquals('test_server', $result->getServer());
214
+        $this->assertEquals('test_login', $result->getLoginName());
215
+        $this->assertEquals('test', $result->getAppPassword());
216
+    }
217 217
 
218
-	public function testGetByLoginTokenLoginTokenInvalid(): void {
219
-		$this->expectException(LoginFlowV2NotFoundException::class);
220
-		$this->expectExceptionMessage('Login token invalid');
218
+    public function testGetByLoginTokenLoginTokenInvalid(): void {
219
+        $this->expectException(LoginFlowV2NotFoundException::class);
220
+        $this->expectExceptionMessage('Login token invalid');
221 221
 
222
-		$this->mapper->expects($this->once())
223
-			->method('getByLoginToken')
224
-			->willThrowException(new DoesNotExistException(''));
222
+        $this->mapper->expects($this->once())
223
+            ->method('getByLoginToken')
224
+            ->willThrowException(new DoesNotExistException(''));
225 225
 
226
-		$this->subjectUnderTest->getByLoginToken('test_token');
227
-	}
226
+        $this->subjectUnderTest->getByLoginToken('test_token');
227
+    }
228 228
 
229
-	public function testGetByLoginTokenClientForbidden() {
230
-		$this->expectException(LoginFlowV2ClientForbiddenException::class);
231
-		$this->expectExceptionMessage('Client not allowed');
229
+    public function testGetByLoginTokenClientForbidden() {
230
+        $this->expectException(LoginFlowV2ClientForbiddenException::class);
231
+        $this->expectExceptionMessage('Client not allowed');
232 232
 
233
-		$allowedClients = [
234
-			'/Custom Allowed Client/i'
235
-		];
233
+        $allowedClients = [
234
+            '/Custom Allowed Client/i'
235
+        ];
236 236
 
237
-		$this->config->expects($this->exactly(1))
238
-			->method('getSystemValue')
239
-			->willReturn($this->returnCallback(function ($key) use ($allowedClients) {
240
-				// Note: \OCP\IConfig::getSystemValue returns either an array or string.
241
-				return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : '';
242
-			}));
237
+        $this->config->expects($this->exactly(1))
238
+            ->method('getSystemValue')
239
+            ->willReturn($this->returnCallback(function ($key) use ($allowedClients) {
240
+                // Note: \OCP\IConfig::getSystemValue returns either an array or string.
241
+                return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : '';
242
+            }));
243 243
 
244
-		$loginFlowV2 = new LoginFlowV2();
245
-		$loginFlowV2->setClientName('Rogue Curl Client/1.0');
244
+        $loginFlowV2 = new LoginFlowV2();
245
+        $loginFlowV2->setClientName('Rogue Curl Client/1.0');
246 246
 
247
-		$this->mapper->expects($this->once())
248
-			->method('getByLoginToken')
249
-			->willReturn($loginFlowV2);
247
+        $this->mapper->expects($this->once())
248
+            ->method('getByLoginToken')
249
+            ->willReturn($loginFlowV2);
250 250
 
251
-		$this->subjectUnderTest->getByLoginToken('test_token');
252
-	}
251
+        $this->subjectUnderTest->getByLoginToken('test_token');
252
+    }
253 253
 
254
-	public function testGetByLoginTokenClientAllowed() {
255
-		$allowedClients = [
256
-			'/Foo Allowed Client/i',
257
-			'/Custom Allowed Client/i'
258
-		];
254
+    public function testGetByLoginTokenClientAllowed() {
255
+        $allowedClients = [
256
+            '/Foo Allowed Client/i',
257
+            '/Custom Allowed Client/i'
258
+        ];
259 259
 
260
-		$loginFlowV2 = new LoginFlowV2();
261
-		$loginFlowV2->setClientName('Custom Allowed Client Curl Client/1.0');
260
+        $loginFlowV2 = new LoginFlowV2();
261
+        $loginFlowV2->setClientName('Custom Allowed Client Curl Client/1.0');
262 262
 
263
-		$this->config->expects($this->exactly(1))
264
-			->method('getSystemValue')
265
-			->willReturn($this->returnCallback(function ($key) use ($allowedClients) {
266
-				// Note: \OCP\IConfig::getSystemValue returns either an array or string.
267
-				return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : '';
268
-			}));
263
+        $this->config->expects($this->exactly(1))
264
+            ->method('getSystemValue')
265
+            ->willReturn($this->returnCallback(function ($key) use ($allowedClients) {
266
+                // Note: \OCP\IConfig::getSystemValue returns either an array or string.
267
+                return $key == 'core.login_flow_v2.allowed_user_agents' ? $allowedClients : '';
268
+            }));
269 269
 
270
-		$this->mapper->expects($this->once())
271
-			->method('getByLoginToken')
272
-			->willReturn($loginFlowV2);
270
+        $this->mapper->expects($this->once())
271
+            ->method('getByLoginToken')
272
+            ->willReturn($loginFlowV2);
273 273
 
274
-		$result = $this->subjectUnderTest->getByLoginToken('test_token');
274
+        $result = $this->subjectUnderTest->getByLoginToken('test_token');
275 275
 
276
-		$this->assertTrue($result instanceof LoginFlowV2);
277
-		$this->assertEquals('Custom Allowed Client Curl Client/1.0', $result->getClientName());
278
-	}
276
+        $this->assertTrue($result instanceof LoginFlowV2);
277
+        $this->assertEquals('Custom Allowed Client Curl Client/1.0', $result->getClientName());
278
+    }
279 279
 
280
-	/*
280
+    /*
281 281
 	 * Tests for startLoginFlow
282 282
 	 */
283 283
 
284
-	public function testStartLoginFlow(): void {
285
-		$loginFlowV2 = new LoginFlowV2();
284
+    public function testStartLoginFlow(): void {
285
+        $loginFlowV2 = new LoginFlowV2();
286 286
 
287
-		$this->mapper->expects($this->once())
288
-			->method('getByLoginToken')
289
-			->willReturn($loginFlowV2);
287
+        $this->mapper->expects($this->once())
288
+            ->method('getByLoginToken')
289
+            ->willReturn($loginFlowV2);
290 290
 
291
-		$this->mapper->expects($this->once())
292
-			->method('update');
291
+        $this->mapper->expects($this->once())
292
+            ->method('update');
293 293
 
294
-		$this->assertTrue($this->subjectUnderTest->startLoginFlow('test_token'));
295
-	}
294
+        $this->assertTrue($this->subjectUnderTest->startLoginFlow('test_token'));
295
+    }
296 296
 
297
-	public function testStartLoginFlowDoesNotExistException(): void {
298
-		$this->mapper->expects($this->once())
299
-			->method('getByLoginToken')
300
-			->willThrowException(new DoesNotExistException(''));
297
+    public function testStartLoginFlowDoesNotExistException(): void {
298
+        $this->mapper->expects($this->once())
299
+            ->method('getByLoginToken')
300
+            ->willThrowException(new DoesNotExistException(''));
301 301
 
302
-		$this->assertFalse($this->subjectUnderTest->startLoginFlow('test_token'));
303
-	}
302
+        $this->assertFalse($this->subjectUnderTest->startLoginFlow('test_token'));
303
+    }
304 304
 
305
-	/**
306
-	 * If an exception not of type DoesNotExistException is thrown,
307
-	 * it is expected that it is not being handled by startLoginFlow.
308
-	 */
309
-	public function testStartLoginFlowException(): void {
310
-		$this->expectException(Exception::class);
305
+    /**
306
+     * If an exception not of type DoesNotExistException is thrown,
307
+     * it is expected that it is not being handled by startLoginFlow.
308
+     */
309
+    public function testStartLoginFlowException(): void {
310
+        $this->expectException(Exception::class);
311 311
 
312
-		$this->mapper->expects($this->once())
313
-			->method('getByLoginToken')
314
-			->willThrowException(new Exception(''));
312
+        $this->mapper->expects($this->once())
313
+            ->method('getByLoginToken')
314
+            ->willThrowException(new Exception(''));
315 315
 
316
-		$this->subjectUnderTest->startLoginFlow('test_token');
317
-	}
316
+        $this->subjectUnderTest->startLoginFlow('test_token');
317
+    }
318 318
 
319
-	/*
319
+    /*
320 320
 	 * Tests for flowDone
321 321
 	 */
322 322
 
323
-	public function testFlowDone(): void {
324
-		[,, $publicKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass');
325
-
326
-		$loginFlowV2 = new LoginFlowV2();
327
-		$loginFlowV2->setPublicKey($publicKey);
328
-		$loginFlowV2->setClientName('client_name');
329
-
330
-		$this->mapper->expects($this->once())
331
-			->method('getByLoginToken')
332
-			->willReturn($loginFlowV2);
333
-
334
-		$this->mapper->expects($this->once())
335
-			->method('update');
336
-
337
-		$this->secureRandom->expects($this->once())
338
-			->method('generate')
339
-			->with(72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS)
340
-			->willReturn('test_pass');
341
-
342
-		// session token
343
-		$sessionToken = $this->getMockBuilder(IToken::class)->disableOriginalConstructor()->getMock();
344
-		$sessionToken->expects($this->once())
345
-			->method('getLoginName')
346
-			->willReturn('login_name');
347
-
348
-		$this->tokenProvider->expects($this->once())
349
-			->method('getPassword')
350
-			->willReturn('test_pass');
351
-
352
-		$this->tokenProvider->expects($this->once())
353
-			->method('getToken')
354
-			->willReturn($sessionToken);
355
-
356
-		$this->tokenProvider->expects($this->once())
357
-			->method('generateToken')
358
-			->with(
359
-				'test_pass',
360
-				'user_id',
361
-				'login_name',
362
-				'test_pass',
363
-				'client_name',
364
-				IToken::PERMANENT_TOKEN,
365
-				IToken::DO_NOT_REMEMBER
366
-			);
367
-
368
-		$result = $this->subjectUnderTest->flowDone(
369
-			'login_token',
370
-			'session_id',
371
-			'server',
372
-			'user_id'
373
-		);
374
-		$this->assertTrue($result);
375
-
376
-		// app password is encrypted and must look like:
377
-		// ZACZOOzxTpKz4+KXL5kZ/gCK0xvkaVi/8yzupAn6Ui6+5qCSKvfPKGgeDRKs0sivvSLzk/XSp811SZCZmH0Y3g==
378
-		$this->assertMatchesRegularExpression('/[a-zA-Z\/0-9+=]+/', $loginFlowV2->getAppPassword());
379
-
380
-		$this->assertEquals('server', $loginFlowV2->getServer());
381
-	}
382
-
383
-	public function testFlowDoneDoesNotExistException(): void {
384
-		$this->mapper->expects($this->once())
385
-			->method('getByLoginToken')
386
-			->willThrowException(new DoesNotExistException(''));
387
-
388
-		$result = $this->subjectUnderTest->flowDone(
389
-			'login_token',
390
-			'session_id',
391
-			'server',
392
-			'user_id'
393
-		);
394
-		$this->assertFalse($result);
395
-	}
396
-
397
-	public function testFlowDonePasswordlessTokenException(): void {
398
-		$this->tokenProvider->expects($this->once())
399
-			->method('getToken')
400
-			->willThrowException(new InvalidTokenException(''));
401
-
402
-		$result = $this->subjectUnderTest->flowDone(
403
-			'login_token',
404
-			'session_id',
405
-			'server',
406
-			'user_id'
407
-		);
408
-		$this->assertFalse($result);
409
-	}
410
-
411
-	/*
323
+    public function testFlowDone(): void {
324
+        [,, $publicKey] = $this->getOpenSSLEncryptedPublicAndPrivateKey('test_pass');
325
+
326
+        $loginFlowV2 = new LoginFlowV2();
327
+        $loginFlowV2->setPublicKey($publicKey);
328
+        $loginFlowV2->setClientName('client_name');
329
+
330
+        $this->mapper->expects($this->once())
331
+            ->method('getByLoginToken')
332
+            ->willReturn($loginFlowV2);
333
+
334
+        $this->mapper->expects($this->once())
335
+            ->method('update');
336
+
337
+        $this->secureRandom->expects($this->once())
338
+            ->method('generate')
339
+            ->with(72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS)
340
+            ->willReturn('test_pass');
341
+
342
+        // session token
343
+        $sessionToken = $this->getMockBuilder(IToken::class)->disableOriginalConstructor()->getMock();
344
+        $sessionToken->expects($this->once())
345
+            ->method('getLoginName')
346
+            ->willReturn('login_name');
347
+
348
+        $this->tokenProvider->expects($this->once())
349
+            ->method('getPassword')
350
+            ->willReturn('test_pass');
351
+
352
+        $this->tokenProvider->expects($this->once())
353
+            ->method('getToken')
354
+            ->willReturn($sessionToken);
355
+
356
+        $this->tokenProvider->expects($this->once())
357
+            ->method('generateToken')
358
+            ->with(
359
+                'test_pass',
360
+                'user_id',
361
+                'login_name',
362
+                'test_pass',
363
+                'client_name',
364
+                IToken::PERMANENT_TOKEN,
365
+                IToken::DO_NOT_REMEMBER
366
+            );
367
+
368
+        $result = $this->subjectUnderTest->flowDone(
369
+            'login_token',
370
+            'session_id',
371
+            'server',
372
+            'user_id'
373
+        );
374
+        $this->assertTrue($result);
375
+
376
+        // app password is encrypted and must look like:
377
+        // ZACZOOzxTpKz4+KXL5kZ/gCK0xvkaVi/8yzupAn6Ui6+5qCSKvfPKGgeDRKs0sivvSLzk/XSp811SZCZmH0Y3g==
378
+        $this->assertMatchesRegularExpression('/[a-zA-Z\/0-9+=]+/', $loginFlowV2->getAppPassword());
379
+
380
+        $this->assertEquals('server', $loginFlowV2->getServer());
381
+    }
382
+
383
+    public function testFlowDoneDoesNotExistException(): void {
384
+        $this->mapper->expects($this->once())
385
+            ->method('getByLoginToken')
386
+            ->willThrowException(new DoesNotExistException(''));
387
+
388
+        $result = $this->subjectUnderTest->flowDone(
389
+            'login_token',
390
+            'session_id',
391
+            'server',
392
+            'user_id'
393
+        );
394
+        $this->assertFalse($result);
395
+    }
396
+
397
+    public function testFlowDonePasswordlessTokenException(): void {
398
+        $this->tokenProvider->expects($this->once())
399
+            ->method('getToken')
400
+            ->willThrowException(new InvalidTokenException(''));
401
+
402
+        $result = $this->subjectUnderTest->flowDone(
403
+            'login_token',
404
+            'session_id',
405
+            'server',
406
+            'user_id'
407
+        );
408
+        $this->assertFalse($result);
409
+    }
410
+
411
+    /*
412 412
 	 * Tests for createTokens
413 413
 	 */
414 414
 
415
-	public function testCreateTokens(): void {
416
-		$this->config->expects($this->exactly(2))
417
-			->method('getSystemValue')
418
-			->willReturn($this->returnCallback(function ($key) {
419
-				// Note: \OCP\IConfig::getSystemValue returns either an array or string.
420
-				return $key == 'openssl' ? [] : '';
421
-			}));
415
+    public function testCreateTokens(): void {
416
+        $this->config->expects($this->exactly(2))
417
+            ->method('getSystemValue')
418
+            ->willReturn($this->returnCallback(function ($key) {
419
+                // Note: \OCP\IConfig::getSystemValue returns either an array or string.
420
+                return $key == 'openssl' ? [] : '';
421
+            }));
422 422
 
423
-		$this->mapper->expects($this->once())
424
-			->method('insert');
423
+        $this->mapper->expects($this->once())
424
+            ->method('insert');
425 425
 
426
-		$this->secureRandom->expects($this->exactly(2))
427
-			->method('generate');
426
+        $this->secureRandom->expects($this->exactly(2))
427
+            ->method('generate');
428 428
 
429
-		$token = $this->subjectUnderTest->createTokens('user_agent');
430
-		$this->assertTrue($token instanceof LoginFlowV2Tokens);
431
-	}
429
+        $token = $this->subjectUnderTest->createTokens('user_agent');
430
+        $this->assertTrue($token instanceof LoginFlowV2Tokens);
431
+    }
432 432
 }
Please login to merge, or discard this patch.