Merge pull request #56534 from nextcloud/backport/56520/stable31
Some checks are pending
Integration sqlite / changes (push) Waiting to run
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, --tags ~@large files_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, capabilities_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, collaboration_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, comments_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, dav_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, federation_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, file_conversions) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, files_reminders) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, filesdrop_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, ldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, openldap_numerical_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, remoteapi_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, setup_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharees_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, sharing_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, theming_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite (stable31, 8.1, stable31, videoverification_features) (push) Blocked by required conditions
Integration sqlite / integration-sqlite-summary (push) Blocked by required conditions
Psalm static code analysis / static-code-analysis (push) Waiting to run
Psalm static code analysis / static-code-analysis-security (push) Waiting to run
Psalm static code analysis / static-code-analysis-ocp (push) Waiting to run
Psalm static code analysis / static-code-analysis-ncu (push) Waiting to run

This commit is contained in:
John Molakvoæ 2025-11-26 10:37:45 +01:00 committed by GitHub
commit 66002ff93e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 160 additions and 7 deletions

View file

@ -62,6 +62,7 @@ jobs:
- '--tags ~@large files_features'
- 'filesdrop_features'
- 'file_conversions'
- 'files_reminders'
- 'openldap_features'
- 'openldap_numerical_features'
- 'ldap_features'

View file

@ -82,6 +82,10 @@ class ApiController extends OCSController {
public function set(int $fileId, string $dueDate): DataResponse {
try {
$dueDate = (new DateTime($dueDate))->setTimezone(new DateTimeZone('UTC'));
$nowDate = (new DateTime('now'))->setTimezone(new DateTimeZone('UTC'));
if ($dueDate <= $nowDate) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
return new DataResponse([], Http::STATUS_BAD_REQUEST);

View file

@ -131,6 +131,16 @@ default:
- admin
- admin
regular_user_password: 123456
files_reminders:
paths:
- "%paths.base%/../files_reminders"
contexts:
- FilesRemindersContext:
baseUrl: http://localhost:8080
admin:
- admin
- admin
regular_user_password: 123456
capabilities:
paths:
- "%paths.base%/../capabilities_features"

View file

@ -115,18 +115,27 @@ trait BasicStructure {
}
/**
* Parses the xml answer to get ocs response which doesn't match with
* Parses the xml or json answer to get ocs response which doesn't match with
* http one in v1 of the api.
*
* @param ResponseInterface $response
* @return string
*/
public function getOCSResponse($response) {
$body = simplexml_load_string((string)$response->getBody());
if ($body === false) {
throw new \RuntimeException('Could not parse OCS response, body is not valid XML');
public function getOCSResponseCode($response): int {
if ($response === null) {
throw new \RuntimeException('No response available');
}
return $body->meta[0]->statuscode;
$body = (string)$response->getBody();
if (str_starts_with($body, '<')) {
$body = simplexml_load_string($body);
if ($body === false) {
throw new \RuntimeException('Could not parse OCS response, body is not valid XML');
}
return (int)$body->meta[0]->statuscode;
}
return json_decode($body, true)['ocs']['meta']['statuscode'];
}
/**
@ -256,7 +265,7 @@ trait BasicStructure {
* @param int $statusCode
*/
public function theOCSStatusCodeShouldBe($statusCode) {
Assert::assertEquals($statusCode, $this->getOCSResponse($this->response));
Assert::assertEquals($statusCode, $this->getOCSResponseCode($this->response));
}
/**

View file

@ -0,0 +1,96 @@
<?php
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
use Behat\Behat\Context\Context;
use PHPUnit\Framework\Assert;
require __DIR__ . '/../../vendor/autoload.php';
/**
* Files reminders context.
*/
class FilesRemindersContext implements Context {
use BasicStructure;
use WebDav;
/**
* @When the user sets a reminder for :path with due date :dueDate
*/
public function settingAReminderForFileWithDueDate($path, $dueDate) {
$fileId = $this->getFileIdForPath($this->currentUser, $path);
$this->sendRequestForJSON(
'PUT',
'/apps/files_reminders/api/v1/' . $fileId,
['dueDate' => $dueDate],
['OCS-APIREQUEST' => 'true']
);
}
/**
* @Then the user sees the reminder for :path is set to :dueDate
*/
public function retrievingTheReminderForFile($path, $dueDate) {
$fileId = $this->getFileIdForPath($this->currentUser, $path);
$this->sendRequestForJSON(
'GET',
'/apps/files_reminders/api/v1/' . $fileId,
null,
['OCS-APIREQUEST' => 'true']
);
$response = $this->getDueDateFromOCSResponse();
Assert::assertEquals($dueDate, $response);
}
/**
* @Then the user sees the reminder for :path is not set
*/
public function retrievingTheReminderForFileIsNotSet($path) {
$fileId = $this->getFileIdForPath($this->currentUser, $path);
$this->sendRequestForJSON(
'GET',
'/apps/files_reminders/api/v1/' . $fileId,
null,
['OCS-APIREQUEST' => 'true']
);
$response = $this->getDueDateFromOCSResponse();
Assert::assertNull($response);
}
/**
* @When the user removes the reminder for :path
*/
public function removingTheReminderForFile($path) {
$fileId = $this->getFileIdForPath($this->currentUser, $path);
$this->sendRequestForJSON(
'DELETE',
'/apps/files_reminders/api/v1/' . $fileId,
null,
['OCS-APIREQUEST' => 'true']
);
}
/**
* Check the due date from OCS response
*/
private function getDueDateFromOCSResponse(): ?string {
if ($this->response === null) {
throw new \RuntimeException('No response available');
}
$body = (string)$this->response->getBody();
if (str_starts_with($body, '<')) {
$body = simplexml_load_string($body);
if ($body === false) {
throw new \RuntimeException('Could not parse OCS response, body is not valid XML');
}
return $body->data->dueDate;
}
$body = json_decode($body, true);
return $body['ocs']['data']['dueDate'] ?? null;
}
}

View file

@ -0,0 +1,33 @@
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-only
Feature: Files reminders
Background:
Given using api version "2"
Scenario: Set a reminder with a past due date
Given user "user0" exists
Given As an "user0"
Given User "user0" uploads file "data/textfile.txt" to "/file.txt"
When the user sets a reminder for "/file.txt" with due date "2000-01-01T00:00:00Z"
Then the OCS status code should be "400"
Then the user sees the reminder for "/file.txt" is not set
Scenario: Set a reminder with a valid due date
Given user "user1" exists
Given As an "user1"
Given User "user1" uploads file "data/textfile.txt" to "/file.txt"
When the user sets a reminder for "/file.txt" with due date "2100-01-01T00:00:00Z"
Then the OCS status code should be "201"
Then the user sees the reminder for "/file.txt" is set to "2100-01-01T00:00:00+00:00"
Scenario: Remove a reminder
Given user "user2" exists
Given As an "user2"
Given User "user2" uploads file "data/textfile.txt" to "/file.txt"
When the user sets a reminder for "/file.txt" with due date "2100-01-01T00:00:00Z"
Then the OCS status code should be "201"
Then the user sees the reminder for "/file.txt" is set to "2100-01-01T00:00:00+00:00"
When the user removes the reminder for "/file.txt"
Then the OCS status code should be "200"
Then the user sees the reminder for "/file.txt" is not set