mirror of
https://github.com/wallabag/wallabag.git
synced 2025-06-06 23:48:48 +00:00
Merge pull request #3944 from shtrom/always-hash-exists-url
Always hash exists url
This commit is contained in:
commit
2cbee36a01
5 changed files with 84 additions and 51 deletions
|
@ -14,6 +14,7 @@ use Wallabag\CoreBundle\Entity\Entry;
|
||||||
use Wallabag\CoreBundle\Entity\Tag;
|
use Wallabag\CoreBundle\Entity\Tag;
|
||||||
use Wallabag\CoreBundle\Event\EntryDeletedEvent;
|
use Wallabag\CoreBundle\Event\EntryDeletedEvent;
|
||||||
use Wallabag\CoreBundle\Event\EntrySavedEvent;
|
use Wallabag\CoreBundle\Event\EntrySavedEvent;
|
||||||
|
use Wallabag\CoreBundle\Helper\UrlHasher;
|
||||||
|
|
||||||
class EntryRestController extends WallabagRestController
|
class EntryRestController extends WallabagRestController
|
||||||
{
|
{
|
||||||
|
@ -43,50 +44,45 @@ class EntryRestController extends WallabagRestController
|
||||||
|
|
||||||
$returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id');
|
$returnId = (null === $request->query->get('return_id')) ? false : (bool) $request->query->get('return_id');
|
||||||
|
|
||||||
$urls = $request->query->get('urls', []);
|
|
||||||
$hashedUrls = $request->query->get('hashed_urls', []);
|
$hashedUrls = $request->query->get('hashed_urls', []);
|
||||||
|
|
||||||
// handle multiple urls first
|
|
||||||
if (!empty($hashedUrls)) {
|
|
||||||
$results = [];
|
|
||||||
foreach ($hashedUrls as $hashedUrl) {
|
|
||||||
$res = $repo->findByHashedUrlAndUserId($hashedUrl, $this->getUser()->getId());
|
|
||||||
|
|
||||||
$results[$hashedUrl] = $this->returnExistInformation($res, $returnId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->sendResponse($results);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @deprecated, to be remove in 3.0
|
|
||||||
if (!empty($urls)) {
|
|
||||||
$results = [];
|
|
||||||
foreach ($urls as $url) {
|
|
||||||
$res = $repo->findByUrlAndUserId($url, $this->getUser()->getId());
|
|
||||||
|
|
||||||
$results[$url] = $this->returnExistInformation($res, $returnId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->sendResponse($results);
|
|
||||||
}
|
|
||||||
|
|
||||||
// let's see if it is a simple url?
|
|
||||||
$url = $request->query->get('url', '');
|
|
||||||
$hashedUrl = $request->query->get('hashed_url', '');
|
$hashedUrl = $request->query->get('hashed_url', '');
|
||||||
|
if (!empty($hashedUrl)) {
|
||||||
|
$hashedUrls[] = $hashedUrl;
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($url) && empty($hashedUrl)) {
|
$urls = $request->query->get('urls', []);
|
||||||
|
$url = $request->query->get('url', '');
|
||||||
|
if (!empty($url)) {
|
||||||
|
$urls[] = $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$urlHashMap = [];
|
||||||
|
foreach ($urls as $urlToHash) {
|
||||||
|
$urlHash = UrlHasher::hashUrl($urlToHash);
|
||||||
|
$hashedUrls[] = $urlHash;
|
||||||
|
$urlHashMap[$urlHash] = $urlToHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($hashedUrls)) {
|
||||||
throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId());
|
throw $this->createAccessDeniedException('URL is empty?, logged user id: ' . $this->getUser()->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
$method = 'findByUrlAndUserId';
|
$results = [];
|
||||||
if (!empty($hashedUrl)) {
|
foreach ($hashedUrls as $hashedUrlToSearch) {
|
||||||
$method = 'findByHashedUrlAndUserId';
|
$res = $repo->findByHashedUrlAndUserId($hashedUrlToSearch, $this->getUser()->getId());
|
||||||
$url = $hashedUrl;
|
|
||||||
|
$results[$hashedUrlToSearch] = $this->returnExistInformation($res, $returnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $repo->$method($url, $this->getUser()->getId());
|
$results = $this->replaceUrlHashes($results, $urlHashMap);
|
||||||
|
|
||||||
return $this->sendResponse(['exists' => $this->returnExistInformation($res, $returnId)]);
|
if (!empty($url) || !empty($hashedUrl)) {
|
||||||
|
$hu = array_keys($results)[0];
|
||||||
|
|
||||||
|
return $this->sendResponse(['exists' => $results[$hu]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendResponse($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -804,6 +800,24 @@ class EntryRestController extends WallabagRestController
|
||||||
return $this->sendResponse($results);
|
return $this->sendResponse($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the hashedUrl keys in $results with the unhashed URL from the
|
||||||
|
* request, as recorded in $urlHashMap.
|
||||||
|
*/
|
||||||
|
private function replaceUrlHashes(array $results, array $urlHashMap)
|
||||||
|
{
|
||||||
|
$newResults = [];
|
||||||
|
foreach ($results as $hash => $res) {
|
||||||
|
if (isset($urlHashMap[$hash])) {
|
||||||
|
$newResults[$urlHashMap[$hash]] = $res;
|
||||||
|
} else {
|
||||||
|
$newResults[$hash] = $res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $newResults;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve value from the request.
|
* Retrieve value from the request.
|
||||||
* Used for POST & PATCH on a an entry.
|
* Used for POST & PATCH on a an entry.
|
||||||
|
@ -832,8 +846,8 @@ class EntryRestController extends WallabagRestController
|
||||||
/**
|
/**
|
||||||
* Return information about the entry if it exist and depending on the id or not.
|
* Return information about the entry if it exist and depending on the id or not.
|
||||||
*
|
*
|
||||||
* @param Entry|null $entry
|
* @param Entry|bool|null $entry
|
||||||
* @param bool $returnId
|
* @param bool $returnId
|
||||||
*
|
*
|
||||||
* @return bool|int
|
* @return bool|int
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,6 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Wallabag\CoreBundle\Helper\UrlHasher;
|
||||||
use Wallabag\UserBundle\Entity\User;
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
|
||||||
class GenerateUrlHashesCommand extends ContainerAwareCommand
|
class GenerateUrlHashesCommand extends ContainerAwareCommand
|
||||||
|
@ -65,7 +66,7 @@ class GenerateUrlHashesCommand extends ContainerAwareCommand
|
||||||
|
|
||||||
$i = 1;
|
$i = 1;
|
||||||
foreach ($entries as $entry) {
|
foreach ($entries as $entry) {
|
||||||
$entry->setHashedUrl(hash('sha1', $entry->getUrl()));
|
$entry->setHashedUrl(UrlHasher::hashUrl($entry->getUrl()));
|
||||||
$em->persist($entry);
|
$em->persist($entry);
|
||||||
|
|
||||||
if (0 === ($i % 20)) {
|
if (0 === ($i % 20)) {
|
||||||
|
@ -84,7 +85,7 @@ class GenerateUrlHashesCommand extends ContainerAwareCommand
|
||||||
*
|
*
|
||||||
* @param string $username
|
* @param string $username
|
||||||
*
|
*
|
||||||
* @return \Wallabag\UserBundle\Entity\User
|
* @return User
|
||||||
*/
|
*/
|
||||||
private function getUser($username)
|
private function getUser($username)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,7 @@ use JMS\Serializer\Annotation\XmlRoot;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
use Wallabag\AnnotationBundle\Entity\Annotation;
|
use Wallabag\AnnotationBundle\Entity\Annotation;
|
||||||
use Wallabag\CoreBundle\Helper\EntityTimestampsTrait;
|
use Wallabag\CoreBundle\Helper\EntityTimestampsTrait;
|
||||||
|
use Wallabag\CoreBundle\Helper\UrlHasher;
|
||||||
use Wallabag\UserBundle\Entity\User;
|
use Wallabag\UserBundle\Entity\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -324,7 +325,7 @@ class Entry
|
||||||
public function setUrl($url)
|
public function setUrl($url)
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->hashedUrl = hash('sha1', $url);
|
$this->hashedUrl = UrlHasher::hashUrl($url);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
23
src/Wallabag/CoreBundle/Helper/UrlHasher.php
Normal file
23
src/Wallabag/CoreBundle/Helper/UrlHasher.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Wallabag\CoreBundle\Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash URLs for privacy and performance.
|
||||||
|
*/
|
||||||
|
class UrlHasher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Hash the given url using the given algorithm.
|
||||||
|
* Hashed url are faster to be retrieved in the database than the real url.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string $algorithm
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function hashUrl(string $url, $algorithm = 'sha1')
|
||||||
|
{
|
||||||
|
return hash($algorithm, urldecode($url));
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||||
use Pagerfanta\Pagerfanta;
|
use Pagerfanta\Pagerfanta;
|
||||||
use Wallabag\CoreBundle\Entity\Entry;
|
use Wallabag\CoreBundle\Entity\Entry;
|
||||||
use Wallabag\CoreBundle\Entity\Tag;
|
use Wallabag\CoreBundle\Entity\Tag;
|
||||||
|
use Wallabag\CoreBundle\Helper\UrlHasher;
|
||||||
|
|
||||||
class EntryRepository extends EntityRepository
|
class EntryRepository extends EntityRepository
|
||||||
{
|
{
|
||||||
|
@ -348,17 +349,10 @@ class EntryRepository extends EntityRepository
|
||||||
*/
|
*/
|
||||||
public function findByUrlAndUserId($url, $userId)
|
public function findByUrlAndUserId($url, $userId)
|
||||||
{
|
{
|
||||||
$res = $this->createQueryBuilder('e')
|
return $this->findByHashedUrlAndUserId(
|
||||||
->where('e.url = :url')->setParameter('url', urldecode($url))
|
UrlHasher::hashUrl($url),
|
||||||
->andWhere('e.user = :user_id')->setParameter('user_id', $userId)
|
$userId
|
||||||
->getQuery()
|
);
|
||||||
->getResult();
|
|
||||||
|
|
||||||
if (\count($res)) {
|
|
||||||
return current($res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue