Pending/Accepted invitation endpoint

added new endpoint to get pending/accepted
invitations from my member

Change-Id: I6a673a902200dacbd3197487c14e5389e5ef14be
This commit is contained in:
Sebastian Marcet 2017-01-18 14:47:58 -03:00
parent b364505b55
commit add88d3440
10 changed files with 226 additions and 12 deletions

View File

@ -1,6 +1,6 @@
<?php namespace App\Http\Controllers; <?php namespace App\Http\Controllers;
/** /**
* Copyright 2016 OpenStack Foundation * Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -49,6 +49,9 @@ final class OAuth2TeamInvitationsApiController extends OAuth2ProtectedController
$this->service = $service; $this->service = $service;
} }
/**
* @return mixed
*/
public function getMyInvitations(){ public function getMyInvitations(){
try { try {
@ -83,6 +86,80 @@ final class OAuth2TeamInvitationsApiController extends OAuth2ProtectedController
} }
} }
/**
* @return mixed
*/
public function getMyPendingInvitations(){
try {
$current_member_id = $this->resource_server_context->getCurrentUserExternalId();
if (is_null($current_member_id)) return $this->error403();
$invitations = $this->repository->getPendingInvitationsByInvitee($current_member_id);
$response = new PagingResponse
(
count($invitations),
count($invitations),
1,
1,
$invitations
);
return $this->ok($response->toArray($expand = Input::get('expand','')));
}
catch (ValidationException $ex1) {
Log::warning($ex1);
return $this->error412(array($ex1->getMessage()));
}
catch(EntityNotFoundException $ex2)
{
Log::warning($ex2);
return $this->error404(array('message'=> $ex2->getMessage()));
}
catch (\Exception $ex) {
Log::error($ex);
return $this->error500($ex);
}
}
/**
* @return mixed
*/
public function getMyAcceptedInvitations(){
try {
$current_member_id = $this->resource_server_context->getCurrentUserExternalId();
if (is_null($current_member_id)) return $this->error403();
$invitations = $this->repository->getAcceptedInvitationsByInvitee($current_member_id);
$response = new PagingResponse
(
count($invitations),
count($invitations),
1,
1,
$invitations
);
return $this->ok($response->toArray($expand = Input::get('expand','')));
}
catch (ValidationException $ex1) {
Log::warning($ex1);
return $this->error412(array($ex1->getMessage()));
}
catch(EntityNotFoundException $ex2)
{
Log::warning($ex2);
return $this->error404(array('message'=> $ex2->getMessage()));
}
catch (\Exception $ex) {
Log::error($ex);
return $this->error500($ex);
}
}
/** /**
* @param $invitation_id * @param $invitation_id
* @return mixed * @return mixed

View File

@ -53,6 +53,8 @@ Route::group(array(
// invitations // invitations
Route::group(['prefix'=>'team-invitations'], function(){ Route::group(['prefix'=>'team-invitations'], function(){
Route::get('', 'OAuth2TeamInvitationsApiController@getMyInvitations'); Route::get('', 'OAuth2TeamInvitationsApiController@getMyInvitations');
Route::get('pending', 'OAuth2TeamInvitationsApiController@getMyPendingInvitations');
Route::get('accepted', 'OAuth2TeamInvitationsApiController@getMyAcceptedInvitations');
Route::group(['prefix'=>'{invitation_id}'], function() { Route::group(['prefix'=>'{invitation_id}'], function() {
Route::put('', 'OAuth2TeamInvitationsApiController@acceptInvitation'); Route::put('', 'OAuth2TeamInvitationsApiController@acceptInvitation');
Route::delete('', 'OAuth2TeamInvitationsApiController@declineInvitation'); Route::delete('', 'OAuth2TeamInvitationsApiController@declineInvitation');

View File

@ -258,6 +258,18 @@ class ChatTeam extends SilverstripeBaseModel
return $this->getOwnerId() == $member->getId(); return $this->getOwnerId() == $member->getId();
} }
/**
* @param Member $member
* @return bool
*/
public function isAlreadyInvited(Member $member){
$res = $this->invitations->filter(function ($i) use($member){
return $i->getInvitee()->getId() == $member->getId() && $i->isPending();
});
return $res->count() > 0;
}
/** /**
* @param Member $member * @param Member $member
* @return bool * @return bool
@ -276,10 +288,19 @@ class ChatTeam extends SilverstripeBaseModel
$res = $this->members->filter(function ($e) use($member){ $res = $this->members->filter(function ($e) use($member){
return $e->getMember()->getId() == $member->getId(); return $e->getMember()->getId() == $member->getId();
}); });
if($res->count() == 0) return;
if($res->count() == 0) return;
// remove member
$team_member = $res->first(); $team_member = $res->first();
$this->members->removeElement($team_member); $this->members->removeElement($team_member);
$res2 = $this->invitations->filter(function ($i) use($member){
return $i->getInvitee()->getId() == $member->getId();
});
// remove invitation
if($res2->count() > 0) {
$this->invitations->removeElement($res2->first());
}
$team_member->setTeam(null); $team_member->setTeam(null);
} }
} }

View File

@ -164,6 +164,13 @@ class ChatTeamInvitation extends SilverstripeBaseModel
return $this->getIsAccepted(); return $this->getIsAccepted();
} }
/**
* @return bool
*/
public function isPending(){
return !$this->getIsAccepted();
}
public function accept() public function accept()
{ {
$this->is_accepted = true; $this->is_accepted = true;

View File

@ -23,4 +23,8 @@ interface IChatTeamInvitationRepository extends IBaseRepository
* @return ChatTeamInvitation[] * @return ChatTeamInvitation[]
*/ */
function getInvitationsByInvitee($invitee_id); function getInvitationsByInvitee($invitee_id);
function getPendingInvitationsByInvitee($invitee_id);
function getAcceptedInvitationsByInvitee($invitee_id);
} }

