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
12 changes: 6 additions & 6 deletions LICENSES/AGPL-3.0-only.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ An older license, called the Affero General Public License and published by Affe

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS
TERMS AND CONDITIONS

0. Definitions.

Expand Down Expand Up @@ -219,14 +219,14 @@ If you develop a new program, and you want it to be of the greatest possible use

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>

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 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.
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/>.
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/>.

Also add information on how to contact you by electronic and paper mail.

Expand Down
20 changes: 10 additions & 10 deletions LICENSES/CC0-1.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,22 @@ Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:

i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
world based on applicable law or treaty, and any national
implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ appstore: build
--exclude="$(source_build_directory)/psalm.xml" \
--exclude="$(source_build_directory)/webpack.config.json" \
--exclude="$(source_build_directory)/stylelint.config.json" \
--exclude="$(source_build_directory)/empty-skeleton.config.php" \
--exclude="$(source_build_directory)/scoper.inc.php" \
--exclude="$(source_build_directory)/renovate.json" \
--exclude="$(source_build_directory)/renovate.json.license" \
Expand Down
3 changes: 2 additions & 1 deletion appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
['name' => 'settings#getSendMailSummaryOfMaliciousFiles', 'url'
=> '/getSendMailSummaryOfMaliciousFiles', 'verb' => 'GET'],
['name' => 'settings#setSendMailSummaryOfMaliciousFiles', 'url'
=> '/setSendMailSummaryOfMaliciousFiles', 'verb' => 'POST']
=> '/setSendMailSummaryOfMaliciousFiles', 'verb' => 'POST'],
['name' => 'settings#testsettings', 'url' => '/testsettings', 'verb' => 'POST']
]
];
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
},
"scripts": {
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './nextcloud-server/*' -not -path './node_modules/*' -print0 | xargs -0 -n1 php -l",
"cs:check": "rm -rf node_modules/ nextcloud-server/ || true && ./vendor/bin/php-cs-fixer fix --dry-run --diff --config=.php-cs-fixer.dist.php .",
"cs:fix": "rm -rf node_modules/ nextcloud-server/ || true && ./vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php .",
"psalm": "rm -rf node_modules/ || true && vendor/psalm/phar/psalm.phar",
"psalm:check": "rm -rf node_modules/ || true && composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github --show-info=true",
"psalm:fix": "rm -rf node_modules/ || true && composer run psalm -- --alter --issues=MissingOverrideAttribute,ClassMustBeFinal,PossiblyUnusedMethod,MissingParamType",
"psalm:clear": "vendor/psalm/phar/psalm.phar --clear-cache && vendor/psalm/phar/psalm.phar --clear-global-cache"
"cs:check": "./vendor/bin/php-cs-fixer fix --dry-run --diff --config=.php-cs-fixer.dist.php .",
"cs:fix": "./vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php .",
"psalm": "./vendor/psalm/phar/psalm.phar",
"psalm:check": "composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github --show-info=true",
"psalm:fix": "composer run psalm -- --alter --issues=MissingOverrideAttribute,ClassMustBeFinal,PossiblyUnusedMethod,MissingParamType",
"psalm:clear": "./vendor/psalm/phar/psalm.phar --clear-cache && vendor/psalm/phar/psalm.phar --clear-global-cache"
},
"config": {
"allow-plugins": {
Expand Down
32 changes: 32 additions & 0 deletions lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,37 @@
namespace OCA\GDataVaas\Controller;

use OCA\GDataVaas\Service\TagService;
use OCA\GDataVaas\Service\VerdictService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\DB\Exception;
use OCP\IAppConfig;
use OCP\IRequest;
use OCP\Mail\IMailer;
use VaasSdk\Exceptions\VaasAuthenticationException;
use VaasSdk\Options\VaasOptions;
use VaasSdk\Vaas;
use VaasSdk\Verdict;

class SettingsController extends Controller {
private IAppConfig $config;
private TagService $tagService;
private IMailer $mailer;
private VerdictService $verdictService;

public function __construct(
$appName,
IRequest $request,
IAppConfig $config,
TagService $tagService,
IMailer $mailer,
VerdictService $verdictService,
) {
parent::__construct($appName, $request);
$this->config = $config;
$this->tagService = $tagService;
$this->mailer = $mailer;
$this->verdictService = $verdictService;
}

public function setconfig(
Expand Down Expand Up @@ -154,4 +162,28 @@ public function setSendMailSummaryOfMaliciousFiles(bool $sendMailSummaryOfMalici
$this->config->setValueBool($this->appName, 'notifyAdminEnabled', $sendMailSummaryOfMaliciousFiles);
return new JSONResponse(['status' => 'success']);
}

public function testSettings(string $tokenEndpoint, string $vaasUrl): JSONResponse {
try {
$authenticator = $this->verdictService->getAuthenticator($this->verdictService->authMethod, $tokenEndpoint);
$options = new VaasOptions(true, true, $vaasUrl);
$vaas = Vaas::builder()
->withAuthenticator($authenticator)
->withOptions($options)
->build();
$verdict = $vaas->forUrlAsync('https://www.gdata.de')->await();
if ($verdict->verdict === Verdict::CLEAN) {
return new JSONResponse(['status' => 'success']);
}
return new JSONResponse(['status' => 'error', 'message' => 'Test URL verdict: ' . $verdict->verdict->value]);
} catch (VaasAuthenticationException $e) {
return new JSONResponse([
'status' => 'error',
'message' => 'Authentication failed. Please also check your login details above and save them before
taking the test. ' . $e->getMessage()
]);
} catch (\Exception $e) {
return new JSONResponse(['status' => 'error', 'message' => $e->getMessage()]);
}
}
}
10 changes: 6 additions & 4 deletions lib/Service/VerdictService.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class VerdictService {
private string $password;
private string $clientId;
private string $clientSecret;
private string $authMethod;
public string $authMethod;
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the visibility of $authMethod from private to public breaks encapsulation. Consider adding a getter method instead of exposing the property directly.

Suggested change
public string $authMethod;
private string $authMethod;

Copilot uses AI. Check for mistakes.
private string $tokenEndpoint;
private string $vaasUrl;
private IAppConfig $appConfig;
Expand Down Expand Up @@ -212,31 +212,33 @@ public function createAndConnectVaas(): Vaas {
}
$options = new VaasOptions(true, true, $this->vaasUrl);
return Vaas::builder()
->withAuthenticator($this->getAuthenticator($this->authMethod))
->withAuthenticator($this->getAuthenticator($this->authMethod, $this->tokenEndpoint))
->withOptions($options)
->build();
}

/**
* @param string $authMethod
* @param string $tokenEndpoint
* @return ClientCredentialsGrantAuthenticator|ResourceOwnerPasswordGrantAuthenticator
* @throws VaasAuthenticationException
*/
public function getAuthenticator(
string $authMethod,
string $tokenEndpoint,
): ClientCredentialsGrantAuthenticator|ResourceOwnerPasswordGrantAuthenticator {
if ($authMethod === 'ResourceOwnerPassword') {
return new ResourceOwnerPasswordGrantAuthenticator(
'nextcloud-customer',
$this->username,
$this->password,
$this->tokenEndpoint
$tokenEndpoint
);
} elseif ($authMethod === 'ClientCredentials') {
return new ClientCredentialsGrantAuthenticator(
$this->clientId,
$this->clientSecret,
$this->tokenEndpoint
$tokenEndpoint
);
} else {
throw new VaasAuthenticationException('Invalid auth method: ' . $authMethod);
Expand Down
2 changes: 1 addition & 1 deletion lib/Settings/VaasAdminSection.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __construct(

#[\Override]
public function getName(): string {
return 'Verdict-as-a-Service';
return 'G DATA Antivirus';
}

#[\Override]
Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
<directory name="lib" />
<ignoreFiles>
<directory name="vendor" />
<directory name="nextcloud-server" />
</ignoreFiles>
</projectFiles>
<extraFiles>
Expand Down
19 changes: 19 additions & 0 deletions src/admin-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ document.addEventListener('DOMContentLoaded', async () => {

const authSubmit = document.querySelector('#auth_submit');
const authSubmitAdvanced = document.querySelector('#auth_submit_advanced');
const testSettings = document.querySelector('#test-settings');
const resetAllTags = document.querySelector('#reset');
const autoScanFiles = document.querySelector('#auto_scan_files');
const prefixMalicious = document.querySelector('#prefixMalicious');
Expand Down Expand Up @@ -91,6 +92,24 @@ document.addEventListener('DOMContentLoaded', async () => {
}
});

testSettings.addEventListener('click', async (e) => {
e.preventDefault();
const tokenEndpoint = document.querySelector('#token_endpoint').value;
const vaasUrl = document.querySelector('#vaas_url').value;

const response = await postData(OC.generateUrl('apps/gdatavaas/testsettings'), {
tokenEndpoint,
vaasUrl
});
const msgElement = document.querySelector('#auth_save_msg_advanced');

if (response.status === "success") {
msgElement.textContent = 'Authentication successful and VaaS backend reachable.';
} else {
msgElement.textContent = response.message || 'An error occurred during the test.';
}
});

authSubmitAdvanced.addEventListener('click', async (e) => {
e.preventDefault();
const tokenEndpoint = document.querySelector('#token_endpoint').value;
Expand Down
11 changes: 6 additions & 5 deletions templates/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<body>
<div class="section section-auth">
<fieldset class="personalblock">
<h2>G DATA Verdict-as-a-Service</h2>
<h3>You may use self registration and create a new username and password by yourself <a href="https://vaas.gdata.de/login" target="_blank">here</a> for free.</h3>
<h2>G DATA Antivirus</h2>
<h6>You may use self registration and create a new username and password by yourself <a href="https://vaas.gdata.de/login" target="_blank">here</a> for free.</h6>
<table class="basic_settings_table">
<tr class="basic_settings">
<td><div title="<?php p($l->t('If you have registered yourself with your e-mail address and a password, select "Resource Owner Password Flow" here, if you have received a client id and a client secret from G DATA CyberDefense AG, use "Client Credentials Flow". You can ignore the other fields.'));?>" class="visible"><label for="auth_method"><?php p($l->t('Authentication Method'));?></label></div></td>
Expand Down Expand Up @@ -73,8 +73,8 @@
<strong>Caution:</strong> The use of the <em>"Scan only this"</em> and <em>"Do not scan this"</em> settings should be approached with caution. Using these settings allows malicious users to upload and distribute malicious content via the Nextcloud instance. It is recommended that you carefully consider the implications of these settings and use them in a way that does not jeopardize the security of your system and data.
</div>
<div id="advanced_settings">
<h3><?php p($l->t('Advanced Settings'));?></h3>
<h4><?php p($l->t('If you are not sure about this, you can just leave it blank.'));?></h4>
<h2><?php p($l->t('Advanced Settings'));?></h2>
<h6><?php p($l->t('If you are not sure about this, you can just leave it blank.'));?></h6>
<table>
<tr class="token_endpoint">
<td><label for="token_endpoint">Token Endpoint</label></td>
Expand All @@ -87,11 +87,12 @@
</table>
<table>
<tr id="advanced_buttons">
<td><input id="test-settings" type="submit" value="<?php p($l->t('Test'));?>" /></td>
<td><input id="auth_submit_advanced" type="submit" value="<?php p($l->t('Save'));?>" /></td>
<td><div title="<?php p($l->t('Removes all tags set by this app.'));?>" class="visible"><input class="submit-button" id="reset" type="submit" value="<?php p($l->t('Reset all tags'));?>"/></div></td>
<td><span id="auth_save_msg_advanced"></span></td>
</tr>
</table>
<span id="auth_save_msg_advanced"></span>
</div>
</fieldset>
</div>
Expand Down
5 changes: 4 additions & 1 deletion tests/unittests/VerdictServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ public function testAuthenticator(): void {
$this->createMock(FileService::class),
$this->createMock(TagService::class));

$authenticator = $verdictService->getAuthenticator('ResourceOwnerPassword');
$authenticator = $verdictService->getAuthenticator(
'ResourceOwnerPassword',
'https://account-staging.gdata.de/realms/vaas-staging/protocol/openid-connect/token'
);
$this->assertInstanceOf(ResourceOwnerPasswordGrantAuthenticator::class, $authenticator);
}
}