Skip to content

Commit

Permalink
devsync test
Browse files Browse the repository at this point in the history
  • Loading branch information
pulsejet committed Oct 2, 2023
1 parent 63b5c00 commit 2fa41f1
Show file tree
Hide file tree
Showing 5 changed files with 407 additions and 2 deletions.
3 changes: 3 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ function w($base, $param)
['name' => 'Admin#setSystemConfig', 'url' => '/api/system-config/{key}', 'verb' => 'PUT'],
['name' => 'Admin#placesSetup', 'url' => '/api/occ/places-setup', 'verb' => 'POST'],

// DevSync
['name' => 'DevSync#register', 'url' => '/api/dev-sync/register', 'verb' => 'POST'],

// Service worker
['name' => 'Other#serviceWorker', 'url' => '/service-worker.js', 'verb' => 'GET'],
]
Expand Down
43 changes: 43 additions & 0 deletions lib/Controller/DevSyncController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2022 Varun Patil <radialapps@gmail.com>
* @author Varun Patil <radialapps@gmail.com>
* @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 <http://www.gnu.org/licenses/>.
*/

namespace OCA\Memories\Controller;

use OCA\Memories\Util;
use OCP\AppFramework\Http;
use \OCA\Memories\Db\DevSync;

class DevSyncController extends GenericApiController
{
/**
* @NoAdminRequired
*
* @PublicPage
*/
public function register(int $deviceId, array $auids): Http\Response
{
return Util::guardEx(static function () use ($deviceId, $auids) {
return \OC::$server->get(DevSync::class)->register($deviceId, $auids);
});
}
}
201 changes: 201 additions & 0 deletions lib/Db/DevSync.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<?php

declare(strict_types=1);

namespace OCA\Memories\Db;

use OCA\Memories\Util;
use OCP\IDBConnection;

class DevSync
{
protected IDBConnection $connection;

public function __construct(IDBConnection $connection)
{
$this->connection = $connection;
}

/**
* Process an existing file for sync purposes.
*
* @param int $fileid The file ID
* @param int $auid The AUID
*/
public function haveFile(int $fileid, int $auid)
{
// Get the current record for the file
$query = $this->connection->getQueryBuilder();
$current = $query
->select('*')
->from('memories_sync')
->where(
$query->expr()->orX(
$query->expr()->eq('fileid', $query->createNamedParameter($fileid)),
$query->expr()->eq('auid', $query->createNamedParameter($auid))
),
)->executeQuery()
->fetch()
;

if ($current) {
// Update status if it's not extant
$updateStatus = 1 !== (int) $current['status'];

// Update the file ID only if it didn't already exist
// or if the file didn't exist in our collection to begin with
$updateFileId = $updateStatus || 0 === (int) $current['fileid'];

if (!$updateFileId && !$updateStatus) {
// Nothing to do. This can also happen if same AUID exists
// with a different file ID (duplicates get ignored)
return;
}

// Update the record
$query = $this->connection->getQueryBuilder();
$query->update('memories_sync')
->set('mtime', $query->createNamedParameter(time()))
->set('status', $query->createNamedParameter(1))
->where($query->expr()->eq('id', $query->createNamedParameter((int) $current['id'])))
;

// Only update the file ID if it didn't exist
if ($updateFileId) {
$query->set('fileid', $query->createNamedParameter($fileid));
}

$query->executeStatement();

return;
}

// File does not exist in sync; create a new record
$query = $this->connection->getQueryBuilder();
$query->insert('memories_sync')
->values([
'mtime' => $query->createNamedParameter(time()),
'fileid' => $query->createNamedParameter($fileid),
'auid' => $query->createNamedParameter($auid),
'device' => $query->createNamedParameter(0),
'status' => $query->createNamedParameter(1),
])
->executeStatement()
;
}

/**
* Process a deleted file for sync purposes.
*
* @param int $fileid The file ID
*/
public function deleteFile(int $fileid)
{
// If the file is being deleted, simply mark any existing record as such and return
$query = $this->connection->getQueryBuilder();
$query->update('memories_sync')
->set('mtime', $query->createNamedParameter(time()))
->set('status', $query->createNamedParameter(2))
->where($query->expr()->eq('fileid', $query->createNamedParameter($fileid)))
->executeStatement()
;
}

/**
* Register a device for a set of AUIDs.
*
* @param int $deviceId The device ID
* @param array $auids The AUIDs
*/
public function register(int $deviceId, array $auids)
{
// Convert all auid to int and filter out zeros
$auids = array_filter(array_map('intval', $auids));

$uid = Util::getUID();

// Result for mappings
$result = [];

// Get filesystem manager
$fs = \OC::$server->get(\OCA\Memories\Db\FsManager::class);

// Get the current records for the AUIDs
foreach ($auids as $auid) {
$query = $this->connection->getQueryBuilder();
$current = $query
->select('*')
->from('memories_sync')
->where($query->expr()->eq('auid', $query->createNamedParameter($auid)))
->executeQuery()
->fetch()
;

// An existing record exists
if ($current) {
$recordId = (int) $current['id'];

$result[] = [
'fileid' => (int) $current['fileid'],
'auid' => (int) $current['auid'],
'status' => (int) $current['status'],
];

// Update the record if device is not registered
if (!(int) $current['device']) {
$this->updateDeviceId($deviceId, $recordId);
}

// If a different device is registered the file owner gets priority
elseif ((int) $current['device'] !== $deviceId) {
$userFile = $fs->getUserFolderFile((int) $current['fileid']);

// If the owner is the current user, update the device ID
if (null !== $userFile && $userFile->getOwner() && $userFile->getOwner()->getUID() === $uid) {
$this->updateDeviceId($deviceId, $recordId);
}
}

continue;
}

// Create record
$query = $this->connection->getQueryBuilder();
$query->insert('memories_sync')
->values([
'mtime' => $query->createNamedParameter(time()),
'fileid' => $query->createNamedParameter(0),
'auid' => $query->createNamedParameter($auid),
'device' => $query->createNamedParameter($deviceId),
'status' => $query->createNamedParameter(0),
])
->executeStatement()
;

// Add to result
$result[] = [
'fileid' => 0,
'auid' => (int) $current['auid'],
'status' => 0,
];
}

return $result;
}

/**
* Update the device ID for a file.
*
* @param int $recordId The record ID
* @param int $deviceId The device ID
*/
private function updateDeviceId(int $recordId, int $deviceId)
{
$query = $this->connection->getQueryBuilder();
$query->update('memories_sync')
->set('device', $query->createNamedParameter($deviceId))
->where($query->expr()->eq('id', $query->createNamedParameter($recordId)))
->executeStatement()
;
}
}
10 changes: 8 additions & 2 deletions lib/Db/TimelineWrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@ class TimelineWrite
protected IDBConnection $connection;
protected LivePhoto $livePhoto;
protected ILockingProvider $lockingProvider;
protected DevSync $devSync;

public function __construct(
IDBConnection $connection,
LivePhoto $livePhoto,
ILockingProvider $lockingProvider
ILockingProvider $lockingProvider,
DevSync $devSync
) {
$this->connection = $connection;
$this->livePhoto = $livePhoto;
$this->lockingProvider = $lockingProvider;
$this->devSync = $devSync;
}

/**
Expand Down Expand Up @@ -184,7 +187,7 @@ public function processFile(
/**
* Remove a file from the exif database.
*/
public function deleteFile(File &$file)
public function deleteFile(File $file)
{
// Get full record
$query = $this->connection->getQueryBuilder();
Expand All @@ -211,6 +214,9 @@ public function deleteFile(File &$file)
$this->mapRemoveFromCluster($cid, (float) $record['lat'], (float) $record['lon']);
}

// Mark deletion in sync table
$this->devSync->deleteFile($file->getId());

// Commit transaction
$this->connection->commit();
}
Expand Down
Loading

0 comments on commit 2fa41f1

Please sign in to comment.