View File

@ -37,4 +37,34 @@ final class DoctrineChatTeamInvitationRepository
->innerJoin('i.invitee', 'm', Join::WITH, " m.id = :member_id") ->innerJoin('i.invitee', 'm', Join::WITH, " m.id = :member_id")
->setParameter('member_id', $invitee_id)->getQuery()->getResult(); ->setParameter('member_id', $invitee_id)->getQuery()->getResult();
} }
/**
* @param int $invitee_id
* @return ChatTeamInvitation[]
*/
function getPendingInvitationsByInvitee($invitee_id)
{
return $this->getEntityManager()
->createQueryBuilder()
->select("i")
->from(\models\main\ChatTeamInvitation::class, "i")
->innerJoin('i.invitee', 'm', Join::WITH, " m.id = :member_id")
->where('i.is_accepted = false')
->setParameter('member_id', $invitee_id)->getQuery()->getResult();
}
/**
* @param int $invitee_id
* @return ChatTeamInvitation[]
*/
function getAcceptedInvitationsByInvitee($invitee_id)
{
return $this->getEntityManager()
->createQueryBuilder()
->select("i")
->from(\models\main\ChatTeamInvitation::class, "i")
->innerJoin('i.invitee', 'm', Join::WITH, " m.id = :member_id")
->where('i.is_accepted = true')
->setParameter('member_id', $invitee_id)->getQuery()->getResult();
}
} }

View File

