API: Add /users/{id}/angeltypes, updated openapi formatting
This commit is contained in:
parent
497c1772f7
commit
5b237febf8
|
@ -123,6 +123,7 @@ $route->addGroup(
|
||||||
$route->get('/news', 'Api\NewsController@index');
|
$route->get('/news', 'Api\NewsController@index');
|
||||||
$route->get('/locations', 'Api\LocationsController@index');
|
$route->get('/locations', 'Api\LocationsController@index');
|
||||||
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
|
$route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
|
||||||
|
$route->get('/users/{user_id:\d+}/angeltypes', 'Api\AngelTypeController@ofUser');
|
||||||
|
|
||||||
$route->addRoute(
|
$route->addRoute(
|
||||||
['POST', 'PUT', 'DELETE', 'PATCH'],
|
['POST', 'PUT', 'DELETE', 'PATCH'],
|
||||||
|
|
|
@ -3,7 +3,7 @@ openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
version: 0.0.1-beta
|
version: 0.0.1-beta
|
||||||
title: Engelsystem
|
title: Engelsystem
|
||||||
description: |
|
description: >
|
||||||
This API is as stable as a **beta** version might be.
|
This API is as stable as a **beta** version might be.
|
||||||
It could burst into flames and morph into a monster at any second!
|
It could burst into flames and morph into a monster at any second!
|
||||||
(But we try to keep it somewhat consistent, at least during events).
|
(But we try to keep it somewhat consistent, at least during events).
|
||||||
|
@ -25,6 +25,8 @@ tags:
|
||||||
description: News and meeting announcements
|
description: News and meeting announcements
|
||||||
- name: shift
|
- name: shift
|
||||||
description: Event shifts and location
|
description: Event shifts and location
|
||||||
|
- name: user
|
||||||
|
description: User information
|
||||||
|
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
|
@ -81,6 +83,24 @@ components:
|
||||||
- name
|
- name
|
||||||
- description
|
- description
|
||||||
- url
|
- url
|
||||||
|
UserAngelType:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/AngelType'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
confirmed:
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
description: >
|
||||||
|
If the user is confirmed
|
||||||
|
(either by the angeltype not requiring confirmation, being a supporter or being confirmed by one).
|
||||||
|
supporter:
|
||||||
|
type: boolean
|
||||||
|
example: false
|
||||||
|
description: If the user is a supporter of the angeltype.
|
||||||
|
required:
|
||||||
|
- confirmed
|
||||||
|
- supporter
|
||||||
Error:
|
Error:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -168,9 +188,9 @@ components:
|
||||||
example: Cleanup the venue
|
example: Cleanup the venue
|
||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
example: You clean up the venue after the event, its fun, we promise!
|
example: You clean up the venue after the event. Its fun, we promise!
|
||||||
description: |
|
description: >
|
||||||
Shift description, should be added to the shift type description as it might be empty.
|
Shift description, should be added to the shift type description but might be empty.
|
||||||
Normally contains additional information for a specific shift / task.
|
Normally contains additional information for a specific shift / task.
|
||||||
starts_at:
|
starts_at:
|
||||||
type: string
|
type: string
|
||||||
|
@ -206,7 +226,7 @@ components:
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
example: https://example.com/shifts/42
|
example: https://example.com/shifts/42
|
||||||
description: Direct link of the shift
|
description: Direct link to the shift
|
||||||
required:
|
required:
|
||||||
- id
|
- id
|
||||||
- title
|
- title
|
||||||
|
@ -230,9 +250,10 @@ components:
|
||||||
$ref: '#/components/schemas/AngelType'
|
$ref: '#/components/schemas/AngelType'
|
||||||
needs:
|
needs:
|
||||||
type: integer
|
type: integer
|
||||||
description: |
|
description: >
|
||||||
Number of users needed for the shift.
|
Number of users needed for the shift of the given type.
|
||||||
Can be more than users count when not full, less when overbooked or 0 when additional users have been added.
|
Will be more than users count when not full, less when overbooked
|
||||||
|
or 0 when only additional users with given type have been added.
|
||||||
example: 3
|
example: 3
|
||||||
required:
|
required:
|
||||||
- users
|
- users
|
||||||
|
@ -402,3 +423,35 @@ paths:
|
||||||
$ref: '#/components/responses/ForbiddenError'
|
$ref: '#/components/responses/ForbiddenError'
|
||||||
'404':
|
'404':
|
||||||
$ref: '#/components/responses/NotFoundError'
|
$ref: '#/components/responses/NotFoundError'
|
||||||
|
|
||||||
|
/users/{id}/angeltypes:
|
||||||
|
parameters:
|
||||||
|
- name: id
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The user identifier
|
||||||
|
example: 42
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Get the users angel types
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Ok
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/UserAngelType'
|
||||||
|
'401':
|
||||||
|
$ref: '#/components/responses/UnauthorizedError'
|
||||||
|
'403':
|
||||||
|
$ref: '#/components/responses/ForbiddenError'
|
||||||
|
'404':
|
||||||
|
$ref: '#/components/responses/NotFoundError'
|
||||||
|
|
|
@ -4,8 +4,10 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Engelsystem\Controllers\Api;
|
namespace Engelsystem\Controllers\Api;
|
||||||
|
|
||||||
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
|
||||||
class AngelTypeController extends ApiController
|
class AngelTypeController extends ApiController
|
||||||
{
|
{
|
||||||
|
@ -16,11 +18,43 @@ class AngelTypeController extends ApiController
|
||||||
->get(['id', 'name', 'description']);
|
->get(['id', 'name', 'description']);
|
||||||
|
|
||||||
$models->map(function (AngelType $model): void {
|
$models->map(function (AngelType $model): void {
|
||||||
$model->url = $this->url->to('/angeltypes', ['action' => 'view', 'angeltype_id' => $model->id]);
|
$model->url = $this->getUrl($model);
|
||||||
});
|
});
|
||||||
|
|
||||||
$data = ['data' => $models];
|
$data = ['data' => $models];
|
||||||
return $this->response
|
return $this->response
|
||||||
->withContent(json_encode($data));
|
->withContent(json_encode($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ofUser(Request $request): Response
|
||||||
|
{
|
||||||
|
$id = (int) $request->getAttribute('user_id');
|
||||||
|
$model = User::findOrFail($id);
|
||||||
|
|
||||||
|
$models = $model->userAngelTypes()->get([
|
||||||
|
'angel_types.id',
|
||||||
|
'angel_types.name',
|
||||||
|
'angel_types.description',
|
||||||
|
'angel_types.restricted',
|
||||||
|
]);
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
$models->map(function (AngelType $model) use (&$data): void {
|
||||||
|
$model->confirmed = !$model->restricted || $model->pivot->supporter || $model->pivot->confirm_user_id;
|
||||||
|
$model->supporter = $model->pivot->supporter;
|
||||||
|
$model->url = $this->getUrl($model);
|
||||||
|
$modelData = $model->attributesToArray();
|
||||||
|
unset($modelData['restricted']);
|
||||||
|
$data[] = $modelData;
|
||||||
|
});
|
||||||
|
|
||||||
|
$data = ['data' => $data];
|
||||||
|
return $this->response
|
||||||
|
->withContent(json_encode($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getUrl(AngelType $model): string
|
||||||
|
{
|
||||||
|
return $this->url->to('/angeltypes', ['action' => 'view', 'angeltype_id' => $model->id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,17 @@ declare(strict_types=1);
|
||||||
namespace Engelsystem\Test\Unit\Controllers\Api;
|
namespace Engelsystem\Test\Unit\Controllers\Api;
|
||||||
|
|
||||||
use Engelsystem\Controllers\Api\AngelTypeController;
|
use Engelsystem\Controllers\Api\AngelTypeController;
|
||||||
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\Response;
|
use Engelsystem\Http\Response;
|
||||||
use Engelsystem\Models\AngelType;
|
use Engelsystem\Models\AngelType;
|
||||||
|
use Engelsystem\Models\User\User;
|
||||||
|
use Engelsystem\Models\UserAngelType;
|
||||||
|
|
||||||
class AngelTypeControllerTest extends ApiBaseControllerTest
|
class AngelTypeControllerTest extends ApiBaseControllerTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Controllers\Api\AngelTypeController::index
|
* @covers \Engelsystem\Controllers\Api\AngelTypeController::index
|
||||||
|
* @covers \Engelsystem\Controllers\Api\AngelTypeController::getUrl
|
||||||
*/
|
*/
|
||||||
public function testIndex(): void
|
public function testIndex(): void
|
||||||
{
|
{
|
||||||
|
@ -33,4 +37,28 @@ class AngelTypeControllerTest extends ApiBaseControllerTest
|
||||||
return $item['name'] == $items->first()->getAttribute('name');
|
return $item['name'] == $items->first()->getAttribute('name');
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Controllers\Api\AngelTypeController::ofUser
|
||||||
|
*/
|
||||||
|
public function testOfUser(): void
|
||||||
|
{
|
||||||
|
$this->initDatabase();
|
||||||
|
$user = User::factory()->create();
|
||||||
|
$items = UserAngelType::factory(3)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$controller = new AngelTypeController(new Response(), $this->url);
|
||||||
|
|
||||||
|
$response = $controller->ofUser(new Request([], [], ['user_id' => $user->id]));
|
||||||
|
$this->validateApiResponse('/users/{id}/angeltypes', 'get', $response);
|
||||||
|
|
||||||
|
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
|
||||||
|
$this->assertJson($response->getContent());
|
||||||
|
|
||||||
|
$data = json_decode($response->getContent(), true);
|
||||||
|
$this->assertArrayHasKey('data', $data);
|
||||||
|
$this->assertCount(3, $data['data']);
|
||||||
|
$this->assertCount(1, collect($data['data'])->filter(function ($item) use ($items) {
|
||||||
|
return $item['name'] == $items->first()->angelType->name;
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue