Skip to content

Commit c46884f

Browse files
doxthreepstadermann
authored andcommitted
Admin delegation (#270)
Implementation and test
1 parent e10fb44 commit c46884f

24 files changed

+3515
-1562
lines changed

.github/workflows/lint-eslint.yml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ on: pull_request
1313
permissions:
1414
contents: read
1515

16-
1716
jobs:
1817
changes:
1918
runs-on: ubuntu-latest
@@ -43,14 +42,12 @@ jobs:
4342
- '**.ts'
4443
- '**.vue'
4544
46-
lint:
45+
eslint:
4746
runs-on: ubuntu-latest
4847

4948
needs: changes
5049
if: needs.changes.outputs.src != 'false'
5150

52-
name: NPM lint
53-
5451
steps:
5552
- name: Checkout
5653
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -80,18 +77,3 @@ jobs:
8077

8178
- name: Lint
8279
run: npm run lint
83-
84-
summary:
85-
permissions:
86-
contents: none
87-
runs-on: ubuntu-latest
88-
needs: [changes, lint]
89-
90-
if: always()
91-
92-
# This is the summary, we just avoid to rename it so that branch protection rules still match
93-
name: eslint
94-
95-
steps:
96-
- name: Summary status
97-
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi

.github/workflows/tests.yml

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ defaults:
99
shell: bash
1010
on:
1111
push:
12-
branches: ["main"]
13-
tags: ["*"]
12+
branches: ['main']
13+
tags: ['*']
1414
pull_request:
1515
workflow_dispatch:
1616

@@ -39,15 +39,15 @@ jobs:
3939
env:
4040
IS_CI: 1
4141
options: --name nextcloud-antivirus-build-container
42-
needs:
42+
needs:
4343
- build-devcontainer
4444
steps:
4545
- uses: actions/checkout@v4
4646

4747
- name: postCreateCommands
4848
run: |
4949
source .devcontainer/postCreateCommands.sh
50-
50+
5151
- name: add composer bin to path
5252
run: |
5353
echo $(composer config home --global)/vendor/bin >> $GITHUB_PATH
@@ -82,21 +82,14 @@ jobs:
8282
run: |
8383
docker network connect nextcloud-gdata-antivirus_nextcloud-network nextcloud-antivirus-build-container
8484
85-
- name: run tests
86-
id: bats-tests
85+
- name: run integration tests
8786
env:
8887
CLIENT_ID: ${{ secrets.VAAS_CLIENT_ID }}
8988
CLIENT_SECRET: ${{ secrets.VAAS_CLIENT_SECRET }}
89+
NEXTCLOUD_HOSTNAME: nextcloud-container
9090
run: |
91-
if bats --verbose-run --timing --trace ./tests/bats; then
92-
echo "bats_run=success" | tee -a "$GITHUB_OUTPUT";
93-
else
94-
echo "bats_run=fail" | tee -a "$GITHUB_OUTPUT";
95-
fi
96-
97-
- name: fail if bats tests did fail
98-
if: steps.bats-tests.outputs.bats_run == 'fail'
99-
run: exit 1
91+
bats --verbose-run --timing --trace ./tests/bats
92+
./vendor/bin/phpunit --bootstrap tests/integration/bootstrap.php tests/integration/
10093
10194
- uses: actions/upload-artifact@master
10295
with:

.prettierrc.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-FileCopyrightText: 2025 G DATA CyberDefense AG <[email protected]>
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
semi: false
5+
singleQuote: true

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ unittests:
7777
composer install
7878
./vendor/bin/phpunit --bootstrap tests/unittests/bootstrap.php tests/unittests/ --testdox
7979

80+
# Run integration tests
81+
.PHONY: integrationtests
82+
integrationtests:
83+
./scripts/run-app.sh "32.0.0" 1
84+
composer install
85+
./vendor/bin/phpunit -c tests/integration/phpunit.xml tests/integration/ --testdox
86+
8087
# Run bats tests
8188
.PHONY: bats
8289
bats:

appinfo/info.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Please make sure the "Authentication Method" "Resource Owner Password Flow" is s
7171
</commands>
7272
<settings>
7373
<admin>OCA\GDataVaas\Settings\VaasAdmin</admin>
74+
<admin>OCA\GDataVaas\Settings\VaasOperator</admin>
7475
<admin-section>OCA\GDataVaas\Settings\VaasAdminSection</admin-section>
7576
</settings>
7677
<activity>

appinfo/routes.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@
77
return [
88
'resources' => [],
99
'routes' => [
10+
// user
1011
['name' => 'scan#scan', 'url' => '/scan', 'verb' => 'POST'],
11-
['name' => 'settings#setconfig', 'url' => '/setconfig', 'verb' => 'POST'],
12-
['name' => 'settings#setadvancedconfig', 'url' => '/setadvancedconfig', 'verb' => 'POST'],
12+
// operator
13+
['name' => 'settings#setOperatorSettings', 'url' => '/operatorSettings', 'verb' => 'POST'],
14+
['name' => 'settings#getSendMailOnVirusUpload', 'url' => '/getSendMailOnVirusUpload', 'verb' => 'GET'],
15+
['name' => 'settings#setSendMailOnVirusUpload', 'url' => '/setSendMailOnVirusUpload', 'verb' => 'POST'],
1316
['name' => 'settings#setAutoScan', 'url' => '/setAutoScan', 'verb' => 'POST'],
1417
['name' => 'settings#getAutoScan', 'url' => '/getAutoScan', 'verb' => 'GET'],
1518
['name' => 'settings#setPrefixMalicious', 'url' => '/setPrefixMalicious', 'verb' => 'POST'],
1619
['name' => 'settings#getPrefixMalicious', 'url' => '/getPrefixMalicious', 'verb' => 'GET'],
17-
['name' => 'settings#getAuthMethod', 'url' => '/getAuthMethod', 'verb' => 'GET'],
1820
['name' => 'settings#setDisableUnscannedTag', 'url' => '/setDisableUnscannedTag', 'verb' => 'POST'],
1921
['name' => 'settings#getDisableUnscannedTag', 'url' => '/getDisableUnscannedTag', 'verb' => 'GET'],
20-
['name' => 'settings#resetAllTags', 'url' => '/resetalltags', 'verb' => 'POST'],
2122
['name' => 'settings#getCounters', 'url' => '/getCounters', 'verb' => 'GET'],
22-
['name' => 'settings#getSendMailOnVirusUpload', 'url' => '/getSendMailOnVirusUpload', 'verb' => 'GET'],
23-
['name' => 'settings#setSendMailOnVirusUpload', 'url' => '/setSendMailOnVirusUpload', 'verb' => 'POST'],
23+
// admin
24+
['name' => 'settings#setAdminSettings', 'url' => '/adminSettings', 'verb' => 'POST'],
25+
['name' => 'settings#setAdvancedConfig', 'url' => '/setAdvancedConfig', 'verb' => 'POST'],
26+
['name' => 'settings#getAuthMethod', 'url' => '/getAuthMethod', 'verb' => 'GET'],
27+
['name' => 'settings#resetAllTags', 'url' => '/resetalltags', 'verb' => 'POST'],
2428
['name' => 'settings#testsettings', 'url' => '/testsettings', 'verb' => 'POST'],
2529
['name' => 'settings#getCache', 'url' => '/getCache', 'verb' => 'GET'],
26-
['name' => 'settings#getHashlookup', 'url' => '/getHashlookup', 'verb' => 'GET']
30+
['name' => 'settings#getHashlookup', 'url' => '/getHashlookup', 'verb' => 'GET'],
2731
]
2832
];

composer.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
"coduo/php-humanizer": "5.0.0"
1414
},
1515
"require-dev": {
16-
"nextcloud/ocp": "v31.0.8",
16+
"nextcloud/ocp": "v31.0.9",
1717
"psalm/phar": "6.8.2",
1818
"nextcloud/coding-standard": "v1.4.0",
19-
"colinodell/psr-testlogger": "1.3.0",
20-
"phpunit/phpunit": "10.5.52",
21-
"symfony/console": "v6.4.24"
19+
"colinodell/psr-testlogger": "1.3.1",
20+
"phpunit/phpunit": "10.5.58",
21+
"symfony/console": "v6.4.27",
22+
"amphp/http-client": "5.3.4",
23+
"amphp/amp": "3.1.1",
24+
"vlucas/phpdotenv": "5.6.2"
2225
},
2326
"autoload": {
2427
"psr-4": {
@@ -45,4 +48,4 @@
4548
"php": "8.1"
4649
}
4750
}
48-
}
51+
}