@ -45,7 +45,7 @@ final class DoctrineChatTeamRepository extends SilverStripeDoctrineRepository im
{ {
$result = $this $result = $this
->getEntityManager() ->getEntityManager()
->createQuery("select t.id from \models\main\ChatTeam t join t.messages m where exists (select m2.id from \models\main\ChatTeamPushNotificationMessage m2 where m2.id = m.id and m2.is_sent = 0 )") ->createQuery("select distinct t.id from \models\main\ChatTeam t join t.messages m where exists (select m2.id from \models\main\ChatTeamPushNotificationMessage m2 where m2.id = m.id and m2.is_sent = 0 )")
->getScalarResult(); ->getScalarResult();
$ids = array_map('current', $result); $ids = array_map('current', $result);
return $ids; return $ids;

View File

@ -1,6 +1,6 @@
<?php namespace services\model; <?php namespace services\model;
/** /**
* Copyright 2016 OpenStack Foundation * Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -172,6 +172,7 @@ final class ChatTeamService implements IChatTeamService
function addMember2Team($team_id, $invitee_id, $permission = ChatTeamPermission::Read) function addMember2Team($team_id, $invitee_id, $permission = ChatTeamPermission::Read)
{ {
return $this->tx_service->transaction(function() use($team_id, $invitee_id, $permission){ return $this->tx_service->transaction(function() use($team_id, $invitee_id, $permission){
$team = $this->repository->getById($team_id); $team = $this->repository->getById($team_id);
if(is_null($team)) throw new EntityNotFoundException(); if(is_null($team)) throw new EntityNotFoundException();
@ -182,15 +183,16 @@ final class ChatTeamService implements IChatTeamService
if (is_null($inviter)) throw new EntityNotFoundException(); if (is_null($inviter)) throw new EntityNotFoundException();
$invitee = $this->member_repository->getById($invitee_id); $invitee = $this->member_repository->getById($invitee_id);
if(is_null($invitee)) if(is_null($invitee)) throw new EntityNotFoundException();
throw new EntityNotFoundException();
if(!$team->isAdmin($inviter)) if(!$team->isAdmin($inviter)) throw new EntityNotFoundException();
throw new EntityNotFoundException();
if($team->isMember($invitee)) if($team->isMember($invitee))
throw new ValidationException(sprintf('member id %s already is a member of team id %s', $invitee_id, $team_id)); throw new ValidationException(sprintf('member id %s already is a member of team id %s', $invitee_id, $team_id));
if($team->isAlreadyInvited($invitee))
throw new ValidationException(sprintf('member id %s has a pending invitation on team id %s', $invitee_id, $team_id));
$invitation = $team->createInvitation($inviter, $invitee, $permission); $invitation = $team->createInvitation($inviter, $invitee, $permission);
$team->addInvitation($invitation); $team->addInvitation($invitation);
@ -343,17 +345,21 @@ final class ChatTeamService implements IChatTeamService
function sendMessages($batch_size = 1000) function sendMessages($batch_size = 1000)
{ {
return $this->tx_service->transaction(function() use($batch_size){ return $this->tx_service->transaction(function() use($batch_size){
echo(sprintf('calling ChatTeamService.sendMessages(%s)', $batch_size)).PHP_EOL;
$teams_ids = $this->repository->getAllTeamsIdsWithPendingMessages2Sent(); $teams_ids = $this->repository->getAllTeamsIdsWithPendingMessages2Sent();
$qty = 0; $qty = 0;
foreach($teams_ids as $team_id) { foreach($teams_ids as $team_id) {
echo(sprintf('processing messages for team id %s', $team_id)).PHP_EOL;
$messages = $this->chat_message_repository->getAllNotSentByTeamPaginated $messages = $this->chat_message_repository->getAllNotSentByTeamPaginated
( (
$team_id, $team_id,
new PagingInfo(1, $batch_size) new PagingInfo(1, $batch_size)
); );
echo(sprintf('found %s messages for team id %s, send them...', $team_id, $messages->getTotal())).PHP_EOL;
$team_messages_counter = 0;
foreach ($messages->getItems() as $message){ foreach ($messages->getItems() as $message){
$data = [ $data = [
@ -369,7 +375,10 @@ final class ChatTeamService implements IChatTeamService
$this->push_sender_service->sendPush([sprintf('team_%s', $team_id)], $data); $this->push_sender_service->sendPush([sprintf('team_%s', $team_id)], $data);
$message->markSent(); $message->markSent();
++$qty; ++$qty;
++$team_messages_counter;
} }
echo(sprintf('sent %s messages for team id %s', $team_messages_counter, $team_id)).PHP_EOL;
} }
return $qty; return $qty;
}); });

View File

@ -552,6 +552,18 @@ class ApiEndpointsSeeder extends Seeder
'http_method' => 'GET', 'http_method' => 'GET',
'scopes' => [sprintf('%s/members/invitations/read', $current_realm)], '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( array(
'name' => 'accept-invitation', 'name' => 'accept-invitation',
'route' => '/api/v1/members/me/team-invitations/{invitation_id}', 'route' => '/api/v1/members/me/team-invitations/{invitation_id}',

View File

@ -329,9 +329,61 @@ final class OAuth2ChatTeamApiTest extends ProtectedApiTest
); );
$content = $response->getContent(); $content = $response->getContent();
$messages = json_decode($content); $invitations = json_decode($content);
$this->assertTrue(!is_null($messages)); $this->assertTrue(!is_null($invitations));
$this->assertResponseStatus(200); $this->assertResponseStatus(200);
return $messages; return $invitations;
}
public function testGetMyPendingInvitations(){
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
];
$params = [
];
$response = $this->action(
"GET",
"OAuth2TeamInvitationsApiController@getMyPendingInvitations",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$invitations = json_decode($content);
$this->assertTrue(!is_null($invitations));
$this->assertResponseStatus(200);
return $invitations;
}
public function testGetMyAcceptedInvitations(){
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
];
$params = [
];
$response = $this->action(
"GET",
"OAuth2TeamInvitationsApiController@getMyAcceptedInvitations",
$params,
array(),
array(),
array(),
$headers
);
$content = $response->getContent();
$invitations = json_decode($content);
$this->assertTrue(!is_null($invitations));
$this->assertResponseStatus(200);
return $invitations;
} }
} }