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
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
php-version: ${{ matrix.phpVersion }}
tools: composer, phpunit
coverage: xdebug
extensions: gd, sqlite3

- name: Get composer cache directory
id: composer-cache
Expand Down Expand Up @@ -240,7 +241,7 @@ jobs:
with:
php-version: ${{ format('{0}.{1}', matrix.phpVersionMajor,matrix.phpVersionMinor) }}
tools: composer
extensions: intl
extensions: intl, gd

- name: Get composer cache directory
id: composer-cache
Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ On the OpenProject end, users are able to:

For more information on how to set up and use the OpenProject application, please refer to [integration setup guide](https://www.openproject.org/docs/system-admin-guide/integrations/nextcloud/) for administrators and [the user guide](https://www.openproject.org/docs/user-guide/nextcloud-integration/).
]]></description>
<version>2.3.7</version>
<version>2.3.8</version>
<licence>agpl</licence>
<author>Julien Veyssier</author>
<namespace>OpenProject</namespace>
Expand Down
52 changes: 34 additions & 18 deletions lib/Service/OauthService.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use OCA\OAuth2\Db\ClientMapper;
use OCA\OAuth2\Exceptions\ClientNotFoundException;
use OCP\Security\ISecureRandom;
use OCP\Security\ICrypto;
use OC_Util;

class OauthService {
/**
Expand All @@ -28,14 +30,21 @@ class OauthService {
*/
private $clientMapper;

/**
* @var ICrypto
*/
private $crypto;

/**
* Service to manipulate Nextcloud oauth clients
*/
public function __construct(ClientMapper $clientMapper,
ISecureRandom $secureRandom
ISecureRandom $secureRandom,
ICrypto $crypto
) {
$this->secureRandom = $secureRandom;
$this->clientMapper = $clientMapper;
$this->crypto = $crypto;
}

/**
Expand All @@ -48,11 +57,27 @@ public function createNcOauthClient(string $name, string $redirectUri): array {
$client = new Client();
$client->setName($name);
$client->setRedirectUri(sprintf($redirectUri, $clientId));
$client->setSecret($this->secureRandom->generate(64, self::validChars));
$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);
$client->setClientIdentifier($clientId);
$client = $this->clientMapper->insert($client);

return $this->generateClientInfo($client);
return [
'id' => $client->getId(),
'nextcloud_oauth_client_name' => $client->getName(),
'openproject_redirect_uri' => $client->getRedirectUri(),
'nextcloud_client_id' => $client->getClientIdentifier(),
'nextcloud_client_secret' => $secret,
];
}

/**
Expand All @@ -62,7 +87,12 @@ public function createNcOauthClient(string $name, string $redirectUri): array {
public function getClientInfo(int $id): ?array {
try {
$client = $this->clientMapper->getByUid($id);
return $this->generateClientInfo($client);
return [
'id' => $client->getId(),
'nextcloud_oauth_client_name' => $client->getName(),
'openproject_redirect_uri' => $client->getRedirectUri(),
'nextcloud_client_id' => $client->getClientIdentifier(),
];
} catch (ClientNotFoundException $e) {
return null;
}
Expand All @@ -85,18 +115,4 @@ public function setClientRedirectUri(int $id, string $opUrl): bool {
return false;
}
}

/**
* @param Client $client
* @return array<mixed>
*/
private function generateClientInfo(Client $client): array {
return [
'id' => $client->getId(),
'nextcloud_oauth_client_name' => $client->getName(),
'openproject_redirect_uri' => $client->getRedirectUri(),
'nextcloud_client_id' => $client->getClientIdentifier(),
'nextcloud_client_secret' => $client->getSecret(),
];
}
}
6 changes: 3 additions & 3 deletions src/components/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,11 @@
title="Nextcloud OAuth client secret"
is-required
encrypt-value
with-inspection
:value="ncClientSecret" />
<div class="form-actions">
<Button v-if="isNcOAuthFormInEdit"
type="primary"
:disabled="!ncClientId || !ncClientSecret"
:disabled="!ncClientId"
data-test-id="submit-nc-oauth-values-form-btn"
@click="setNCOAuthFormToViewMode">
<template #icon>
Expand Down Expand Up @@ -252,7 +251,8 @@ export default {
return this.state.nc_oauth_client?.nextcloud_client_id
},
ncClientSecret() {
return this.state.nc_oauth_client?.nextcloud_client_secret
return '*******'

},
serverHostErrorMessage() {
if (
Expand Down
15 changes: 5 additions & 10 deletions tests/acceptance/features/api/setup.feature
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,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:\/\/.*\/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]+"}
"nextcloud_client_id": {"type": "string", "pattern": "[A-Za-z0-9]+"}
},
"not": {
"required": [
Expand Down Expand Up @@ -263,14 +261,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:\/\/.*\/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]+"}
"nextcloud_client_id": {"type": "string", "pattern": "[A-Za-z0-9]+"}
},
"not": {
"required": [
Expand Down Expand Up @@ -407,8 +403,7 @@ Feature: setup the integration through an API
"required": [
"nextcloud_oauth_client_name",
"openproject_redirect_uri",
"nextcloud_client_id",
"nextcloud_client_secret"
"nextcloud_client_id"
]
},
"not": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ exports[`AdminSettings.vue Nextcloud OAuth values form view mode with complete v
<formheading-stub index="3" title="Nextcloud OAuth client" iscomplete="true"></formheading-stub>
<div>
<fieldvalue-stub title="Nextcloud OAuth client ID" value="some-nc-client-id-here" isrequired="true"></fieldvalue-stub>
<fieldvalue-stub title="Nextcloud OAuth client secret" value="some-nc-client-secret-here" isrequired="true" encryptvalue="true" withinspection="true"></fieldvalue-stub>
<fieldvalue-stub title="Nextcloud OAuth client secret" value="*******" isrequired="true" encryptvalue="true"></fieldvalue-stub>
<div class="form-actions">
<button-stub type="secondary" nativetype="button" data-test-id="reset-nc-oauth-btn">
Replace Nextcloud OAuth values
Expand Down