From ff08494edec5d86ffc3bc64d0d8eeaf592a1e7b6 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 13:22:11 +0200 Subject: [PATCH 01/11] Get overview of roles in an organization --- .../Repositories/EloquentRepository.php | 2 +- .../OrganizationRolesController.php | 48 +++++++++++++++++++ app/Models/Organization.php | 15 +++--- app/Models/OrganizationRole.php | 39 +++++++++++++++ .../Repositories/RolesReadRepository.php | 25 ++++++++++ .../OrganizationRoleTransformer.php | 23 +++++++++ ...095958_create_organization_roles_table.php | 32 +++++++++++++ routes/api.php | 5 +- 8 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 app/Http/Controllers/OrganizationRolesController.php create mode 100644 app/Models/OrganizationRole.php create mode 100644 app/Organizations/Repositories/RolesReadRepository.php create mode 100644 app/Organizations/Transformers/OrganizationRoleTransformer.php create mode 100644 database/migrations/2018_05_15_095958_create_organization_roles_table.php diff --git a/app/Entities/Repositories/EloquentRepository.php b/app/Entities/Repositories/EloquentRepository.php index a05ec37f08af..af7ecc4473b7 100644 --- a/app/Entities/Repositories/EloquentRepository.php +++ b/app/Entities/Repositories/EloquentRepository.php @@ -9,7 +9,7 @@ class EloquentRepository /** * @var Model */ - private $items; + protected $items; /** * @param Model $items diff --git a/app/Http/Controllers/OrganizationRolesController.php b/app/Http/Controllers/OrganizationRolesController.php new file mode 100644 index 000000000000..a144416d8c81 --- /dev/null +++ b/app/Http/Controllers/OrganizationRolesController.php @@ -0,0 +1,48 @@ +setTransformer($roleTransformer); + $this->readRepository = $readRepository; + $this->rolesReadRepository = $rolesReadRepository; + } + + /** + * @param string $organizationId + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function all($organizationId) + { + $organization = $this->readRepository->find($organizationId); + $roles = $this->rolesReadRepository->findForOrganization($organization->id); + + return $this->responsePaginator($roles); + } +} diff --git a/app/Models/Organization.php b/app/Models/Organization.php index a45ca0eb7a98..056f53250bb6 100644 --- a/app/Models/Organization.php +++ b/app/Models/Organization.php @@ -15,13 +15,6 @@ class Organization extends Model use SoftDeletes; use UuidModel; - /** - * Table name. - * - * @var string - */ - public $table = 'organizations'; - /** * The attributes that are mass assignable. * @@ -47,4 +40,12 @@ public function users() { return $this->hasMany(User::class); } + + /** + * Get the roles of the organization. + */ + public function roles() + { + return $this->hasMany(OrganizationRole::class); + } } diff --git a/app/Models/OrganizationRole.php b/app/Models/OrganizationRole.php new file mode 100644 index 000000000000..726d0fb429e5 --- /dev/null +++ b/app/Models/OrganizationRole.php @@ -0,0 +1,39 @@ + 'required', + ]; + + /** + * Get the users of the organization. + */ + public function organization() + { + return $this->belongsTo(Organization::class); + } +} diff --git a/app/Organizations/Repositories/RolesReadRepository.php b/app/Organizations/Repositories/RolesReadRepository.php new file mode 100644 index 000000000000..ff95bb80e901 --- /dev/null +++ b/app/Organizations/Repositories/RolesReadRepository.php @@ -0,0 +1,25 @@ +items->where('organization_id', $organizationId)->paginate(); + } +} diff --git a/app/Organizations/Transformers/OrganizationRoleTransformer.php b/app/Organizations/Transformers/OrganizationRoleTransformer.php new file mode 100644 index 000000000000..4e1009760436 --- /dev/null +++ b/app/Organizations/Transformers/OrganizationRoleTransformer.php @@ -0,0 +1,23 @@ + $role->id, + 'name' => $role->name, + 'services' => [], + ]; + } +} diff --git a/database/migrations/2018_05_15_095958_create_organization_roles_table.php b/database/migrations/2018_05_15_095958_create_organization_roles_table.php new file mode 100644 index 000000000000..9b85cf6aedcd --- /dev/null +++ b/database/migrations/2018_05_15_095958_create_organization_roles_table.php @@ -0,0 +1,32 @@ +string('id', 36); + $table->string('organization_id', 36); + $table->string('name'); + $table->timestamps(); + $table->softDeletes(); + $table->primary('id'); + $table->index('organization_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down() + { + Schema::dropIfExists('organization_roles'); + } +} diff --git a/routes/api.php b/routes/api.php index b10cc648632a..541bf4812710 100644 --- a/routes/api.php +++ b/routes/api.php @@ -22,4 +22,7 @@ Route::post('/signin/code', 'oAuth\UserController@authorizeFromCode'); }); -Route::get('/organizations/{organizationId}', 'OrganizationsController@get'); +Route::group(['prefix' => '/organizations/{organizationId}'], function() { + Route::get('/', 'OrganizationsController@get'); + Route::get('/roles', 'OrganizationRolesController@all'); +}); From 78032a69d1ed1e70679f1c86c51bc630b6f8a337 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 13:29:22 +0200 Subject: [PATCH 02/11] Update documentation with pagination --- docs/api-endpoints.yml | 76 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/docs/api-endpoints.yml b/docs/api-endpoints.yml index aeddfd0d9f07..2bdeb9e8a2a9 100644 --- a/docs/api-endpoints.yml +++ b/docs/api-endpoints.yml @@ -410,6 +410,9 @@ paths: description: "ID of the transaction" required: true type: "string" + enum: + - "me" + - "UUID of the organization" responses: 200: description: "" @@ -489,6 +492,13 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" + - name: "page" + in: "query" + description: "" + type: "integer" responses: 200: description: "" @@ -560,6 +570,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "roleId" in: "path" description: "ID of the role" @@ -625,6 +638,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "roleId" in: "query" description: "Filter by role" @@ -743,6 +759,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "userId" in: "path" description: "ID of the user" @@ -882,6 +901,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" responses: 200: description: "" @@ -967,6 +989,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "budgetId" in: "path" description: "ID of the budget" @@ -1045,6 +1070,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "status" in: "query" description: "Filter on status" @@ -1095,6 +1123,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "requestId" in: "path" description: "ID of the subscription request" @@ -1136,6 +1167,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "userId" in: "query" description: "Filter by user ID" @@ -1232,6 +1266,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "subscriptionId" in: "path" description: "ID of the subscription" @@ -1317,6 +1354,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "userId" in: "query" description: "Filter by user ID" @@ -1435,6 +1475,9 @@ paths: description: "ID of the organization" required: true type: "string" + enum: + - "me" + - "UUID of the organization" - name: "transactionId" in: "path" description: "ID of the transaction" @@ -1531,15 +1574,30 @@ definitions: meta: type: object properties: - total: - type: "integer" - example: 321 - perPage: - type: "integer" - example: 10 - page: - type: "integer" - example: 2 + pagination: + type: "object" + properties: + total: + type: "integer" + example: 321 + count: + type: "integer" + example: 15 + per_page: + type: "integer" + example: 10 + current_page: + type: "integer" + example: 2 + total_pages: + type: "integer" + example: 2 + links: + type: "object" + properties: + previous: + type: "string" + example: "http://host/api/organizations/1234/roles?page=1" ErrorResponse: type: "object" properties: From 60be0fa7df076164b9110445284480cca662b0db Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 13:53:36 +0200 Subject: [PATCH 03/11] Update documentation with real error responses --- docs/api-endpoints.yml | 98 ++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/docs/api-endpoints.yml b/docs/api-endpoints.yml index 2bdeb9e8a2a9..ea0d7b73e998 100644 --- a/docs/api-endpoints.yml +++ b/docs/api-endpoints.yml @@ -189,8 +189,10 @@ paths: responses: 200: description: "User updated" - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - usersAuth: [] /users/me/subscriptions: @@ -359,8 +361,10 @@ paths: responses: 200: description: "Transaction updated" - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - usersAuth: [] /organizations: @@ -392,8 +396,10 @@ paths: description: "Organization created" schema: $ref: '#/definitions/Organization' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] /organizations/{id}: @@ -460,6 +466,10 @@ paths: description: "" schema: $ref: '#/definitions/Organization' + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - organizationsAuth: [] - operatorsAuth: [] @@ -549,8 +559,10 @@ paths: description: "Organization role created" schema: $ref: '#/definitions/Role' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -598,8 +610,10 @@ paths: description: "Organization role updated" schema: $ref: '#/definitions/Role' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -740,8 +754,10 @@ paths: description: "Organization user created" schema: $ref: '#/definitions/User' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -861,8 +877,10 @@ paths: description: "Organization user updated" schema: $ref: '#/definitions/User' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -968,8 +986,10 @@ paths: description: "Organization budget created" schema: $ref: '#/definitions/Budget' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -1030,8 +1050,10 @@ paths: description: "Organization budget updated" schema: $ref: '#/definitions/Budget' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -1149,6 +1171,10 @@ paths: description: "" schema: $ref: "#/definitions/SubscriptionRequest" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - organizationsAuth: [] - operatorsAuth: [] @@ -1245,8 +1271,10 @@ paths: description: "Organization subscription created" schema: $ref: '#/definitions/Subscription' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -1314,8 +1342,10 @@ paths: description: "Organization subscription updated" schema: $ref: '#/definitions/Subscription' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -1454,8 +1484,10 @@ paths: description: "Organization transaction created" schema: $ref: '#/definitions/Transaction' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] @@ -1524,8 +1556,10 @@ paths: description: "Organization transaction updated" schema: $ref: '#/definitions/Transaction' - 405: - description: "Validation exception" + 422: + description: "" + schema: + $ref: "#/definitions/ErrorResponse" security: - operatorsAuth: [] - organizationsAuth: [] @@ -1610,8 +1644,16 @@ definitions: type: "object" properties: email: - type: "string" - example: "The selected email is invalid." + type: "array" + items: + type: object + properties: + code: + type: "string" + example: "errors.required" + message: + type: "string" + example: "The selected email is invalid." Subscription: type: "object" required: From 80cfe7e122f1cc2ab15dedf3aaca0826bee5efb8 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 13:56:43 +0200 Subject: [PATCH 04/11] Create a role in an organization --- .../OrganizationRolesController.php | 17 +++++++ .../CreateOrganizationRoleRequest.php | 29 ++++++++++++ .../CreateOrganizationRole.php | 25 +++++++++++ .../Commands/CreateOrganizationRole.php | 44 +++++++++++++++++++ routes/api.php | 1 + 5 files changed, 116 insertions(+) create mode 100644 app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php create mode 100644 app/Organizations/CommandHandlers/CreateOrganizationRole.php create mode 100644 app/Organizations/Commands/CreateOrganizationRole.php diff --git a/app/Http/Controllers/OrganizationRolesController.php b/app/Http/Controllers/OrganizationRolesController.php index a144416d8c81..69065f50a7a1 100644 --- a/app/Http/Controllers/OrganizationRolesController.php +++ b/app/Http/Controllers/OrganizationRolesController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers; +use App\Http\Requests\Organizations\CreateOrganizationRoleRequest; +use App\Organizations\Commands\CreateOrganizationRole; use App\Organizations\Repositories\ReadRepository; use App\Organizations\Repositories\RolesReadRepository; use App\Organizations\Transformers\OrganizationRoleTransformer; @@ -45,4 +47,19 @@ public function all($organizationId) return $this->responsePaginator($roles); } + + /** + * @param CreateOrganizationRoleRequest $request + * @param string $organizationId + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function create(CreateOrganizationRoleRequest $request, $organizationId) + { + $organization = $this->readRepository->find($organizationId); + + $role = $this->dispatch(new CreateOrganizationRole($organization, $request->get('name'))); + + return $this->responseCreated($role); + } } diff --git a/app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php b/app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php new file mode 100644 index 000000000000..05a67403f9d1 --- /dev/null +++ b/app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php @@ -0,0 +1,29 @@ + $command->getName(), + ]); + + $command->getOrganization()->roles()->save($role); + + return $role; + } +} diff --git a/app/Organizations/Commands/CreateOrganizationRole.php b/app/Organizations/Commands/CreateOrganizationRole.php new file mode 100644 index 000000000000..fbac4f9dadf1 --- /dev/null +++ b/app/Organizations/Commands/CreateOrganizationRole.php @@ -0,0 +1,44 @@ +name = $name; + $this->organization = $organization; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return Organization + */ + public function getOrganization() + { + return $this->organization; + } +} diff --git a/routes/api.php b/routes/api.php index 541bf4812710..e11812142305 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,4 +25,5 @@ Route::group(['prefix' => '/organizations/{organizationId}'], function() { Route::get('/', 'OrganizationsController@get'); Route::get('/roles', 'OrganizationRolesController@all'); + Route::post('/roles', 'OrganizationRolesController@create'); }); From 10e55ed940521463bd623b0c7141033d500946a4 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 14:15:36 +0200 Subject: [PATCH 05/11] Update a role in an organization --- .../OrganizationRolesController.php | 24 +++++++- ...equest.php => OrganizationRoleRequest.php} | 2 +- .../UpdateOrganizationRole.php | 23 +++++++ .../Commands/UpdateOrganizationRole.php | 60 +++++++++++++++++++ routes/api.php | 2 + 5 files changed, 107 insertions(+), 4 deletions(-) rename app/Http/Requests/Organizations/{CreateOrganizationRoleRequest.php => OrganizationRoleRequest.php} (89%) create mode 100644 app/Organizations/CommandHandlers/UpdateOrganizationRole.php create mode 100644 app/Organizations/Commands/UpdateOrganizationRole.php diff --git a/app/Http/Controllers/OrganizationRolesController.php b/app/Http/Controllers/OrganizationRolesController.php index 69065f50a7a1..b87172e6be21 100644 --- a/app/Http/Controllers/OrganizationRolesController.php +++ b/app/Http/Controllers/OrganizationRolesController.php @@ -2,8 +2,9 @@ namespace App\Http\Controllers; -use App\Http\Requests\Organizations\CreateOrganizationRoleRequest; +use App\Http\Requests\Organizations\OrganizationRoleRequest; use App\Organizations\Commands\CreateOrganizationRole; +use App\Organizations\Commands\UpdateOrganizationRole; use App\Organizations\Repositories\ReadRepository; use App\Organizations\Repositories\RolesReadRepository; use App\Organizations\Transformers\OrganizationRoleTransformer; @@ -49,12 +50,12 @@ public function all($organizationId) } /** - * @param CreateOrganizationRoleRequest $request + * @param OrganizationRoleRequest $request * @param string $organizationId * * @return \Psr\Http\Message\ResponseInterface */ - public function create(CreateOrganizationRoleRequest $request, $organizationId) + public function create(OrganizationRoleRequest $request, $organizationId) { $organization = $this->readRepository->find($organizationId); @@ -62,4 +63,21 @@ public function create(CreateOrganizationRoleRequest $request, $organizationId) return $this->responseCreated($role); } + + /** + * @param OrganizationRoleRequest $request + * @param string $organizationId + * @param string $roleId + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function update(OrganizationRoleRequest $request, $organizationId, $roleId) + { + $organization = $this->readRepository->find($organizationId); + $role = $this->rolesReadRepository->find($roleId); + + $role = $this->dispatch(new UpdateOrganizationRole($organization, $role, $request->get('name'))); + + return $this->responseItem($role); + } } diff --git a/app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php b/app/Http/Requests/Organizations/OrganizationRoleRequest.php similarity index 89% rename from app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php rename to app/Http/Requests/Organizations/OrganizationRoleRequest.php index 05a67403f9d1..c6a3bb755d56 100644 --- a/app/Http/Requests/Organizations/CreateOrganizationRoleRequest.php +++ b/app/Http/Requests/Organizations/OrganizationRoleRequest.php @@ -5,7 +5,7 @@ use App\Http\Requests\FormRequest; use App\Models\OrganizationRole; -class CreateOrganizationRoleRequest extends FormRequest +class OrganizationRoleRequest extends FormRequest { /** * Determine if the user is authorized to make this request. diff --git a/app/Organizations/CommandHandlers/UpdateOrganizationRole.php b/app/Organizations/CommandHandlers/UpdateOrganizationRole.php new file mode 100644 index 000000000000..cafec2fee336 --- /dev/null +++ b/app/Organizations/CommandHandlers/UpdateOrganizationRole.php @@ -0,0 +1,23 @@ +getRole()->update([ + 'name' => $command->getName(), + ]); + + return $command->getRole(); + } +} diff --git a/app/Organizations/Commands/UpdateOrganizationRole.php b/app/Organizations/Commands/UpdateOrganizationRole.php new file mode 100644 index 000000000000..0cba0817a4e7 --- /dev/null +++ b/app/Organizations/Commands/UpdateOrganizationRole.php @@ -0,0 +1,60 @@ +name = $name; + $this->organization = $organization; + $this->role = $role; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return Organization + */ + public function getOrganization() + { + return $this->organization; + } + + /** + * @return OrganizationRole + */ + public function getRole() + { + return $this->role; + } +} diff --git a/routes/api.php b/routes/api.php index e11812142305..f131f1f0b4a2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -24,6 +24,8 @@ Route::group(['prefix' => '/organizations/{organizationId}'], function() { Route::get('/', 'OrganizationsController@get'); + Route::get('/roles', 'OrganizationRolesController@all'); Route::post('/roles', 'OrganizationRolesController@create'); + Route::put('/roles/{roleId}', 'OrganizationRolesController@update'); }); From 744c811af1f0bedb4d78aad1c3c0b199bc2d7f0d Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 14:20:05 +0200 Subject: [PATCH 06/11] Delete a role in an organization --- .../OrganizationRolesController.php | 17 +++++++ .../DeleteOrganizationRole.php | 16 +++++++ .../Commands/DeleteOrganizationRole.php | 45 +++++++++++++++++++ routes/api.php | 1 + 4 files changed, 79 insertions(+) create mode 100644 app/Organizations/CommandHandlers/DeleteOrganizationRole.php create mode 100644 app/Organizations/Commands/DeleteOrganizationRole.php diff --git a/app/Http/Controllers/OrganizationRolesController.php b/app/Http/Controllers/OrganizationRolesController.php index b87172e6be21..a2bbd8c32d63 100644 --- a/app/Http/Controllers/OrganizationRolesController.php +++ b/app/Http/Controllers/OrganizationRolesController.php @@ -4,6 +4,7 @@ use App\Http\Requests\Organizations\OrganizationRoleRequest; use App\Organizations\Commands\CreateOrganizationRole; +use App\Organizations\Commands\DeleteOrganizationRole; use App\Organizations\Commands\UpdateOrganizationRole; use App\Organizations\Repositories\ReadRepository; use App\Organizations\Repositories\RolesReadRepository; @@ -80,4 +81,20 @@ public function update(OrganizationRoleRequest $request, $organizationId, $roleI return $this->responseItem($role); } + + /** + * @param string $organizationId + * @param string $roleId + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function delete($organizationId, $roleId) + { + $organization = $this->readRepository->find($organizationId); + $role = $this->rolesReadRepository->find($roleId); + + $this->dispatch(new DeleteOrganizationRole($organization, $role)); + + return $this->responseNoContent(); + } } diff --git a/app/Organizations/CommandHandlers/DeleteOrganizationRole.php b/app/Organizations/CommandHandlers/DeleteOrganizationRole.php new file mode 100644 index 000000000000..5cd539abc677 --- /dev/null +++ b/app/Organizations/CommandHandlers/DeleteOrganizationRole.php @@ -0,0 +1,16 @@ +getRole()->delete(); + } +} diff --git a/app/Organizations/Commands/DeleteOrganizationRole.php b/app/Organizations/Commands/DeleteOrganizationRole.php new file mode 100644 index 000000000000..9de84d28b0bb --- /dev/null +++ b/app/Organizations/Commands/DeleteOrganizationRole.php @@ -0,0 +1,45 @@ +organization = $organization; + $this->role = $role; + } + + /** + * @return Organization + */ + public function getOrganization() + { + return $this->organization; + } + + /** + * @return OrganizationRole + */ + public function getRole() + { + return $this->role; + } +} diff --git a/routes/api.php b/routes/api.php index f131f1f0b4a2..b74dd7196c55 100644 --- a/routes/api.php +++ b/routes/api.php @@ -28,4 +28,5 @@ Route::get('/roles', 'OrganizationRolesController@all'); Route::post('/roles', 'OrganizationRolesController@create'); Route::put('/roles/{roleId}', 'OrganizationRolesController@update'); + Route::delete('/roles/{roleId}', 'OrganizationRolesController@delete'); }); From 0cab086d153b4a5a2767e94c62227c943df4d1a8 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 15:06:04 +0200 Subject: [PATCH 07/11] Move roles related code to own namespace --- app/Http/Controllers/OrganizationRolesController.php | 10 +++++----- .../CommandHandlers/CreateOrganizationRole.php | 4 ++-- .../CommandHandlers/DeleteOrganizationRole.php | 4 ++-- .../CommandHandlers/UpdateOrganizationRole.php | 4 ++-- .../{ => Roles}/Commands/CreateOrganizationRole.php | 2 +- .../{ => Roles}/Commands/DeleteOrganizationRole.php | 2 +- .../{ => Roles}/Commands/UpdateOrganizationRole.php | 2 +- .../{ => Roles}/Repositories/RolesReadRepository.php | 2 +- .../Transformers/OrganizationRoleTransformer.php | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) rename app/Organizations/{ => Roles}/CommandHandlers/CreateOrganizationRole.php (76%) rename app/Organizations/{ => Roles}/CommandHandlers/DeleteOrganizationRole.php (60%) rename app/Organizations/{ => Roles}/CommandHandlers/UpdateOrganizationRole.php (73%) rename app/Organizations/{ => Roles}/Commands/CreateOrganizationRole.php (93%) rename app/Organizations/{ => Roles}/Commands/DeleteOrganizationRole.php (94%) rename app/Organizations/{ => Roles}/Commands/UpdateOrganizationRole.php (95%) rename app/Organizations/{ => Roles}/Repositories/RolesReadRepository.php (91%) rename app/Organizations/{ => Roles}/Transformers/OrganizationRoleTransformer.php (89%) diff --git a/app/Http/Controllers/OrganizationRolesController.php b/app/Http/Controllers/OrganizationRolesController.php index a2bbd8c32d63..df3dbff9fe31 100644 --- a/app/Http/Controllers/OrganizationRolesController.php +++ b/app/Http/Controllers/OrganizationRolesController.php @@ -3,12 +3,12 @@ namespace App\Http\Controllers; use App\Http\Requests\Organizations\OrganizationRoleRequest; -use App\Organizations\Commands\CreateOrganizationRole; -use App\Organizations\Commands\DeleteOrganizationRole; -use App\Organizations\Commands\UpdateOrganizationRole; use App\Organizations\Repositories\ReadRepository; -use App\Organizations\Repositories\RolesReadRepository; -use App\Organizations\Transformers\OrganizationRoleTransformer; +use App\Organizations\Roles\Commands\CreateOrganizationRole; +use App\Organizations\Roles\Commands\DeleteOrganizationRole; +use App\Organizations\Roles\Commands\UpdateOrganizationRole; +use App\Organizations\Roles\Repositories\RolesReadRepository; +use App\Organizations\Roles\Transformers\OrganizationRoleTransformer; class OrganizationRolesController extends ApiController { diff --git a/app/Organizations/CommandHandlers/CreateOrganizationRole.php b/app/Organizations/Roles/CommandHandlers/CreateOrganizationRole.php similarity index 76% rename from app/Organizations/CommandHandlers/CreateOrganizationRole.php rename to app/Organizations/Roles/CommandHandlers/CreateOrganizationRole.php index 2062c0c19bbd..a0e4c6d0f13d 100644 --- a/app/Organizations/CommandHandlers/CreateOrganizationRole.php +++ b/app/Organizations/Roles/CommandHandlers/CreateOrganizationRole.php @@ -1,9 +1,9 @@ Date: Tue, 15 May 2018 15:49:36 +0200 Subject: [PATCH 08/11] Add all user fields --- app/Console/Commands/Users/CreateUser.php | 17 +++------ app/User.php | 3 +- app/Users/CommandHandlers/CreateUser.php | 3 +- app/Users/Commands/CreateUser.php | 29 ++++++++++----- .../2018_05_15_132250_add_users_settings.php | 36 +++++++++++++++++++ 5 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 database/migrations/2018_05_15_132250_add_users_settings.php diff --git a/app/Console/Commands/Users/CreateUser.php b/app/Console/Commands/Users/CreateUser.php index 32648c0c5935..2620d0f88996 100644 --- a/app/Console/Commands/Users/CreateUser.php +++ b/app/Console/Commands/Users/CreateUser.php @@ -15,22 +15,14 @@ class CreateUser extends Command * * @var string */ - protected $signature = 'eurides:user:create {name} {email} {organization_id}'; + protected $signature = 'eurides:user:create {first_name} {last_name} {email} {organization_id}'; /** * The console command description. * * @var string */ - protected $description = 'Create a user for an organization. Arguments: {name} {email} {organization_id}'; - - /** - * Create a new command instance. - */ - public function __construct() - { - parent::__construct(); - } + protected $description = 'Create a user for an organization.'; /** * Execute the console command. @@ -39,11 +31,12 @@ public function __construct() */ public function handle() { - $name = $this->argument('name'); + $firstName = $this->argument('first_name'); + $lastName = $this->argument('last_name'); $email = $this->argument('email'); $organizationId = $this->argument('organization_id'); - $user = $this->dispatch(new CreateUserCommand($name, $email, $organizationId)); + $user = $this->dispatch(new CreateUserCommand($firstName, $lastName, $email, $organizationId)); $this->info("User created successfully => ID {$user->id}"); } diff --git a/app/User.php b/app/User.php index 084ae946b7c4..896df1aca6dc 100644 --- a/app/User.php +++ b/app/User.php @@ -20,7 +20,8 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', 'organization_id', + 'first_name', 'last_name', 'email', 'password', 'gender', 'birthdate', 'language', 'address_street', 'address_number', 'address_box', + 'address_city', 'address_postal_code', 'address_country_code', ]; /** diff --git a/app/Users/CommandHandlers/CreateUser.php b/app/Users/CommandHandlers/CreateUser.php index 36b96feb0a1d..8e4d42d0cbc4 100644 --- a/app/Users/CommandHandlers/CreateUser.php +++ b/app/Users/CommandHandlers/CreateUser.php @@ -15,7 +15,8 @@ public function handle(Command $command) } return User::create([ - 'name' => $command->getName(), + 'first_name' => $command->getFirstName(), + 'last_name' => $command->getLastName(), 'email' => $command->getEmail(), 'organization_id' => $command->getOrganizationId(), ]); diff --git a/app/Users/Commands/CreateUser.php b/app/Users/Commands/CreateUser.php index 0a863373825e..77514ba08f1a 100644 --- a/app/Users/Commands/CreateUser.php +++ b/app/Users/Commands/CreateUser.php @@ -7,7 +7,12 @@ class CreateUser /** * @var string */ - protected $name; + protected $firstName; + + /** + * @var string + */ + protected $lastName; /** * @var string @@ -20,15 +25,15 @@ class CreateUser protected $organizationId; /** - * CreateUser constructor. - * - * @param string $name + * @param string $firstName + * @param string $lastName * @param string $email * @param string $organizationId */ - public function __construct(string $name, string $email, string $organizationId) + public function __construct(string $firstName, string $lastName, string $email, string $organizationId) { - $this->name = $name; + $this->firstName = $firstName; + $this->lastName = $lastName; $this->email = $email; $this->organizationId = $organizationId; } @@ -36,9 +41,17 @@ public function __construct(string $name, string $email, string $organizationId) /** * @return string */ - public function getName(): string + public function getFirstName(): string + { + return $this->firstName; + } + + /** + * @return string + */ + public function getLastName(): string { - return $this->name; + return $this->lastName; } /** diff --git a/database/migrations/2018_05_15_132250_add_users_settings.php b/database/migrations/2018_05_15_132250_add_users_settings.php new file mode 100644 index 000000000000..0abc4e1b3aed --- /dev/null +++ b/database/migrations/2018_05_15_132250_add_users_settings.php @@ -0,0 +1,36 @@ +renameColumn('name', 'first_name'); + $table->string('last_name'); + $table->string('language'); + $table->string('gender')->nullable(); + $table->date('birthdate')->nullable(); + $table->string('address_street')->nullable(); + $table->string('address_number')->nullable(); + $table->string('address_box')->nullable(); + $table->string('address_postal_code')->nullable(); + $table->string('address_city')->nullable(); + $table->string('address_country_code')->nullable(); + $table->string('role_id', 36); + }); + } + + /** + * Reverse the migrations. + */ + public function down() + { + } +} From 30b5687d72d97a9f1ab8a4e5ff5bfb028bdb45e0 Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 16:20:05 +0200 Subject: [PATCH 09/11] Add overview of users endpoint --- .../OrganizationUsersController.php | 57 +++++++++++++++++++ app/Models/OrganizationRole.php | 9 +++ app/User.php | 27 ++++++++- .../Queries/FindUsersForOrganizationQuery.php | 37 ++++++++++++ .../Repositories/UsersReadRepository.php | 25 ++++++++ app/Users/Transformers/UserTransformer.php | 52 +++++++++++++++++ routes/api.php | 2 + 7 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/OrganizationUsersController.php create mode 100644 app/Users/Queries/FindUsersForOrganizationQuery.php create mode 100644 app/Users/Repositories/UsersReadRepository.php create mode 100644 app/Users/Transformers/UserTransformer.php diff --git a/app/Http/Controllers/OrganizationUsersController.php b/app/Http/Controllers/OrganizationUsersController.php new file mode 100644 index 000000000000..4d46eb55f8ad --- /dev/null +++ b/app/Http/Controllers/OrganizationUsersController.php @@ -0,0 +1,57 @@ +setTransformer($userTransformer); + $this->organizationsReadRepository = $organizationsReadRepository; + $this->usersReadRepository = $usersReadRepository; + } + + /** + * @param Request $request + * @param string $organizationId + * @param FindUsersForOrganizationQuery $query + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function all(Request $request, $organizationId, FindUsersForOrganizationQuery $query) + { + $organization = $this->organizationsReadRepository->find($organizationId); + + if ($roleId = $request->get('roleId')) { + $query->filterByRoleId($roleId); + } + + $users = $query->find($organization); + + return $this->responsePaginator($users); + } +} diff --git a/app/Models/OrganizationRole.php b/app/Models/OrganizationRole.php index 726d0fb429e5..cbde21d98c16 100644 --- a/app/Models/OrganizationRole.php +++ b/app/Models/OrganizationRole.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Traits\UuidModel; +use App\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -36,4 +37,12 @@ public function organization() { return $this->belongsTo(Organization::class); } + + /** + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function users() + { + return $this->hasMany(User::class); + } } diff --git a/app/User.php b/app/User.php index 896df1aca6dc..0d773105d147 100644 --- a/app/User.php +++ b/app/User.php @@ -3,6 +3,7 @@ namespace App; use App\Models\Organization; +use App\Models\OrganizationRole; use App\Traits\UuidModel; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -20,8 +21,19 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'first_name', 'last_name', 'email', 'password', 'gender', 'birthdate', 'language', 'address_street', 'address_number', 'address_box', - 'address_city', 'address_postal_code', 'address_country_code', + 'first_name', + 'last_name', + 'email', + 'password', + 'gender', + 'birthdate', + 'language', + 'address_street', + 'address_number', + 'address_box', + 'address_city', + 'address_postal_code', + 'address_country_code', ]; /** @@ -30,7 +42,8 @@ class User extends Authenticatable * @var array */ protected $hidden = [ - 'password', 'remember_token', + 'password', + 'remember_token', ]; /** @@ -40,4 +53,12 @@ public function organization() { return $this->belongsTo(Organization::class); } + + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function role() + { + return $this->belongsTo(OrganizationRole::class); + } } diff --git a/app/Users/Queries/FindUsersForOrganizationQuery.php b/app/Users/Queries/FindUsersForOrganizationQuery.php new file mode 100644 index 000000000000..b638ae791b46 --- /dev/null +++ b/app/Users/Queries/FindUsersForOrganizationQuery.php @@ -0,0 +1,37 @@ +items = User::query(); + } + + /** + * @param string $roleId + */ + public function filterByRoleId(string $roleId) + { + $this->items = $this->items->where('role_id', $roleId); + } + + /** + * @param Organization $organization + * + * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator + */ + public function find(Organization $organization) + { + return $this->items->where('organization_id', $organization->id)->paginate(); + } +} diff --git a/app/Users/Repositories/UsersReadRepository.php b/app/Users/Repositories/UsersReadRepository.php new file mode 100644 index 000000000000..066bb3c11539 --- /dev/null +++ b/app/Users/Repositories/UsersReadRepository.php @@ -0,0 +1,25 @@ +items->where('organization_id', $organizationId)->paginate(); + } +} diff --git a/app/Users/Transformers/UserTransformer.php b/app/Users/Transformers/UserTransformer.php new file mode 100644 index 000000000000..5b5a17dba7fe --- /dev/null +++ b/app/Users/Transformers/UserTransformer.php @@ -0,0 +1,52 @@ + $user->id, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, + 'email' => $user->email, + 'language' => $user->language, + 'gender' => $user->gender, + 'birthDate' => $user->birthdate, + 'addressStreet' => $user->address_street, + 'addressNumber' => $user->address_number, + 'addressBox' => $user->address_box, + 'addressPostalCode' => $user->address_postal_code, + 'addressCity' => $user->address_city, + 'addressCountryCode' => $user->address_country_code, + ]; + } + + /** + * @param User $user + * + * @return \League\Fractal\Resource\Item + */ + public function includeRole(User $user) + { + return $this->item($user->role, new OrganizationRoleTransformer()); + } +} diff --git a/routes/api.php b/routes/api.php index b74dd7196c55..1df063b59c7e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -29,4 +29,6 @@ Route::post('/roles', 'OrganizationRolesController@create'); Route::put('/roles/{roleId}', 'OrganizationRolesController@update'); Route::delete('/roles/{roleId}', 'OrganizationRolesController@delete'); + + Route::get('/users', 'OrganizationUsersController@all'); }); From 1c4d5c4c0f76c3828ffbd9fe6b0005382c47978d Mon Sep 17 00:00:00 2001 From: dieterve Date: Tue, 15 May 2018 16:49:08 +0200 Subject: [PATCH 10/11] SQLite does not like adding new fields that aren't nullable --- database/factories/UserFactory.php | 3 ++- .../migrations/2018_05_15_132250_add_users_settings.php | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index facf2337b93e..e7678a2290b7 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -15,7 +15,8 @@ $factory->define(App\User::class, function (Faker $faker) { return [ - 'name' => $faker->name, + 'first_name' => $faker->firstName, + 'last_name' => $faker->lastName, 'email' => $faker->unique()->safeEmail, 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'remember_token' => str_random(10), diff --git a/database/migrations/2018_05_15_132250_add_users_settings.php b/database/migrations/2018_05_15_132250_add_users_settings.php index 0abc4e1b3aed..c368354dcfd3 100644 --- a/database/migrations/2018_05_15_132250_add_users_settings.php +++ b/database/migrations/2018_05_15_132250_add_users_settings.php @@ -12,9 +12,9 @@ class AddUsersSettings extends Migration public function up() { Schema::table('users', function (Blueprint $table) { - $table->renameColumn('name', 'first_name'); - $table->string('last_name'); - $table->string('language'); + $table->renameColumn('name', 'first_name')->nullable(); + $table->string('last_name')->nullable(); + $table->string('language')->nullable(); $table->string('gender')->nullable(); $table->date('birthdate')->nullable(); $table->string('address_street')->nullable(); @@ -23,7 +23,7 @@ public function up() $table->string('address_postal_code')->nullable(); $table->string('address_city')->nullable(); $table->string('address_country_code')->nullable(); - $table->string('role_id', 36); + $table->string('role_id', 36)->nullable(); }); } From 22bdd9b486ad98b8b3ed50eeb3acf9f93c1ca89b Mon Sep 17 00:00:00 2001 From: dieterve Date: Wed, 23 May 2018 15:41:41 +0200 Subject: [PATCH 11/11] Remove unused user method --- app/Users/Repositories/UsersReadRepository.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/Users/Repositories/UsersReadRepository.php b/app/Users/Repositories/UsersReadRepository.php index 066bb3c11539..4186199ecee4 100644 --- a/app/Users/Repositories/UsersReadRepository.php +++ b/app/Users/Repositories/UsersReadRepository.php @@ -14,12 +14,4 @@ public function __construct(User $items) { parent::__construct($items); } - - /** - * @param $organizationId - */ - public function findForOrganization($organizationId) - { - return $this->items->where('organization_id', $organizationId)->paginate(); - } }