[OP#45466]Remove expired direct upload tokens using background jobs (#341)
* Added function to remove all expired tokens for direct upload Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> * use time() as timestamp Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> * Added unit tests for delete upload tokens Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> * fix lint Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> * CI check to enable integration app Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> * Follow up CI failure Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com> --------- Signed-off-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com>
This commit is contained in:
Родитель
3e72773e45
Коммит
b5aaa10af6
|
@ -91,6 +91,11 @@ jobs:
|
|||
|
||||
- name: PHP & Vue Unit Tests
|
||||
run: |
|
||||
mkdir -p server/apps/integration_openproject
|
||||
cp -r `ls -A | grep -v 'server'` server/apps/integration_openproject/
|
||||
cd server
|
||||
./occ a:e integration_openproject
|
||||
cd apps/integration_openproject
|
||||
make phpunit
|
||||
make jsunit
|
||||
|
||||
|
@ -99,7 +104,7 @@ jobs:
|
|||
uses: romeovs/lcov-reporter-action@v0.3.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
lcov-file: ./coverage/jest/lcov.info
|
||||
lcov-file: ./server/apps/integration_openproject/coverage/jest/lcov.info
|
||||
delete-old-comments: true
|
||||
title: "JS Code Coverage"
|
||||
|
||||
|
@ -107,8 +112,8 @@ jobs:
|
|||
if: ${{ github.event_name == 'pull_request' && matrix.nextcloudVersion == 'master' && matrix.phpVersion == '8.1' }}
|
||||
uses: danielpalme/ReportGenerator-GitHub-Action@5.0.3
|
||||
with:
|
||||
reports: './coverage/php/cobertura.xml' # REQUIRED # The coverage reports that should be parsed (separated by semicolon). Globbing is supported.
|
||||
targetdir: './coverage/php' # REQUIRED # The directory where the generated report should be saved.
|
||||
reports: './server/apps/integration_openproject/coverage/php/cobertura.xml' # REQUIRED # The coverage reports that should be parsed (separated by semicolon). Globbing is supported.
|
||||
targetdir: './server/apps/integration_openproject/coverage/php' # REQUIRED # The directory where the generated report should be saved.
|
||||
reporttypes: 'lcov' # The output formats and scope (separated by semicolon) Values: Badges, Clover, Cobertura, CsvSummary, Html, HtmlChart, HtmlInline, HtmlInline_AzurePipelines, HtmlInline_AzurePipelines_Dark, HtmlSummary, JsonSummary, Latex, LatexSummary, lcov, MarkdownSummary, MHtml, PngChart, SonarQube, TeamCitySummary, TextSummary, Xml, XmlSummary
|
||||
sourcedirs: '' # Optional directories which contain the corresponding source code (separated by semicolon). The source directories are used if coverage report contains classes without path information.
|
||||
historydir: '' # Optional directory for storing persistent coverage information. Can be used in future reports to show coverage evolution.
|
||||
|
@ -127,7 +132,7 @@ jobs:
|
|||
uses: romeovs/lcov-reporter-action@v0.3.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
lcov-file: ./coverage/php/lcov.info
|
||||
lcov-file: ./server/apps/integration_openproject/coverage/php/lcov.info
|
||||
delete-old-comments: true
|
||||
title: "PHP Code Coverage"
|
||||
|
||||
|
@ -136,14 +141,15 @@ jobs:
|
|||
uses: VeryGoodOpenSource/very_good_coverage@v1.2.0
|
||||
with:
|
||||
min_coverage: '59'
|
||||
path: './coverage/jest/lcov.info'
|
||||
path: './server/apps/integration_openproject/coverage/jest/lcov.info'
|
||||
|
||||
- name: PHP coverage check
|
||||
if: ${{ github.event_name == 'pull_request' && matrix.nextcloudVersion == 'master' && matrix.phpVersion == '8.1' }}
|
||||
uses: VeryGoodOpenSource/very_good_coverage@v1.2.0
|
||||
with:
|
||||
min_coverage: '57'
|
||||
path: './coverage/php/lcov.info'
|
||||
path: './server/apps/integration_openproject/coverage/php/lcov.info'
|
||||
|
||||
api-tests:
|
||||
name: API tests
|
||||
strategy:
|
||||
|
|
|
@ -38,7 +38,7 @@ For more information on how to set up and use the OpenProject application, pleas
|
|||
<nextcloud min-version="22" max-version="26"/>
|
||||
</dependencies>
|
||||
<background-jobs>
|
||||
<job>OCA\OpenProject\BackgroundJob\CheckNotifications</job>
|
||||
<job>OCA\OpenProject\BackgroundJob\RemoveExpiredDirectUploadTokens</job>
|
||||
</background-jobs>
|
||||
<settings>
|
||||
<admin>OCA\OpenProject\Settings\Admin</admin>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Sagar Gurung <sagar@jankaritech.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* 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\OpenProject\BackgroundJob;
|
||||
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\DB\Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use OCA\OpenProject\Service\DatabaseService;
|
||||
|
||||
class RemoveExpiredDirectUploadTokens extends TimedJob {
|
||||
|
||||
/** @var LoggerInterface */
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
/** @var DatabaseService */
|
||||
protected DatabaseService $databaseService;
|
||||
|
||||
public function __construct(ITimeFactory $time, DatabaseService $databaseService, LoggerInterface $logger) {
|
||||
parent::__construct($time);
|
||||
// runs once a day
|
||||
$this->setInterval(24 * 3600);
|
||||
$this->databaseService = $databaseService;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $argument
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function run($argument): void {
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$this->logger->info('Deleted all the expired tokens from Database');
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ class DatabaseService {
|
|||
/**
|
||||
* @var IDBConnection
|
||||
*/
|
||||
private IDBConnection $db;
|
||||
public IDBConnection $db;
|
||||
|
||||
|
||||
/** @var string table name */
|
||||
|
@ -102,6 +102,19 @@ class DatabaseService {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function deleteExpiredTokens(): void {
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->delete($this->table)
|
||||
->where(
|
||||
$query->expr()->lt('expires_on', $query->createNamedParameter(time()))
|
||||
);
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the token from the table
|
||||
* @param string $token
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Swikriti Tripathi <swikriti@jankaritech.com>
|
||||
*
|
||||
* @author Your name <swikriti@jankaritech.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* 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\OpenProject\Service;
|
||||
|
||||
use OCA\OpenProject\AppInfo\Application;
|
||||
use OCP\DB\Exception;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatabaseServiceTest extends TestCase {
|
||||
/**
|
||||
* @var DatabaseService
|
||||
*/
|
||||
private $databaseService;
|
||||
private const TABLE_NAME = 'direct_upload';
|
||||
|
||||
/**
|
||||
* createdAt and expiresOn info is not included since it requires current timestamp
|
||||
*
|
||||
* @var array <mixed>
|
||||
*/
|
||||
private array $unexpiredDirectUploadInfo = [
|
||||
[
|
||||
"token" => 'unExpiredToken1',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
[
|
||||
"token" => 'unExpiredToken2',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
[
|
||||
"token" => 'unExpiredToken3',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* createdAt and expiresOn info is not included since it requires current timestamp
|
||||
*
|
||||
* @var array <mixed>
|
||||
*/
|
||||
private array $expiredDirectUploadInfo = [
|
||||
[
|
||||
"token" => 'expiredToken1',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
[
|
||||
"token" => 'expiredToken2',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
[
|
||||
"token" => 'expiredToken3',
|
||||
"folderId" => 1,
|
||||
"userId" => 'u1',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
protected function setUp(): void {
|
||||
$app = new Application();
|
||||
$c = $app->getContainer();
|
||||
|
||||
/** @var DatabaseService $databaseService */
|
||||
$databaseService = $c->get(DatabaseService::class);
|
||||
$this->databaseService = $databaseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function tearDown(): void {
|
||||
$query = $this->databaseService->db->getQueryBuilder();
|
||||
$query->delete(self::TABLE_NAME);
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public function getAllTokensFromTable(): array {
|
||||
$tokens = [];
|
||||
$query = $this->databaseService->db->getQueryBuilder();
|
||||
$query->select('token')
|
||||
->from(self::TABLE_NAME);
|
||||
$req = $query->executeQuery();
|
||||
while ($row = $req->fetch()) {
|
||||
$tokens[] = $row['token'];
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testDeleteSingleExpiredToken(): void {
|
||||
$this->databaseService->setInfoForDirectUpload("expiredToken", 1, "u1", time(), time() - 1000);
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$token = $this->getAllTokensFromTable();
|
||||
self::assertEquals(0, sizeof($token));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testDeleteMultipleExpiredTokens(): void {
|
||||
foreach ($this->expiredDirectUploadInfo as $info) {
|
||||
$this->databaseService->setInfoForDirectUpload($info['token'], $info['folderId'], $info['userId'], time(), time() - 1000);
|
||||
}
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$tokens = $this->getAllTokensFromTable();
|
||||
self::assertEquals(0, sizeof($tokens));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testDeleteSingleUnExpiredToken(): void {
|
||||
$this->databaseService->setInfoForDirectUpload("unExpiredToken", 1, "u1", time(), time() + 1000);
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$token = $this->getAllTokensFromTable();
|
||||
self::assertSame('unExpiredToken', $token[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testDeleteMultipleUnExpiredTokens(): void {
|
||||
foreach ($this->unexpiredDirectUploadInfo as $info) {
|
||||
$this->databaseService->setInfoForDirectUpload($info['token'], $info['folderId'], $info['userId'], time(), time() + 1000);
|
||||
}
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$tokens = $this->getAllTokensFromTable();
|
||||
self::assertEquals(sizeof($this->unexpiredDirectUploadInfo), sizeof($tokens));
|
||||
foreach ($this->unexpiredDirectUploadInfo as $info) {
|
||||
self::assertContains($info['token'], $tokens);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testDeleteMultipleExpiredAndUnexpiredTokens(): void {
|
||||
foreach ($this->expiredDirectUploadInfo as $info) {
|
||||
$this->databaseService->setInfoForDirectUpload($info['token'], $info['folderId'], $info['userId'], time(), time() - 1000);
|
||||
}
|
||||
foreach ($this->unexpiredDirectUploadInfo as $info) {
|
||||
$this->databaseService->setInfoForDirectUpload($info['token'], $info['folderId'], $info['userId'], time(), time() + 1000);
|
||||
}
|
||||
$this->databaseService->deleteExpiredTokens();
|
||||
$tokens = $this->getAllTokensFromTable();
|
||||
self::assertEquals(sizeof($this->unexpiredDirectUploadInfo), sizeof($tokens));
|
||||
foreach ($this->unexpiredDirectUploadInfo as $info) {
|
||||
self::assertContains($info['token'], $tokens);
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче