Revert: Revert: User removal support.

This commit is contained in:
Alexey Skobkin 2017-01-18 00:58:53 +03:00
parent 38d0ab50be
commit 76b332155b
11 changed files with 129 additions and 66 deletions

View file

@ -0,0 +1,34 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* User removal support
*/
class Version20170116224555 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE users.users ADD is_removed BOOLEAN DEFAULT FALSE NOT NULL');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE users.users DROP is_removed');
}
}

View file

@ -75,15 +75,9 @@ class ImportUsersCommand extends ContainerAwareCommand
continue; continue;
} }
$createdAt = \DateTime::createFromFormat('Y-m-d_H:i:s', $row[3]); $createdAt = \DateTime::createFromFormat('Y-m-d_H:i:s', $row[3]) ?: new \DateTime();
if (!$createdAt) { $user = new User($row[0], $createdAt, $row[1], $row[2]);
$createdAt = new \DateTime();
}
$user = (new User($row[0], $row[1], $row[2]))
->setCreatedAt($createdAt)
;
if (!$input->getOption('check-only')) { if (!$input->getOption('check-only')) {
$em->persist($user); $em->persist($user);

View file

@ -6,6 +6,7 @@ use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; use Skobkin\Bundle\PointToolsBundle\Entity\Subscription;
use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Skobkin\Bundle\PointToolsBundle\Exception\Api\UserNotFoundException;
use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository; use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository;
use Skobkin\Bundle\PointToolsBundle\Service\SubscriptionsManager; use Skobkin\Bundle\PointToolsBundle\Service\SubscriptionsManager;
use Skobkin\Bundle\PointToolsBundle\Service\Api\UserApi; use Skobkin\Bundle\PointToolsBundle\Service\Api\UserApi;
@ -185,6 +186,11 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
try { try {
$userCurrentSubscribers = $this->api->getUserSubscribersById($user->getId()); $userCurrentSubscribers = $this->api->getUserSubscribersById($user->getId());
} catch (UserNotFoundException $e) {
$this->logger->warning('User not found. Marking as removed', ['login' => $user->getLogin(), 'user_id' => $user->getId()]);
$user->markAsRemoved();
continue;
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error( $this->logger->error(
'Error while getting subscribers. Skipping.', 'Error while getting subscribers. Skipping.',
@ -222,14 +228,16 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
private function getUsersForUpdate(int $appUserId): array private function getUsersForUpdate(int $appUserId): array
{ {
$usersForUpdate = [];
if ($this->input->getOption('all-users')) { if ($this->input->getOption('all-users')) {
$usersForUpdate = $this->userRepo->findAll(); $usersForUpdate = $this->userRepo->findBy(['removed' => false]);
} else { } else {
/** @var User $serviceUser */ /** @var User $serviceUser */
$serviceUser = $this->userRepo->find($appUserId); $serviceUser = $this->userRepo->findActiveUserWithSubscribers($appUserId);
if (!$serviceUser) { if (!$serviceUser) {
$this->logger->info('Service user not found'); $this->logger->critical('Service user not found or marked as removed');
// @todo Retrieving user // @todo Retrieving user
throw new \RuntimeException('Service user not found in the database'); throw new \RuntimeException('Service user not found in the database');
@ -239,6 +247,10 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
try { try {
$usersForUpdate = $this->api->getUserSubscribersById($appUserId); $usersForUpdate = $this->api->getUserSubscribersById($appUserId);
} catch (UserNotFoundException $e) {
$this->logger->critical('Service user deleted or API response is invalid');
throw $e;
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->warning( $this->logger->warning(
'Error while getting service subscribers. Fallback to local list.', 'Error while getting service subscribers. Fallback to local list.',
@ -251,8 +263,6 @@ class UpdateSubscriptionsCommand extends ContainerAwareCommand
] ]
); );
$usersForUpdate = [];
/** @var Subscription $subscription */ /** @var Subscription $subscription */
foreach ((array) $serviceUser->getSubscribers() as $subscription) { foreach ((array) $serviceUser->getSubscribers() as $subscription) {
$usersForUpdate[] = $subscription->getSubscriber(); $usersForUpdate[] = $subscription->getSubscriber();

View file

@ -27,9 +27,7 @@ class LoadUserData extends AbstractFixture implements OrderedFixtureInterface
$userId = 99999; $userId = 99999;
foreach ($this->users as $userData) { foreach ($this->users as $userData) {
$user = (new User($userId--, $userData['login'], $userData['name'])) $user = new User($userId--, new \DateTime(), $userData['login'], $userData['name']);
->setCreatedAt(new \DateTime())
;
$om->persist($user); $om->persist($user);

View file

@ -68,17 +68,25 @@ class User
/** /**
* @var ArrayCollection|SubscriptionEvent[] * @var ArrayCollection|SubscriptionEvent[]
*
* @ORM\OneToMany(targetEntity="SubscriptionEvent", mappedBy="author", fetch="EXTRA_LAZY") * @ORM\OneToMany(targetEntity="SubscriptionEvent", mappedBy="author", fetch="EXTRA_LAZY")
*/ */
private $newSubscriberEvents; private $newSubscriberEvents;
/**
* @var bool
*
* @ORM\Column(name="is_removed", type="boolean", options={"default": false})
*/
private $removed = false;
public function __construct(int $id, string $login = null, string $name = null)
public function __construct(int $id, \DateTime $createdAt = null, string $login = null, string $name = null)
{ {
$this->id = $id; $this->id = $id;
$this->login = $login; $this->login = $login;
$this->name = $name; $this->name = $name;
$this->createdAt = new \DateTime(); $this->createdAt = $createdAt ?: new \DateTime();
$this->subscribers = new ArrayCollection(); $this->subscribers = new ArrayCollection();
$this->subscriptions = new ArrayCollection(); $this->subscriptions = new ArrayCollection();
@ -98,30 +106,25 @@ class User
return $this->id; return $this->id;
} }
public function setLogin(string $login): self
{
$this->login = $login;
return $this;
}
public function getLogin(): string public function getLogin(): string
{ {
return $this->login; return $this->login;
} }
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getName(): ?string public function getName(): ?string
{ {
return $this->name; return $this->name;
} }
public function updateLoginAndName(string $login, ?string $name): self
{
$this->login = $login;
$this->name = $name;
return $this;
}
public function addSubscriber(Subscription $subscribers): self public function addSubscriber(Subscription $subscribers): self
{ {
$this->subscribers[] = $subscribers; $this->subscribers[] = $subscribers;
@ -170,15 +173,18 @@ class User
return $this->createdAt; return $this->createdAt;
} }
public function setCreatedAt(\DateTime $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTime public function getUpdatedAt(): ?\DateTime
{ {
return $this->updatedAt; return $this->updatedAt;
} }
public function isRemoved(): bool
{
return $this->isRemoved();
}
public function markAsRemoved(): void
{
$this->removed = true;
}
} }

View file

@ -13,6 +13,22 @@ class UserRepository extends EntityRepository
$this->getEntityManager()->persist($entity); $this->getEntityManager()->persist($entity);
} }
public function findActiveUserWithSubscribers(int $id): ?User
{
$qb = $this->createQueryBuilder('u');
// May be optimize hydration procedure
return $qb
->select(['u', 's', 'us'])
->innerJoin('u.subscribers', 's')
->innerJoin('s.subscriber', 'us')
->where('u.id = :id')
->where('u.removed = FALSE')
->setParameter('id', $id)
->getQuery()->getOneOrNullResult()
;
}
/** /**
* Case-insensitive user search * Case-insensitive user search
*/ */

View file

@ -51,22 +51,6 @@ class AbstractApi
$this->logger = $logger; $this->logger = $logger;
} }
/**
* Make GET request and return response body
*/
public function getGetResponseBody($path, array $parameters = []): StreamInterface
{
return $this->sendGetRequest($path, $parameters)->getBody();
}
/**
* Make POST request and return response body
*/
public function getPostResponseBody(string $path, array $parameters = []): StreamInterface
{
return $this->sendPostRequest($path, $parameters)->getBody();
}
/** /**
* Make GET request and return DTO objects * Make GET request and return DTO objects
* *
@ -97,6 +81,22 @@ class AbstractApi
); );
} }
/**
* Make GET request and return response body
*/
public function getGetResponseBody($path, array $parameters = []): StreamInterface
{
return $this->sendGetRequest($path, $parameters)->getBody();
}
/**
* Make POST request and return response body
*/
public function getPostResponseBody(string $path, array $parameters = []): StreamInterface
{
return $this->sendPostRequest($path, $parameters)->getBody();
}
/** /**
* @param string $path Request path * @param string $path Request path
* @param array $parameters Key => Value array of query parameters * @param array $parameters Key => Value array of query parameters
@ -151,6 +151,12 @@ class AbstractApi
$code = $response->getStatusCode(); $code = $response->getStatusCode();
$reason = $response->getReasonPhrase(); $reason = $response->getReasonPhrase();
// @todo remove after fix
// Temporary fix until @arts fixes this bug
if ('{"error": "UserNotFound"}' === (string) $response->getBody()) {
throw new NotFoundException($reason, $code);
}
switch ($code) { switch ($code) {
case SymfonyResponse::HTTP_UNAUTHORIZED: case SymfonyResponse::HTTP_UNAUTHORIZED:
throw new UnauthorizedException($reason, $code); throw new UnauthorizedException($reason, $code);

View file

@ -39,16 +39,14 @@ class UserFactory extends AbstractFactory
/** @var User $user */ /** @var User $user */
if (null === ($user = $this->userRepository->find($userData->getId()))) { if (null === ($user = $this->userRepository->find($userData->getId()))) {
// Creating new user $user = new User(
$user = new User($userData->getId()); $userData->getId(),
\DateTime::createFromFormat('Y-m-d_H:i:s', $userData->getCreated()) ?: new \DateTime()
);
$this->userRepository->add($user); $this->userRepository->add($user);
} }
// Updating data $user->updateLoginAndName($userData->getLogin(), $userData->getName());
$user
->setLogin($userData->getLogin())
->setName($userData->getName())
;
return $user; return $user;
} }

View file

@ -52,6 +52,7 @@ class SubscriptionsManager
*/ */
public function updateUserSubscribers(User $user, $newSubscribersList = []): void public function updateUserSubscribers(User $user, $newSubscribersList = []): void
{ {
// @todo optimize
$tmpOldSubscribers = $user->getSubscribers(); $tmpOldSubscribers = $user->getSubscribers();
$oldSubscribersList = []; $oldSubscribersList = [];

View file

@ -14,15 +14,15 @@ class UserSubscribersUpdatedEventTest extends \PHPUnit_Framework_TestCase
public function testCreate() public function testCreate()
{ {
$user = new User(99999, 'testuser', 'Test User 1'); $user = new User(99999, new \DateTime(), 'testuser', 'Test User 1');
$subscribed = [ $subscribed = [
new User(99998, 'testuser2', 'Test User 2'), new User(99998, new \DateTime(), 'testuser2', 'Test User 2'),
]; ];
$unsubscribed = [ $unsubscribed = [
new User(99997, 'testuser3', 'Test User 3'), new User(99997, new \DateTime(), 'testuser3', 'Test User 3'),
new User(99996, 'testuser4', 'Test User 4'), new User(99996, new \DateTime(), 'testuser4', 'Test User 4'),
]; ];
return new UserSubscribersUpdatedEvent($user, $subscribed, $unsubscribed); return new UserSubscribersUpdatedEvent($user, $subscribed, $unsubscribed);

View file

@ -15,7 +15,7 @@ class UsersRenamedEventTest extends \PHPUnit_Framework_TestCase
public function testGetRenames() public function testGetRenames()
{ {
$user = new User(99999, 'testuser', 'Test User 1'); $user = new User(99999, new \DateTime(), 'testuser', 'Test User 1');
$renameRecords = [ $renameRecords = [
new UserRenameEvent($user, 'testuser_old1'), new UserRenameEvent($user, 'testuser_old1'),
new UserRenameEvent($user, 'testuser_old2'), new UserRenameEvent($user, 'testuser_old2'),