Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 28 additions & 33 deletions .github/workflows/shared_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ jobs:
name: unit tests and linting
strategy:
matrix:
nextcloudVersion: [ stable26, stable27, stable28, stable29, stable30 ]
phpVersion: [ 8.0, 8.1, 8.2, 8.3]
exclude:
- nextcloudVersion: stable26
phpVersion: 8.3
nextcloudVersion: [ stable30 ]
phpVersion: [ 8.1, 8.2, 8.3 ]
include:
- nextcloudVersion: stable27
phpVersion: 8.3
- nextcloudVersion: stable30
phpVersion: 8.0
- nextcloudVersion: stable28
phpVersion: 8.1
- nextcloudVersion: stable29
phpVersion: 8.1
runs-on: ubuntu-20.04
steps:
- name: Checkout for nightly CI
Expand Down Expand Up @@ -111,10 +111,10 @@ jobs:
./occ a:e integration_openproject
cd apps/integration_openproject
# The following if block can be removed once Nextcloud no longer supports PHP 8.0
if [ "${{matrix.phpVersion}}" -eq 8 ]; then
make phpunitforphp8.0
if [ "${{ matrix.phpVersion }}" -eq 8 ]; then
make phpunitforphp8.0 || (echo "A few of the unit tests were unsuccessful. Rerunning the unit test once again......" && make phpunitforphp8.0)
else
make phpunit
make phpunit || (echo "A few of the unit tests were unsuccessful. Rerunning the unit test once again......" && make phpunit)
fi
make jsunit

Expand Down Expand Up @@ -180,29 +180,28 @@ jobs:
name: API tests
strategy:
matrix:
nextcloudVersion: [ stable26, stable27, stable28, stable29, stable30 ]
nextcloudVersion: [ stable30 ]
phpVersionMajor: [ 8 ]
phpVersionMinor: [ 0, 1, 2, 3 ]
database: [pgsql, mysql]
isScheduledEventNightly:
- ${{github.event_name == 'schedule'}}
exclude:
- nextcloudVersion: stable26
phpVersionMinor: 3
- nextcloudVersion: stable27
phpVersionMinor: 3
phpVersionMinor: [ 1, 2, 3 ]
database: [ mysql ]
include:
# Each database once on the newest Server with preinstalled PHP version
- nextcloudVersion: stable30
phpVersionMajor: 8
phpVersionMinor: 1
database: pgsql
- nextcloudVersion: stable27
phpVersionMajor: 8
phpVersionMinor: 0
- isScheduledEventNightly: false
phpVersionMinor: 0
- isScheduledEventNightly: false
database: mysql
- nextcloudVersion: stable28
phpVersionMajor: 8
phpVersionMinor: 1
database: mysql
- nextcloudVersion: stable29
phpVersionMajor: 8
phpVersionMinor: 1
- isScheduledEventNightly: false
nextcloudVersion: stable28
phpVersionMinor: 2
- isScheduledEventNightly: false
nextcloudVersion: stable29
phpVersionMinor: 2
database: mysql
runs-on: ubuntu-20.04
container:
image: public.ecr.aws/ubuntu/ubuntu:latest
Expand Down Expand Up @@ -297,10 +296,6 @@ jobs:
- name: API Tests
env:
NEXTCLOUD_BASE_URL: http://nextcloud
BEHAT_FILTER_TAGS: ${{
matrix.nextcloudVersion == 'stable26' && '~@skipOnStable26' ||
''
}}
run: |
# The following if block can be removed once Nextcloud no longer supports PHP 8.0
if [ "${{matrix.phpVersionMajor}}" -eq 8 ] && [ "${{matrix.phpVersionMinor}}" -eq 0 ]; then
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fix random deactivation of automatically managed project folder
- Fix avatar not found in openproject
- Enhance project search when creating workpackages from Nextcloud
- Drop application's support for Nextcloud 26
- Fix issue preventing direct uploading of resources in Nextcloud that are managed by app `Files Access Control`
- Hash or encrypt `client_secret` for different Nextcloud versions

