Skip to content

Commit d634f0f

Browse files
Support for Querying Resources Using HTTP POST (limosa-io#97)
1 parent fd2dbac commit d634f0f

File tree

3 files changed

+77
-2
lines changed

3 files changed

+77
-2
lines changed

src/Http/Controllers/ResourceController.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use ArieTimmerman\Laravel\SCIMServer\Events\Patch;
1616
use ArieTimmerman\Laravel\SCIMServer\Parser\Parser as ParserParser;
1717
use ArieTimmerman\Laravel\SCIMServer\PolicyDecisionPoint;
18+
use ArieTimmerman\Laravel\SCIMServer\Tests\Model\User;
1819
use Illuminate\Contracts\Pagination\CursorPaginator;
1920
use Illuminate\Database\Eloquent\Builder;
2021
use Illuminate\Support\Facades\Validator;
@@ -274,14 +275,20 @@ function (Builder $query) use ($filter, $resourceType) {
274275
}
275276

276277
// TODO: splitting the attributes parameters by dot and comma is not correct, but works in most cases
277-
$attributes = $request->input('attributes') ? preg_split('/[,.]/', $request->input('attributes')) : [];
278+
// if body contains attributes and this is an array, use that, else use existing
279+
if($request->json('attributes') && is_array($request->json('attributes'))){
280+
$attributes = $request->json('attributes');
281+
} else {
282+
$attributes = $request->input('attributes') ? preg_split('/[,.]/', $request->input('attributes')) : [];
283+
}
278284

279285
if (!empty($attributes)) {
280286
$attributes[] = 'id';
281287
$attributes[] = 'meta';
282288
$attributes[] = 'schemas';
283289
}
284290

291+
// TODO: implement excludedAttributes
285292
$excludedAttributes = [];
286293

287294
return new ListResponse(
@@ -295,4 +302,19 @@ function (Builder $query) use ($filter, $resourceType) {
295302
($resourceObjects instanceof CursorPaginator) ? $resourceObjects->previousCursor()?->encode() : null
296303
);
297304
}
305+
306+
public function search(Request $request, PolicyDecisionPoint $pdp, ResourceType $resourceType){
307+
308+
$input = $request->json()->all();
309+
310+
// ensure request post body is a scim SearchRequest
311+
if (!is_array($input) || !isset($input['schemas']) || !in_array("urn:ietf:params:scim:api:messages:2.0:SearchRequest", $input['schemas'])) {
312+
throw (new SCIMException('Invalid schema. MUST be "urn:ietf:params:scim:api:messages:2.0:SearchRequest"'))->setCode(400);
313+
}
314+
315+
// ensure $request->input reads from payload/post only, not query parameters
316+
$request->replace($request->json()->all());
317+
318+
return $this->index($request, $pdp, $resourceType);
319+
}
298320
}

src/RouteProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ private static function allRoutes(array $options = [])
7878
// TODO: Use the attributes parameters ?attributes=userName, excludedAttributes=asdg,asdg (respect "returned" settings "always")
7979
Route::get('/{resourceType}/{resourceObject}', '\ArieTimmerman\Laravel\SCIMServer\Http\Controllers\ResourceController@show')->name('scim.resource');
8080
Route::get("/{resourceType}", '\ArieTimmerman\Laravel\SCIMServer\Http\Controllers\ResourceController@index')->name('scim.resources');
81-
81+
Route::post("/{resourceType}/.search", '\ArieTimmerman\Laravel\SCIMServer\Http\Controllers\ResourceController@search');
8282
Route::post("/{resourceType}", '\ArieTimmerman\Laravel\SCIMServer\Http\Controllers\ResourceController@create');
8383

8484
Route::put("/{resourceType}/{resourceObject}", '\ArieTimmerman\Laravel\SCIMServer\Http\Controllers\ResourceController@replace');

tests/BasicTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,41 @@ public function testGetAttributes()
5656
]
5757
]
5858
]);
59+
60+
foreach ($response->json('Resources') as $resource) {
61+
$this->assertArrayNotHasKey('emails', $resource['urn:ietf:params:scim:schemas:core:2.0:User']);
62+
}
63+
}
64+
65+
public function testGetAttributesSearch()
66+
{
67+
$response = $this->postJson(
68+
'/scim/v2/Users/.search',
69+
[
70+
'schemas' => ['urn:ietf:params:scim:api:messages:2.0:SearchRequest'],
71+
'attributes' => [
72+
'userName',
73+
'name.formatted',
74+
'groups'
75+
]
76+
]
77+
);
78+
79+
$response->assertStatus(200);
80+
$response->assertJsonCount(10, 'Resources');
81+
$response->assertJsonStructure([
82+
'Resources' => [
83+
'*' => [
84+
'urn:ietf:params:scim:schemas:core:2.0:User' => [
85+
'userName',
86+
]
87+
]
88+
]
89+
]);
90+
91+
foreach ($response->json('Resources') as $resource) {
92+
$this->assertArrayNotHasKey('emails', $resource['urn:ietf:params:scim:schemas:core:2.0:User']);
93+
}
5994
}
6095

6196
public function testGetGroupsAttribute()
@@ -180,6 +215,24 @@ public function testFilterByGroup()
180215
$response->assertStatus(200);
181216
}
182217

218+
public function testSearch()
219+
{
220+
// First get a username to search for
221+
$response = $this->postJson('/scim/v2/Users/.search', [
222+
'schemas' => ['urn:ietf:params:scim:api:messages:2.0:SearchRequest'],
223+
"startIndex" => 30,
224+
"count" => 1
225+
]);
226+
227+
$userName = $response->json('Resources')[0]['urn:ietf:params:scim:schemas:core:2.0:User']['userName'];
228+
229+
// Now search for this username
230+
$response = $this->get('/scim/v2/Users?filter=userName eq "'.$userName.'"');
231+
$response->assertStatus(200);
232+
233+
$this->assertEquals(1, count($response->json('Resources')));
234+
}
235+
183236
public function testGroupAssignment()
184237
{
185238
// First get a username to search for

0 commit comments

Comments
 (0)