From 365b71b5bfd433d2e09a2c6e144afc45130d1b22 Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sat, 13 Aug 2022 03:34:05 +0000 Subject: [PATCH] Add some things --- appinfo/routes.php | 14 +- css/style.css | 18 +++ js/script.js | 11 ++ lib/Command/Index.php | 4 +- lib/Controller/ApiController.php | 150 ++++++++++++++++++ lib/Controller/PageController.php | 8 +- lib/{ => Db}/Util.php | 58 ++++++- lib/Listeners/PostDeleteListener.php | 4 +- lib/Listeners/PostWriteListener.php | 4 +- .../Version000000Date20220812163631.php | 2 +- templates/content/index.php | 4 +- templates/index.php | 4 +- templates/navigation/index.php | 9 +- 13 files changed, 249 insertions(+), 41 deletions(-) create mode 100644 lib/Controller/ApiController.php rename lib/{ => Db}/Util.php (57%) diff --git a/appinfo/routes.php b/appinfo/routes.php index 0afaea37..c10bfe63 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,15 +1,11 @@ OCA\BetterPhotos\Controller\PageController->index() - * - * The controller class has to be registered in the application.php file since - * it's instantiated in there - */ return [ 'routes' => [ ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], - ['name' => 'page#do_echo', 'url' => '/echo', 'verb' => 'POST'], + + // API + ['name' => 'api#list', 'url' => '/api/list', 'verb' => 'GET'], + ['name' => 'api#listafter', 'url' => '/api/list/after/{time}', 'verb' => 'GET'], + ['name' => 'api#listbefore', 'url' => '/api/list/before/{time}', 'verb' => 'GET'], ] ]; diff --git a/css/style.css b/css/style.css index ce350c6a..40b332c4 100644 --- a/css/style.css +++ b/css/style.css @@ -1,3 +1,21 @@ #hello { color: red; } + +#photos { + width: 100%; + height: 100%; + overflow: auto; + display: grid; + grid-template-columns: auto auto auto auto auto auto; + column-gap: 3px; + row-gap: 3px; +} + +img.photo { + height: 100%; + width: 100%; + margin: 0 0; + object-fit: cover; + display: inline-block; +} \ No newline at end of file diff --git a/js/script.js b/js/script.js index e69de29b..bebe5881 100644 --- a/js/script.js +++ b/js/script.js @@ -0,0 +1,11 @@ +(async () => { + const res = await fetch('/apps/betterphotos/api/list'); + const data = await res.json(); + for (const p of data) { + const img = document.createElement('img'); + img.classList = 'photo'; + img.src = `/core/preview?fileId=${p.file_id}&x=250&y=250`; + document.getElementById('photos').appendChild(img); + } +})(); + diff --git a/lib/Command/Index.php b/lib/Command/Index.php index 47600963..3b5fd951 100644 --- a/lib/Command/Index.php +++ b/lib/Command/Index.php @@ -60,7 +60,7 @@ class Index extends Command { protected OutputInterface $output; protected IManager $encryptionManager; protected IDBConnection $connection; - protected \OCA\BetterPhotos\Util $util; + protected \OCA\BetterPhotos\Db\Util $util; public function __construct(IRootFolder $rootFolder, IUserManager $userManager, @@ -77,7 +77,7 @@ class Index extends Command { $this->config = $config; $this->encryptionManager = $encryptionManager; $this->connection = $connection; - $this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); + $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection); try { $this->globalService = $container->get(GlobalStoragesService::class); diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php new file mode 100644 index 00000000..3fde1ec1 --- /dev/null +++ b/lib/Controller/ApiController.php @@ -0,0 +1,150 @@ + + * + * @author John Molakvoæ + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\BetterPhotos\Controller; + +use OCA\BetterPhotos\AppInfo\Application; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\StreamResponse; +use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IRequest; +use OCP\IUserSession; + +class ApiController extends Controller { + private IConfig $config; + private IUserSession $userSession; + private IDBConnection $connection; + + public function __construct( + IRequest $request, + IConfig $config, + IUserSession $userSession, + IDBConnection $connection + ) { + parent::__construct(Application::APPNAME, $request); + + $this->config = $config; + $this->userSession = $userSession; + $this->connection = $connection; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function list(): JSONResponse { + $user = $this->userSession->getUser(); + if (is_null($user)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + + $list = \OCA\BetterPhotos\Db\Util::getList($this->connection, $user->getUID()); + return new JSONResponse($list, Http::STATUS_OK); + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function listafter(string $time): JSONResponse { + $user = $this->userSession->getUser(); + if (is_null($user)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + + if (!is_numeric($time)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + + $list = \OCA\BetterPhotos\Db\Util::getAfter($this->connection, $user->getUID(), intval($time)); + return new JSONResponse($list, Http::STATUS_OK); + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function listbefore(string $time): JSONResponse { + $user = $this->userSession->getUser(); + if (is_null($user)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + if (!is_numeric($time)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + $list = \OCA\BetterPhotos\Db\Util::getBefore($this->connection, $user->getUID(), intval($time)); + return new JSONResponse($list, Http::STATUS_OK); + } + + + /** + * @NoAdminRequired + * + * update preferences (user setting) + * + * @param string key the identifier to change + * @param string value the value to set + * + * @return JSONResponse an empty JSONResponse with respective http status code + */ + public function setUserConfig(string $key, string $value): JSONResponse { + $user = $this->userSession->getUser(); + if (is_null($user)) { + return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + } + + $userId = $user->getUid(); + $this->config->setUserValue($userId, Application::APPNAME, $key, $value); + return new JSONResponse([], Http::STATUS_OK); + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function serviceWorker(): StreamResponse { + $response = new StreamResponse(__DIR__.'/../../js/photos-service-worker.js'); + $response->setHeaders([ + 'Content-Type' => 'application/javascript', + 'Service-Worker-Allowed' => '/' + ]); + $policy = new ContentSecurityPolicy(); + $policy->addAllowedWorkerSrcDomain("'self'"); + $policy->addAllowedScriptDomain("'self'"); + $policy->addAllowedConnectDomain("'self'"); + $response->setContentSecurityPolicy($policy); + return $response; + } +} \ No newline at end of file diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 3f44104c..9a20c0e9 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -15,17 +15,11 @@ class PageController extends Controller { } /** - * CAUTION: the @Stuff turns off security checks; for this page no admin is - * required and no CSRF check. If you don't know what CSRF is, read - * it up in the docs or you might create a security hole. This is - * basically the only required method to add this exemption, don't - * add it to any other method if you don't exactly know what it does - * * @NoAdminRequired * @NoCSRFRequired */ public function index() { - return new TemplateResponse('betterphotos', 'index'); // templates/index.php + return new TemplateResponse('betterphotos', 'index'); } } diff --git a/lib/Util.php b/lib/Db/Util.php similarity index 57% rename from lib/Util.php rename to lib/Db/Util.php index f8990a6f..78a4c90c 100644 --- a/lib/Util.php +++ b/lib/Db/Util.php @@ -1,7 +1,7 @@ getMtime(); } - - $dateTakenDT = new \DateTime(); - $dateTakenDT->setTimestamp($dateTaken); - return $dateTakenDT; + return $dateTaken; } public function processFile(string $user, File $file, bool $update): void { @@ -52,7 +49,7 @@ class Util { if ($update) { $qb = $this->connection->getQueryBuilder(); $qb->update('betterphotos') - ->set('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_DATE)) + ->set('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_INT)) ->where($qb->expr()->eq('id', $qb->createNamedParameter($row['id']))); $qb->executeStatement(); } @@ -63,7 +60,7 @@ class Util { $qb->insert('betterphotos') ->setValue('user_id', $qb->createNamedParameter($user)) ->setValue('file_id', $qb->createNamedParameter($file->getId())) - ->setValue('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_DATE)); + ->setValue('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_INT)); $qb->executeStatement(); } @@ -73,4 +70,51 @@ class Util { ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($file->getId()))); $qb->executeStatement(); } + + private static function getListQuery( + IDBConnection $connection, + string $user, + ) { + $qb = $connection->getQueryBuilder(); + $qb->select('file_id', 'date_taken') + ->from('betterphotos') + ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user))) + ->orderBy('date_taken', 'DESC') + ->setMaxResults(100); + return $qb; + } + + public static function getList( + IDBConnection $connection, + string $user, + ): array { + $qb = self::getListQuery($connection, $user); + $result = $qb->executeQuery(); + $rows = $result->fetchAll(); + return $rows; + } + + public static function getAfter( + IDBConnection $connection, + string $user, + int $time, + ): array { + $qb = self::getListQuery($connection, $user); + $qb->andWhere($qb->expr()->gte('date_taken', $qb->createNamedParameter($time, IQueryBuilder::PARAM_INT))); + $result = $qb->executeQuery(); + $rows = $result->fetchAll(); + return $rows; + } + + public static function getBefore( + IDBConnection $connection, + string $user, + int $time, + ): array { + $qb = self::getListQuery($connection, $user); + $qb->andWhere($qb->expr()->lte('date_taken', $qb->createNamedParameter($time, IQueryBuilder::PARAM_INT))); + $result = $qb->executeQuery(); + $rows = $result->fetchAll(); + return $rows; + } } \ No newline at end of file diff --git a/lib/Listeners/PostDeleteListener.php b/lib/Listeners/PostDeleteListener.php index 9237fcc7..57c8ba5b 100644 --- a/lib/Listeners/PostDeleteListener.php +++ b/lib/Listeners/PostDeleteListener.php @@ -31,11 +31,11 @@ use OCP\IPreview; use OCP\IDBConnection; class PostDeleteListener implements IEventListener { - private \OCA\BetterPhotos\Util $util; + private \OCA\BetterPhotos\Db\Util $util; public function __construct(IDBConnection $connection, IPreview $previewGenerator) { - $this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); + $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection); } public function handle(Event $event): void { diff --git a/lib/Listeners/PostWriteListener.php b/lib/Listeners/PostWriteListener.php index 11f7aa9a..e857c4db 100644 --- a/lib/Listeners/PostWriteListener.php +++ b/lib/Listeners/PostWriteListener.php @@ -34,13 +34,13 @@ use OCP\IUserManager; class PostWriteListener implements IEventListener { private IUserManager $userManager; - private \OCA\BetterPhotos\Util $util; + private \OCA\BetterPhotos\Db\Util $util; public function __construct(IDBConnection $connection, IUserManager $userManager, IPreview $previewGenerator) { $this->userManager = $userManager; - $this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); + $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection); } public function handle(Event $event): void { diff --git a/lib/Migration/Version000000Date20220812163631.php b/lib/Migration/Version000000Date20220812163631.php index 60cc6847..d524e1db 100644 --- a/lib/Migration/Version000000Date20220812163631.php +++ b/lib/Migration/Version000000Date20220812163631.php @@ -30,7 +30,7 @@ 'notnull' => true, 'length' => 200, ]); - $table->addColumn('date_taken', Types::DATETIME, [ + $table->addColumn('date_taken', Types::INTEGER, [ 'notnull' => false, ]); $table->addColumn('file_id', Types::BIGINT, [ diff --git a/templates/content/index.php b/templates/content/index.php index 159202e8..4709545e 100644 --- a/templates/content/index.php +++ b/templates/content/index.php @@ -1 +1,3 @@ -

Hello world

+
+
efef
+
\ No newline at end of file diff --git a/templates/index.php b/templates/index.php index a5e1aec2..c76f528b 100644 --- a/templates/index.php +++ b/templates/index.php @@ -1,6 +1,6 @@
diff --git a/templates/navigation/index.php b/templates/navigation/index.php index efa95c6b..191c0980 100644 --- a/templates/navigation/index.php +++ b/templates/navigation/index.php @@ -1,10 +1,3 @@