## 2.6.4 - 2024-08-15
### Changed
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ For more information on how to set up and use the OpenProject application, pleas
<screenshot>https://github.com/nextcloud/integration_openproject/raw/master/img/screenshot1.png</screenshot>
<screenshot>https://github.com/nextcloud/integration_openproject/raw/master/img/screenshot2.png</screenshot>
<dependencies>
<nextcloud min-version="26" max-version="30" />
<nextcloud min-version="27" max-version="30" />
</dependencies>
<background-jobs>
<job>OCA\OpenProject\BackgroundJob\RemoveExpiredDirectUploadTokens</job>
Expand Down
8 changes: 4 additions & 4 deletions lib/Controller/ConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private function setIntegrationConfig(array $values): array {
throw new NoUserException('User "' . Application::OPEN_PROJECT_ENTITIES_NAME . '" does not exists to create application password');
}
$appPassword = $this->openprojectAPIService->generateAppPasswordTokenForUser();
if($isAppPasswordBeingReplaced) {
if ($isAppPasswordBeingReplaced) {
$this->openprojectAPIService->logToAuditFile(
"Application password for user 'OpenProject has been replaced' with new password in application " . Application::APP_ID
);
Expand Down Expand Up @@ -290,7 +290,7 @@ private function setIntegrationConfig(array $values): array {
// resetting and keeping the project folder setup should delete the user app password
if (key_exists('setup_app_password', $values) && $values['setup_app_password'] === false) {
$this->openprojectAPIService->deleteAppPassword();
if(!$runningFullReset) {
if (!$runningFullReset) {
$this->openprojectAPIService->logToAuditFile(
"Project folder setup has been deactivated in application " . Application::APP_ID
);
Expand Down Expand Up @@ -389,14 +389,14 @@ public function setAdminConfig(array $values): DataResponse {
$values['openproject_client_id'] &&
$values['openproject_client_secret'];

if(key_exists('openproject_instance_url', $values) &&
if (key_exists('openproject_instance_url', $values) &&
$values['openproject_instance_url'] && !$isOPOAuthCrdentialSet) {
// sending admin audit log if admin has changed or added the openproject host url
$this->openprojectAPIService->logToAuditFile(
"OpenProject host url has been set to '" . $values['openproject_instance_url'] . "' in application " . Application::APP_ID
);
}
if($isOPOAuthCrdentialSet) {
if ($isOPOAuthCrdentialSet) {
$this->openprojectAPIService->logToAuditFile(
"OpenProject OAuth credential 'openproject_client_id' and 'openproject_client_secret' has been set in application " . Application::APP_ID
);
Expand Down
5 changes: 4 additions & 1 deletion lib/Controller/DirectUploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use OCP\AppFramework\Http\DataResponse;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\ForbiddenException as FileAccessForbiddenException;
use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidContentException;
use OCP\Files\InvalidPathException;
Expand Down Expand Up @@ -275,7 +276,9 @@ public function directUpload(string $token):DataResponse {
return new DataResponse([
'error' => $this->l->t($e->getMessage())
], Http::STATUS_BAD_REQUEST);
} catch (ForbiddenException $e) {
} catch (ForbiddenException | FileAccessForbiddenException $e) {
// the FileAccessForbiddenException can occur when we are not allowed to perform certain file operation
// which is controlled by Nextcloud app File Access Control.
return new DataResponse([
'error' => $this->l->t($e->getMessage())
], Http::STATUS_FORBIDDEN);
Expand Down
38 changes: 26 additions & 12 deletions lib/Service/OauthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ public function __construct(ClientMapper $clientMapper,
$this->crypto = $crypto;
}

/**
* @param string $secret
* @param string $nextcloudVersion
* @return string
*/
public function hashOrEncryptSecretBasedOnNextcloudVersion(string $secret, string $nextcloudVersion): string {
switch (true) {
case version_compare($nextcloudVersion, '30.0.0') >= 0:
case version_compare($nextcloudVersion, '29.0.7') >= 0 && version_compare($nextcloudVersion, '30.0.0') < 0:
case version_compare($nextcloudVersion, '28.0.10') >= 0 && version_compare($nextcloudVersion, '29.0.0') < 0:
case version_compare($nextcloudVersion, '27.1.11.8') >= 0 && version_compare($nextcloudVersion, '28.0.0') < 0:
$encryptedSecret = bin2hex($this->crypto->calculateHMAC($secret));
break;
case version_compare($nextcloudVersion, '27.0.0') === 0:
$encryptedSecret = $secret;
break;
default:
$encryptedSecret = $this->crypto->encrypt($secret);
break;
}
return $encryptedSecret;
}

/**
* @param string $name
* @param string $redirectUri
Expand All @@ -58,16 +81,8 @@ public function createNcOauthClient(string $name, string $redirectUri): array {
$client->setName($name);
$client->setRedirectUri(sprintf($redirectUri, $clientId));
$secret = $this->secureRandom->generate(64, self::validChars);
if (version_compare(OC_Util::getVersionString(), '27.0.1') >= 0) {
$encryptedSecret = $this->crypto->encrypt($secret);
} elseif (version_compare(OC_Util::getVersionString(), '26.0.4') >= 0 && version_compare(OC_Util::getVersionString(), '27.0.0') < 0) {
$encryptedSecret = $this->crypto->encrypt($secret);
} elseif (version_compare(OC_Util::getVersionString(), '25.0.8') >= 0 && version_compare(OC_Util::getVersionString(), '26.0.0') < 0) {
$encryptedSecret = $this->crypto->encrypt($secret);
} else {
$encryptedSecret = $secret;
}
$client->setSecret($encryptedSecret);
$nextcloudVersion = OC_Util::getVersionString();
$client->setSecret($this->hashOrEncryptSecretBasedOnNextcloudVersion($secret, $nextcloudVersion));
$client->setClientIdentifier($clientId);
$client = $this->clientMapper->insert($client);

Expand All @@ -91,8 +106,7 @@ public function getClientInfo(int $id): ?array {
'id' => $client->getId(),
'nextcloud_oauth_client_name' => $client->getName(),
'openproject_redirect_uri' => $client->getRedirectUri(),
'nextcloud_client_id' => $client->getClientIdentifier(),
'nextcloud_client_secret' => $this->crypto->decrypt($client->getSecret()),
'nextcloud_client_id' => $client->getClientIdentifier()
];
} catch (ClientNotFoundException $e) {
return null;
Expand Down
2 changes: 1 addition & 1 deletion lib/Service/OpenProjectAPIService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ class_exists('\OCA\GroupFolders\Folder\FolderManager') &&
* @return void
*/
public function logToAuditFile($auditLogMessage): void {
if($this->isAdminAuditConfigSetCorrectly()) {
if ($this->isAdminAuditConfigSetCorrectly()) {
$this->auditLogger = new AuditLogger($this->logFactory, $this->config);
$this->auditLogger->info($auditLogMessage,
['app' => 'admin_audit']
Expand Down
12 changes: 3 additions & 9 deletions tests/acceptance/features/api/setup.feature
Original file line number Diff line number Diff line change
Expand Up @@ -656,14 +656,12 @@ Feature: setup the integration through an API
"required": [
"nextcloud_oauth_client_name",
"openproject_redirect_uri",
"nextcloud_client_id",
"nextcloud_client_secret"
"nextcloud_client_id"
],
"properties": {
"nextcloud_oauth_client_name": {"type": "string", "pattern": "^OpenProject client$"},
"openproject_redirect_uri": {"type": "string", "pattern": "^http:\/\/some-host.de\/oauth_clients\/[A-Za-z0-9]+\/callback$"},
"nextcloud_client_id": {"type": "string", "pattern": "[A-Za-z0-9]+"},
"nextcloud_client_secret": {"type": "string", "pattern": "[A-Za-z0-9]+"},
"openproject_user_app_password": {"type": "string", "pattern": "[A-Za-z0-9]+"}
}
}
Expand All @@ -678,9 +676,7 @@ Feature: setup the integration through an API
When user "OpenProject" sends a "PROPFIND" request to "/remote.php/webdav" using old app password
Then the HTTP status code should be "401"

# to locally run this test the "project folder" needs to be setup already
# issue of group folder https://github.com/nextcloud/groupfolders/issues/2718
@skipOnStable25 @skipOnStable26

Scenario: check version of uploaded file inside a group folder
Given user "Carol" has been created
And user "Carol" has been added to the group "OpenProject"
Expand All @@ -693,9 +689,7 @@ Feature: setup the integration through an API
When user "Carol" deletes folder "/OpenProject/OpenProject/project-demo"
Then the HTTP status code should be 204

# to locally run this test the "project folder" needs to be setup already
# issue of group folder https://github.com/nextcloud/groupfolders/issues/2718
@skipOnStable25 @skipOnStable26

Scenario: check version of uploaded file after an update inside a group folder
Given user "Carol" has been created
And user "Carol" has been added to the group "OpenProject"
Expand Down
2 changes: 2 additions & 0 deletions tests/lib/Controller/DirectUploadControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

use OC\Files\View;
use OCP\Files\Folder;
use OCP\Files\ForbiddenException as FileAccessForbiddenException;
use OCP\Files\InvalidContentException;
use OCP\IL10N;
use OCP\IRequest;
Expand Down Expand Up @@ -185,6 +186,7 @@ public function testDirectUploadFileNotUploaded(string $tmpName, int $error):voi
public function newFileExceptionsDataProvider() {
return [
[new InvalidContentException('Virus detected'), 'Virus detected', 415],
[new FileAccessForbiddenException('Access denied by the access control', false), 'Access denied by the access control', 403],
[new \Exception('could not upload'), 'could not upload', 500],
];
}
Expand Down
7 changes: 0 additions & 7 deletions tests/lib/Reference/WorkPackageReferenceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
namespace OCA\OpenProject\Reference;

use OC\Collaboration\Reference\ReferenceManager;
use OC_Util;
use OCA\OpenProject\AppInfo\Application;
use OCA\OpenProject\Service\OpenProjectAPIService;
use OCP\IConfig;
Expand All @@ -34,12 +33,6 @@
use PHPUnit\Framework\TestCase;

class WorkPackageReferenceProviderTest extends TestCase {
protected function setUp(): void {
if (version_compare(OC_Util::getVersionString(), '26') < 0) {
$this->markTestSkipped('WorkPackageReferenceProvider is only available from nextcloud 26 so skip the tests on versions below');
}
}

/**
*
* @param array<string> $onlyMethods
Expand Down
Loading