Added new my affiliations endpoints

get my affiliations

GET /api/v1/members/me/affiliations

scopes

%s/members/read/me

Add my affiliation

POST /api/v1/members/me/affiliations

scopes

%s/members/write/me

update my affiliation

/api/v1/members/me/affiliations/{affiliation_id}

scopes

%s/members/write/me

delete my affiliation

/api/v1/members/me/affiliations/{affiliation_id}

scopes

%s/members/write/me

Change-Id: I8a6e1bc7c397cc647396a4a7839b54ef29ea517e
This commit is contained in:
Sebastian Marcet 2018-10-16 11:34:55 -03:00
parent c27160fa01
commit 2dcb7c559e
9 changed files with 221 additions and 143 deletions

View File

@ -58,6 +58,9 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
$this->member_service = $member_service;
}
/**
* @return mixed
*/
public function getAll(){
$values = Input::all();
@ -163,6 +166,9 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
}
}
/**
* @return mixed
*/
public function getMyMember(){
$current_member_id = $this->resource_server_context->getCurrentUserExternalId();
@ -187,6 +193,13 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
}
/**
* @return mixed
*/
public function getMyMemberAffiliations(){
return $this->getMemberAffiliations('me');
}
/**
* @param $member_id
* @return mixed
@ -194,7 +207,11 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
public function getMemberAffiliations($member_id){
try {
if(strtolower($member_id) == 'me'){
$member_id = $this->resource_server_context->getCurrentUserExternalId();
}
$member = $this->repository->getById($member_id);
if(is_null($member)) return $this->error404();
$affiliations = $member->getAffiliations()->toArray();
@ -228,20 +245,36 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
}
}
/**
* @return mixed
*/
public function addMyAffiliation(){
return $this->addAffiliation('me');
}
/**
* @param $member_id
* @return mixed
*/
public function addAffiliation($member_id){
try {
if(!Request::isJson()) return $this->error400();
$data = Input::json();
if(strtolower($member_id) == 'me'){
$member_id = $this->resource_server_context->getCurrentUserExternalId();
}
$member = $this->repository->getById($member_id);
if(is_null($member)) return $this->error404();
$rules = [
'is_current' => 'required|boolean',
'start_date' => 'required|date_format:U|valid_epoch',
'end_date' => 'sometimes|after_or_null_epoch:start_date',
'organization_id' => 'required|integer',
'job_title' => 'sometimes|string|max:255'
'is_current' => 'required|boolean',
'start_date' => 'required|date_format:U|valid_epoch',
'end_date' => 'sometimes|after_or_null_epoch:start_date',
'organization_id' => 'sometimes|integer|required_without:organization_name',
'organization_name' => 'sometimes|string|max:255|required_without:organization_id',
'job_title' => 'sometimes|string|max:255'
];
// Creates a Validator instance and validates the data.
@ -278,6 +311,15 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
}
}
/**
* @param $affiliation_id
* @return mixed
*/
public function updateMyAffiliation($affiliation_id){
return $this->updateAffiliation('me', $affiliation_id);
}
/**
* @param int $member_id
* @param int $affiliation_id
@ -288,15 +330,20 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
if(!Request::isJson()) return $this->error400();
$data = Input::json();
if(strtolower($member_id) == 'me'){
$member_id = $this->resource_server_context->getCurrentUserExternalId();
}
$member = $this->repository->getById($member_id);
if(is_null($member)) return $this->error404();
$rules = [
'is_current' => 'sometimes|boolean',
'start_date' => 'sometimes|date_format:U|valid_epoch',
'end_date' => 'sometimes|after_or_null_epoch:start_date',
'organization_id' => 'sometimes|integer',
'job_title' => 'sometimes|string|max:255'
'is_current' => 'sometimes|boolean',
'start_date' => 'sometimes|date_format:U|valid_epoch',
'end_date' => 'sometimes|after_or_null_epoch:start_date',
'organization_id' => 'sometimes|integer',
'organization_name' => 'sometimes|string|max:255',
'job_title' => 'sometimes|string|max:255'
];
// Creates a Validator instance and validates the data.
@ -332,6 +379,11 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
}
}
public function deleteMyAffiliation($affiliation_id){
return $this->deleteAffiliation('me', $affiliation_id);
}
/**
* @param $member_id
* @param $affiliation_id
@ -340,6 +392,10 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController
public function deleteAffiliation($member_id, $affiliation_id){
try{
if(strtolower($member_id) == 'me'){
$member_id = $this->resource_server_context->getCurrentUserExternalId();
}
$member = $this->repository->getById($member_id);
if(is_null($member)) return $this->error404();

View File

@ -30,14 +30,14 @@ Route::group([
Route::group(['prefix'=>'me'], function(){
// get my member info
Route::get('', 'OAuth2MembersApiController@getMyMember');
// invitations
Route::group(['prefix'=>'team-invitations'], function(){
Route::get('', 'OAuth2TeamInvitationsApiController@getMyInvitations');
Route::get('pending', 'OAuth2TeamInvitationsApiController@getMyPendingInvitations');
Route::get('accepted', 'OAuth2TeamInvitationsApiController@getMyAcceptedInvitations');
Route::group(['prefix'=>'{invitation_id}'], function() {
Route::put('', 'OAuth2TeamInvitationsApiController@acceptInvitation');
Route::delete('', 'OAuth2TeamInvitationsApiController@declineInvitation');
// my affiliations
Route::group(['prefix' => 'affiliations'], function(){
Route::get('', [ 'uses' => 'OAuth2MembersApiController@getMyMemberAffiliations']);
Route::post('', [ 'uses' => 'OAuth2MembersApiController@addMyAffiliation']);
Route::group(['prefix' => '{affiliation_id}'], function(){
Route::put('', ['uses' => 'OAuth2MembersApiController@updateMyAffiliation']);
Route::delete('', [ 'uses' => 'OAuth2MembersApiController@deleteMyAffiliation']);
});
});
});

View File

@ -0,0 +1,28 @@
<?php namespace App\Security;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class MemberScopes
* @package App\Security
*/
final class MemberScopes
{
const ReadMemberData = '%s/members/read';
const ReadMyMemberData = '%s/members/read/me';
const WriteMemberData = '%s/members/write';
const WriteMyMemberData = '%s/members/write/me';
}

View File

@ -35,8 +35,6 @@ final class SummitScopes
const WriteAttendeesData = '%s/attendees/write';
const WriteMemberData = '%s/members/write';
const WritePromoCodeData = '%s/promo-codes/write';
const WriteEventTypeData = '%s/event-types/write';

View File

@ -18,6 +18,7 @@ use models\main\Affiliation;
use models\main\IOrganizationRepository;
use models\main\Member;
use DateTime;
use models\main\Organization;
/**
* Class MemberService
* @package App\Services\Model
@ -80,6 +81,17 @@ final class MemberService
$affiliation->setOrganization($org);
}
if(isset($data['organization_name'])) {
$org = $this->organization_repository->getByName(trim($data['organization_name']));
if(is_null($org)){
$org = new Organization();
$org->setName(trim($data['organization_name']));
$this->organization_repository->add($org);
}
$affiliation->setOrganization($org);
}
if(isset($data['job_title'])) {
$affiliation->setJobTitle(trim($data['job_title']));
}
@ -145,6 +157,7 @@ final class MemberService
$end_date = intval($data['end_date']);
$affiliation->setEndDate($end_date > 0 ? new DateTime("@$end_date") : null);
}
if(isset($data['organization_id'])) {
$org = $this->organization_repository->getById(intval($data['organization_id']));
if(is_null($org))
@ -152,6 +165,17 @@ final class MemberService
$affiliation->setOrganization($org);
}
if(isset($data['organization_name'])) {
$org = $this->organization_repository->getByName(trim($data['organization_name']));
if(is_null($org)){
$org = new Organization();
$org->setName(trim($data['organization_name']));
$this->organization_repository->add($org);
}
$affiliation->setOrganization($org);
}
if(isset($data['job_title'])) {
$affiliation->setJobTitle(trim($data['job_title']));
}

View File

@ -17,6 +17,7 @@ use App\Models\ResourceServer\ApiEndpoint;
use LaravelDoctrine\ORM\Facades\EntityManager;
use App\Security\SummitScopes;
use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
/**
* Class ApiEndpointsSeeder
*/
@ -30,7 +31,6 @@ class ApiEndpointsSeeder extends Seeder
$this->seedSummitEndpoints();
$this->seedMemberEndpoints();
$this->seedTeamEndpoints();
$this->seedTagsEndpoints();
$this->seedCompaniesEndpoints();
$this->seedGroupsEndpoints();
@ -1929,6 +1929,38 @@ class ApiEndpointsSeeder extends Seeder
'http_method' => 'GET',
'scopes' => [sprintf('%s/members/read/me', $current_realm)],
],
// my member affiliations
[
'name' => 'get-my-member-affiliations',
'route' => '/api/v1/members/me/affiliations',
'http_method' => 'GET',
'scopes' => [sprintf(MemberScopes::ReadMyMemberData, $current_realm)],
],
[
'name' => 'add-my-member-affiliation',
'route' => '/api/v1/members/me/affiliations',
'http_method' => 'POST',
'scopes' => [
sprintf(MemberScopes::WriteMyMemberData, $current_realm)
],
],
[
'name' => 'update-my-member-affiliation',
'route' => '/api/v1/members/me/affiliations/{affiliation_id}',
'http_method' => 'PUT',
'scopes' => [
sprintf(MemberScopes::WriteMyMemberData, $current_realm)
],
],
[
'name' => 'delete-my-member-affiliation',
'route' => '/api/v1/members/me/affiliations/{affiliation_id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(MemberScopes::WriteMyMemberData, $current_realm)
],
],
// member affiliations
[
'name' => 'get-member-affiliations',
'route' => '/api/v1/members/{member_id}/affiliations',
@ -1940,7 +1972,7 @@ class ApiEndpointsSeeder extends Seeder
'route' => '/api/v1/members/{member_id}/affiliations',
'http_method' => 'POST',
'scopes' => [
sprintf(SummitScopes::WriteMemberData, $current_realm)
sprintf(MemberScopes::WriteMemberData, $current_realm)
],
],
[
@ -1948,7 +1980,7 @@ class ApiEndpointsSeeder extends Seeder
'route' => '/api/v1/members/{member_id}/affiliations/{affiliation_id}',
'http_method' => 'PUT',
'scopes' => [
sprintf(SummitScopes::WriteMemberData, $current_realm)
sprintf(MemberScopes::WriteMemberData, $current_realm)
],
],
[
@ -1956,7 +1988,7 @@ class ApiEndpointsSeeder extends Seeder
'route' => '/api/v1/members/{member_id}/affiliations/{affiliation_id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(SummitScopes::WriteMemberData, $current_realm)
sprintf(MemberScopes::WriteMemberData, $current_realm)
],
],
[
@ -1964,7 +1996,7 @@ class ApiEndpointsSeeder extends Seeder
'route' => '/api/v1/members/{member_id}/rsvp/{rsvp_id}',
'http_method' => 'DELETE',
'scopes' => [
sprintf(SummitScopes::WriteMemberData, $current_realm)
sprintf(MemberScopes::WriteMemberData, $current_realm)
],
]
]
@ -2058,103 +2090,6 @@ class ApiEndpointsSeeder extends Seeder
);
}
private function seedTeamEndpoints(){
$current_realm = Config::get('app.url');
$this->seedApiEndpoints('teams', [
array(
'name' => 'add-team',
'route' => '/api/v1/teams',
'http_method' => 'POST',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
array(
'name' => 'update-team',
'route' => '/api/v1/teams/{team_id}',
'http_method' => 'PUT',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
array(
'name' => 'delete-team',
'route' => '/api/v1/teams/{team_id}',
'http_method' => 'DELETE',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
array(
'name' => 'get-teams',
'route' => '/api/v1/teams',
'http_method' => 'GET',
'scopes' => [sprintf('%s/teams/read', $current_realm)],
),
array(
'name' => 'get-team',
'route' => '/api/v1/teams/{team_id}',
'http_method' => 'GET',
'scopes' => [sprintf('%s/teams/read', $current_realm)],
),
array(
'name' => 'post-message-2-team',
'route' => '/api/v1/teams/{team_id}/messages',
'http_method' => 'POST',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
array(
'name' => 'get-messages-from-team',
'route' => '/api/v1/teams/{team_id}/messages',
'http_method' => 'GET',
'scopes' => [sprintf('%s/teams/read', $current_realm)],
),
array(
'name' => 'add-member-2-team',
'route' => '/api/v1/teams/{team_id}/members/{member_id}',
'http_method' => 'POST',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
array(
'name' => 'remove-member-from-team',
'route' => '/api/v1/teams/{team_id}/members/{member_id}',
'http_method' => 'DELETE',
'scopes' => [sprintf('%s/teams/write', $current_realm)],
),
]
);
$this->seedApiEndpoints('members', [
array(
'name' => 'get-invitations',
'route' => '/api/v1/members/me/team-invitations',
'http_method' => 'GET',
'scopes' => [sprintf('%s/members/invitations/read', $current_realm)],
),
array(
'name' => 'get-pending-invitations',
'route' => '/api/v1/members/me/team-invitations/pending',
'http_method' => 'GET',
'scopes' => [sprintf('%s/members/invitations/read', $current_realm)],
),
array(
'name' => 'get-accepted-invitations',
'route' => '/api/v1/members/me/team-invitations/accepted',
'http_method' => 'GET',
'scopes' => [sprintf('%s/members/invitations/read', $current_realm)],
),
array(
'name' => 'accept-invitation',
'route' => '/api/v1/members/me/team-invitations/{invitation_id}',
'http_method' => 'PUT',
'scopes' => [sprintf('%s/members/invitations/write', $current_realm)],
),
array(
'name' => 'decline-invitation',
'route' => '/api/v1/members/me/team-invitations/{invitation_id}',
'http_method' => 'DELETE',
'scopes' => [sprintf('%s/members/invitations/write', $current_realm)],
),
]
);
}
public function seedTrackQuestionTemplateEndpoints(){
$current_realm = Config::get('app.url');

View File

@ -18,6 +18,7 @@ use LaravelDoctrine\ORM\Facades\EntityManager;
use Illuminate\Support\Facades\DB;
use App\Security\SummitScopes;
use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
/**
* Class ApiScopesSeeder
*/
@ -177,31 +178,26 @@ final class ApiScopesSeeder extends Seeder
$api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'members']);
$scopes = [
array(
'name' => sprintf('%s/members/read', $current_realm),
[
'name' => sprintf(MemberScopes::ReadMemberData, $current_realm),
'short_description' => 'Get Members Data',
'description' => 'Grants read only access for Members Data',
),
array(
'name' => sprintf('%s/members/read/me', $current_realm),
],
[
'name' => sprintf(MemberScopes::ReadMyMemberData, $current_realm),
'short_description' => 'Get My Member Data',
'description' => 'Grants read only access for My Member',
),
array(
'name' => sprintf('%s/members/invitations/read', $current_realm),
'short_description' => 'Allows read only access to invitations',
'description' => 'Allows read only access to invitations',
),
array(
'name' => sprintf('%s/members/invitations/write', $current_realm),
'short_description' => 'Allows write only access to invitations',
'description' => 'Allows write only access to invitations',
),
array(
'name' => sprintf(SummitScopes::WriteMemberData, $current_realm),
],
[
'name' => sprintf(MemberScopes::WriteMemberData, $current_realm),
'short_description' => 'Allows write only access to members',
'description' => 'Allows write only access to memberss',
),
],
[
'name' => sprintf(MemberScopes::WriteMyMemberData, $current_realm),
'short_description' => 'Allows write only access to my Member Data',
'description' => 'Allows write only access to my Member Data',
],
];
foreach ($scopes as $scope_info) {

View File

@ -200,6 +200,45 @@ final class OAuth2MembersApiTest extends ProtectedApiTest
return $affiliation;
}
public function testAddMyMemberAffiliation(){
$params = [
];
$start_datetime = new DateTime( "2018-11-10 00:00:00");
$start_datetime_unix = $start_datetime->getTimestamp();
$data = [
'is_current' => true,
'start_date' => $start_datetime_unix,
'job_title' => 'test affiliation',
'end_date' => null,
'organization_name' => 'test new organization'
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action(
"POST",
"OAuth2MembersApiController@addMyAffiliation",
$params,
[],
[],
[],
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(201);
$affiliation = json_decode($content);
$this->assertTrue(!is_null($affiliation));
return $affiliation;
}
public function testUpdateMemberAffiliation($member_id = 11624){
$new_affiliation = $this->testAddMemberAffiliation($member_id);

View File

@ -17,6 +17,7 @@ use models\oauth2\AccessToken;
use App\Models\ResourceServer\IAccessTokenService;
use App\Security\SummitScopes;
use App\Security\OrganizationScopes;
use App\Security\MemberScopes;
/**
* Class AccessTokenServiceStub
*/
@ -60,7 +61,8 @@ class AccessTokenServiceStub implements IAccessTokenService
sprintf(SummitScopes::WriteSpeakersData, $url),
sprintf(SummitScopes::WriteMySpeakersData, $url),
sprintf(SummitScopes::WriteAttendeesData, $url),
sprintf(SummitScopes::WriteMemberData, $url),
sprintf(MemberScopes::WriteMemberData, $url),
sprintf(MemberScopes::WriteMyMemberData, $url),
sprintf(SummitScopes::WritePromoCodeData, $url),
sprintf(OrganizationScopes::WriteOrganizationData, $url),
sprintf(OrganizationScopes::ReadOrganizationData, $url),
@ -111,7 +113,7 @@ class AccessTokenServiceStub2 implements IAccessTokenService
sprintf(SummitScopes::WriteSpeakersData, $url),
sprintf(SummitScopes::WriteMySpeakersData, $url),
sprintf(SummitScopes::WriteAttendeesData, $url),
sprintf(SummitScopes::WriteMemberData, $url),
sprintf(Mem::WriteMemberData, $url),
sprintf(SummitScopes::WritePromoCodeData, $url),
sprintf(OrganizationScopes::WriteOrganizationData, $url),
sprintf(OrganizationScopes::ReadOrganizationData, $url),