lib/Controller/SettingsController.php

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
use OCA\GDataVaas\Service\TagService;
1010
use OCA\GDataVaas\Service\VerdictService;
11+
use OCA\GDataVaas\Settings\VaasOperator;
1112
use OCP\AppFramework\Controller;
13+
use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
1214
use OCP\AppFramework\Http\JSONResponse;
1315
use OCP\DB\Exception;
1416
use OCP\IAppConfig;
@@ -40,29 +42,17 @@ public function __construct(
4042
$this->verdictService = $verdictService;
4143
}
4244

43-
public function setconfig(
45+
public function setAdminSettings(
4446
$username,
4547
$password,
4648
$clientId,
4749
$clientSecret,
4850
$authMethod,
49-
$quarantineFolder,
50-
$scanOnlyThis,
51-
$doNotScanThis,
52-
$notifyMails,
5351
$maxScanSize,
5452
$timeout,
5553
bool $cache,
5654
bool $hashlookup,
5755
): JSONResponse {
58-
if (!empty($notifyMails)) {
59-
$mails = explode(',', preg_replace('/\s+/', '', $notifyMails));
60-
foreach ($mails as $mail) {
61-
if ($this->mailer->validateMailAddress($mail) === false) {
62-
return new JSONResponse(['status' => 'error', 'message' => 'Invalid email address: ' . $mail]);
63-
}
64-
}
65-
}
6656
if ((int)$maxScanSize < 1) {
6757
return new JSONResponse(['status' => 'error', 'message' => 'Invalid max scan size: ' . $maxScanSize]);
6858
}
@@ -74,37 +64,59 @@ public function setconfig(
7464
$this->config->setValueString($this->appName, 'clientId', $clientId);
7565
$this->config->setValueString($this->appName, 'clientSecret', $clientSecret);
7666
$this->config->setValueString($this->appName, 'authMethod', $authMethod);
77-
$this->config->setValueString($this->appName, 'quarantineFolder', $quarantineFolder);
78-
$this->config->setValueString($this->appName, 'scanOnlyThis', $scanOnlyThis);
79-
$this->config->setValueString($this->appName, 'doNotScanThis', $doNotScanThis);
80-
$this->config->setValueString($this->appName, 'notifyMails', $notifyMails);
8167
$this->config->setValueInt($this->appName, 'maxScanSizeInMB', (int)$maxScanSize);
8268
$this->config->setValueInt($this->appName, 'timeout', (int)$timeout);
8369
$this->config->setValueBool($this->appName, 'cache', $cache);
8470
$this->config->setValueBool($this->appName, 'hashlookup', $hashlookup);
8571
return new JSONResponse(['status' => 'success']);
8672
}
8773

88-
public function setadvancedconfig($tokenEndpoint, $vaasUrl): JSONResponse {
74+
public function setAdvancedConfig($tokenEndpoint, $vaasUrl): JSONResponse {
8975
$this->config->setValueString($this->appName, 'tokenEndpoint', $tokenEndpoint);
9076
$this->config->setValueString($this->appName, 'vaasUrl', $vaasUrl);
9177
return new JSONResponse(['status' => 'success']);
9278
}
9379

80+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
81+
public function setOperatorSettings(
82+
$quarantineFolder,
83+
$scanOnlyThis,
84+
$doNotScanThis,
85+
$notifyMails,
86+
): JSONResponse {
87+
if (!empty($notifyMails)) {
88+
$mails = explode(',', preg_replace('/\s+/', '', $notifyMails));
89+
foreach ($mails as $mail) {
90+
if ($this->mailer->validateMailAddress($mail) === false) {
91+
return new JSONResponse(['status' => 'error', 'message' => 'Invalid email address: ' . $mail]);
92+
}
93+
}
94+
}
95+
$this->config->setValueString($this->appName, 'quarantineFolder', $quarantineFolder);
96+
$this->config->setValueString($this->appName, 'scanOnlyThis', $scanOnlyThis);
97+
$this->config->setValueString($this->appName, 'doNotScanThis', $doNotScanThis);
98+
$this->config->setValueString($this->appName, 'notifyMails', $notifyMails);
99+
return new JSONResponse(['status' => 'success']);
100+
}
101+
102+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
94103
public function setAutoScan(bool $autoScanFiles): JSONResponse {
95104
$this->config->setValueBool($this->appName, 'autoScanFiles', $autoScanFiles);
96105
return new JSONResponse(['status' => 'success']);
97106
}
98107

108+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
99109
public function getAutoScan(): JSONResponse {
100110
return new JSONResponse(['status' => $this->config->getValueBool($this->appName, 'autoScanFiles')]);
101111
}
102112

113+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
103114
public function setPrefixMalicious(bool $prefixMalicious): JSONResponse {
104115
$this->config->setValueBool($this->appName, 'prefixMalicious', $prefixMalicious);
105116
return new JSONResponse(['status' => 'success']);
106117
}
107118

119+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
108120
public function getPrefixMalicious(): JSONResponse {
109121
return new JSONResponse(['status' => $this->config->getValueBool($this->appName, 'prefixMalicious')]);
110122
}
@@ -113,11 +125,13 @@ public function getAuthMethod(): JSONResponse {
113125
return new JSONResponse(['status' => $this->config->getValueString($this->appName, 'authMethod')]);
114126
}
115127

128+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
116129
public function setDisableUnscannedTag(bool $disableUnscannedTag): JSONResponse {
117130
$this->config->setValueBool($this->appName, 'disableUnscannedTag', $disableUnscannedTag);
118131
return new JSONResponse(['status' => 'success']);
119132
}
120133

134+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
121135
public function getDisableUnscannedTag(): JSONResponse {
122136
return new JSONResponse(['status' => $this->config->getValueBool($this->appName, 'disableUnscannedTag')]);
123137
}
@@ -127,6 +141,7 @@ public function resetAllTags(): JSONResponse {
127141
return new JSONResponse(['status' => 'success']);
128142
}
129143

144+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
130145
public function getCounters(): JSONResponse {
131146
try {
132147
$filesCount = $this->tagService->getScannedFilesCount();
@@ -143,12 +158,14 @@ public function getCounters(): JSONResponse {
143158
]);
144159
}
145160

161+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
146162
public function getSendMailOnVirusUpload(): JSONResponse {
147163
return new JSONResponse(
148164
['status' => $this->config->getValueBool($this->appName, 'sendMailOnVirusUpload')]
149165
);
150166
}
151167

168+
#[AuthorizedAdminSetting(settings: VaasOperator::class)]
152169
public function setSendMailOnVirusUpload(bool $sendMailOnVirusUpload): JSONResponse {
153170
$this->config->setValueBool($this->appName, 'sendMailOnVirusUpload', $sendMailOnVirusUpload);
154171
return new JSONResponse(['status' => 'success']);

lib/Settings/VaasAdmin.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,6 @@ public function getForm(): TemplateResponse {
4242
'vaasUrl',
4343
'https://gateway.staging.vaas.gdatasecurity.de'
4444
),
45-
'quarantineFolder'
46-
=> $this->config->getValueString(Application::APP_ID, 'quarantineFolder', 'Quarantine'),
47-
'autoScanFiles' => $this->config->getValueBool(Application::APP_ID, 'autoScanFiles'),
48-
'prefixMalicious'
49-
=> $this->config->getValueBool(Application::APP_ID, 'prefixMalicious', true),
50-
'disableUnscannedTag' => $this->config->getValueBool(Application::APP_ID, 'disableUnscannedTag'),
51-
'scanOnlyThis' => $this->config->getValueString(Application::APP_ID, 'scanOnlyThis'),
52-
'doNotScanThis' => $this->config->getValueString(Application::APP_ID, 'doNotScanThis'),
53-
'notifyMail' => $this->config->getValueString(Application::APP_ID, 'notifyMails'),
54-
'sendMailOnVirusUpload'
55-
=> $this->config->getValueBool(Application::APP_ID, 'sendMailOnVirusUpload'),
5645
'maxScanSizeInMB'
5746
=> $this->config->getValueInt(Application::APP_ID, 'maxScanSizeInMB', 256),
5847
'timeout' => $this->config->getValueInt(Application::APP_ID, 'timeout', 300),

0 commit comments

Comments
 (0)