Skip to content

Commit

Permalink
feat: Route all event getters through EventProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
kachnitel committed Feb 8, 2020
1 parent 1006eb4 commit b61732b
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 43 deletions.
65 changes: 41 additions & 24 deletions src/API/Controllers/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Doctrine\Common\Collections\Criteria;
use RideTimeServer\API\Filters\EventFilter;
use RideTimeServer\API\Providers\EventProvider;
use Slim\Http\Request;
use Slim\Http\Response;
use RideTimeServer\API\Repositories\EventRepository;
Expand Down Expand Up @@ -47,12 +48,9 @@ public function add(Request $request, Response $response, array $args): Response
*/
public function get(Request $request, Response $response, array $args): Response
{
/** @var Event $event */
$event = $this->getEventRepository()->get($args['id']);

if (!$event->isVisible($request->getAttribute('currentUser'))) {
throw new UserException("Event {$args['id']} is not visible to current user", 403);
}
$provider = new EventProvider($this->getEventRepository());
$provider->setUser($request->getAttribute('currentUser'));
$event = $provider->get($args['id']);

return $response->withJson((object) [
'result' => $event->getDetail(),
Expand All @@ -65,15 +63,20 @@ public function get(Request $request, Response $response, array $args): Response
* @param Response $response
* @param array $args
* @return Response
* @deprecated
*/
public function list(Request $request, Response $response, array $args): Response
{
$result = $this->getEventRepository()
->list($request->getQueryParam('ids'))
->filter(function (Event $event) use ($request) {
return $event->isVisible($request->getAttribute('currentUser'));
})
->getValues();
$filter = new EventFilter($this->getEntityManager());
if (!empty($request->getQueryParam('ids'))) {
$filter->id($request->getQueryParam('ids'));
} else {
$filter->dateStart('1 hour ago');
}

$provider = new EventProvider($this->getEventRepository());
$provider->setUser($request->getAttribute('currentUser'));
$result = $provider->filter($filter->getCriteria())->getValues();

return $response->withJson((object) [
'results' => $this->extractDetails($result)
Expand Down Expand Up @@ -103,12 +106,9 @@ public function filter(Request $request, Response $response, array $args): Respo
$filter = new EventFilter($this->getEntityManager(), $criteria);
$filter->apply($filters);

$result = $this->getEventRepository()
->matching($criteria)
->filter(function (Event $event) use ($request) {
return $event->isVisible($request->getAttribute('currentUser'));
})
->getValues();
$provider = new EventProvider($this->getEventRepository());
$provider->setUser($request->getAttribute('currentUser'));
$result = $provider->filter($criteria)->getValues();

return $response->withJson((object) [
'results' => $this->extractDetails($result)
Expand All @@ -117,8 +117,10 @@ public function filter(Request $request, Response $response, array $args): Respo

public function getInvites(Request $request, Response $response, array $args): Response
{
$user = $request->getAttribute('currentUser');
$result = $user->getEvents(Event::STATUS_INVITED)->getValues();
$result = $this->listOwnEvents(
Event::STATUS_INVITED,
$request->getAttribute('currentUser')
);

return $response->withJson((object) [
'results' => $this->extractDetails($result)
Expand All @@ -127,14 +129,28 @@ public function getInvites(Request $request, Response $response, array $args): R

public function getRequests(Request $request, Response $response, array $args): Response
{
$user = $request->getAttribute('currentUser');
$result = $user->getEvents(Event::STATUS_REQUESTED)->getValues();
$result = $this->listOwnEvents(
Event::STATUS_REQUESTED,
$request->getAttribute('currentUser')
);

return $response->withJson((object) [
'results' => $this->extractDetails($result)
]);
}

protected function listOwnEvents(string $status, User $user): array
{
$ids = $user->getEvents($status)->getValues();

$filter = new EventFilter($this->getEntityManager());
$filter->id($ids);

$provider = new EventProvider($this->getEventRepository());
$provider->setUser($user);
return $provider->filter($filter->getCriteria())->getValues();
}

/**
* TODO: currentUser Must be a member(or other status in the future) to invite
*
Expand Down Expand Up @@ -369,8 +385,9 @@ public function addComment(Request $request, Response $response, array $args): R

public function getComments(Request $request, Response $response, array $args): Response
{
/** @var Event $event */
$event = $this->getEventRepository()->get($args['id']);
$provider = new EventProvider($this->getEventRepository());
$provider->setUser($request->getAttribute('currentUser'));
$event = $provider->get($args['id']);

if (!$event->isVisible($request->getAttribute('currentUser'))) {
throw new UserException("Event {$args['id']} is not visible to current user", 403);
Expand Down
13 changes: 6 additions & 7 deletions src/API/Controllers/LocationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Doctrine\Common\Collections\Criteria;
use RideTimeServer\API\Filters\EventFilter;
use RideTimeServer\API\Filters\TrailforksFilter;
use RideTimeServer\API\Providers\EventProvider;
use RideTimeServer\Entities\Event;
use RideTimeServer\Entities\Location;
use RideTimeServer\Entities\User;
Expand Down Expand Up @@ -67,13 +68,11 @@ protected function getEventsInLocations(array $locations, ?User $currentUser, ar
$filter = new EventFilter($this->getEntityManager());
$filter->apply($filters);

return $this->getEventRepository()
->matching(
$filter->getCriteria()
->andWhere(Criteria::expr()->in('location', $locations))
)
->filter(function (Event $event) use ($currentUser) { return $event->isVisible($currentUser); })
->getValues();
$provider = new EventProvider($this->getEventRepository());
$provider->setUser($currentUser);
return $provider->filter(
$filter->getCriteria()->andWhere(Criteria::expr()->in('location', $locations))
)->getValues();
}

/**
Expand Down
20 changes: 15 additions & 5 deletions src/API/Controllers/UserController.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php
namespace RideTimeServer\API\Controllers;

use RideTimeServer\API\Filters\EventFilter;
use Slim\Http\Request;
use Slim\Http\Response;
use RideTimeServer\Exception\UserException;
use RideTimeServer\API\PictureHandler;
use RideTimeServer\API\Providers\EventProvider;
use RideTimeServer\API\Repositories\UserRepository;
use RideTimeServer\Entities\Event;
use RideTimeServer\Entities\Friendship;
Expand All @@ -26,13 +28,21 @@ public function get(Request $request, Response $response, array $args): Response
{
/** @var User $user */
$user = $this->getUserRepository()->get($args['id']);
$currentUser = $request->getAttribute('currentUser');

$eventProvider = new EventProvider($this->getEventRepository());
$eventProvider->setUser($currentUser);

$eventFilter = new EventFilter($this->getEntityManager());
$eventFilter->id($user->getEvents(Event::STATUS_CONFIRMED)->getValues());

// HACK:
$related = $user->getRelated();
$related->event = $this->extractDetails($user->getEvents(Event::STATUS_CONFIRMED)
->filter(function (Event $event) use ($request) {
return $event->isVisible($request->getAttribute('currentUser'));
})->getValues());
$related->event = $this->extractDetails(
$eventProvider->filter(
$eventFilter->getCriteria()
)->getValues()
);

return $response->withJson((object) [
'result' => $user->getDetail(),
'relatedEntities' => $related
Expand Down
72 changes: 72 additions & 0 deletions src/API/Providers/EventProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
namespace RideTimeServer\API\Providers;

use Doctrine\Common\Collections\Criteria;
use RideTimeServer\API\Repositories\EventRepository;
use RideTimeServer\Entities\User;
use RideTimeServer\Entities\Event;
use RideTimeServer\Exception\RTException;
use RideTimeServer\Exception\UserException;

/**
* TODO:
* + change list in ctrlr to use filter
* - deprecate list route and use new filter in app update
* + change get and filter in ctrlr to use provider
* + use id in ALL relationship lists
* - use provider in ctrlr to fetch related if needed
* + location
* - user (getRelated!)
*/
class EventProvider
{
/**
* @var User
*/
protected $user;

/**
* @var EventRepository
*/
protected $repo;

public function __construct(EventRepository $repo) {
$this->repo = $repo;
}

public function setUser(User $user)
{
$this->user = $user;
}

public function get(int $id)
{
$this->checkUser();

/** @var Event $event */
$event = $this->repo->get($id);
if (!$event->isVisible($this->user)) {
throw new UserException("Event {$id} is not visible to current user", 403);
}

return $event;
}

public function filter(Criteria $criteria)
{
$this->checkUser();

return $this->repo
->matching($criteria)
->filter(function (Event $event) {
return $event->isVisible($this->user);
});
}

protected function checkUser()
{
if (!$this->user) {
throw new RTException('Cannot access events without setting user');
}
}
}
3 changes: 3 additions & 0 deletions src/API/Repositories/EventRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
use RideTimeServer\Entities\Location;
use RideTimeServer\Entities\User;

/**
* MUST NOT be used directly but using EventProvider to ensure security
*/
class EventRepository extends BaseRepository
{
/**
Expand Down
8 changes: 5 additions & 3 deletions src/Entities/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,15 @@ public function setDifficulties($difficulties)
}

/**
* Get one location has many events. This is the inverse side.
* Get events in location.
*
* @return Collection|Event[]
* @return Collection|int[]
*/
public function getEvents(): Collection
{
return $this->events;
return $this->events->map(function (Event $event) {
return $event->getId();
});
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/Entities/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public function removeEvent(\RideTimeServer\Entities\EventMember $membership)
* Get events.
*
* @param string $status
* @return ArrayCollection|Event[]
* @return ArrayCollection|int[]
*/
public function getEvents(string $status)
{
Expand All @@ -208,7 +208,7 @@ public function getEvents(string $status)
};

$map = function (EventMember $em) {
return $em->getEvent();
return $em->getEvent()->getId();
};

return $this->events->filter($filter)->map($map);
Expand Down Expand Up @@ -626,7 +626,7 @@ public function getDetail(): object
'id' => $this->getId(),
'name' => $this->getName(),
'hometown' => $this->getHometown(),
'events' => $this->extractIds($this->getEvents(Event::STATUS_CONFIRMED)->getValues()),
'events' => $this->getEvents(Event::STATUS_CONFIRMED)->getValues(),
'friends' => $this->extractIds($this->getConfirmedFriends()),
'level' => $this->getLevel(),
'bike' => $this->getBike(),
Expand All @@ -640,7 +640,6 @@ public function getDetail(): object
public function getRelated(): object
{
return (object) [
'event' => $this->extractDetails($this->getEvents(Event::STATUS_CONFIRMED)->getValues()),
'user' => $this->extractDetails($this->getConfirmedFriends()),
'location' => $this->extractDetails($this->getLocations()->getValues())
];
Expand Down

0 comments on commit b61732b

Please sign in to comment.