Browse Source

Merge pull request #98 from jld3103/feature/25

Update nextcloud server and notifications to 25.0.0
pull/109/head
jld3103 2 years ago committed by GitHub
parent
commit
fa97f729d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      external/nextcloud-notifications
  2. 2
      external/nextcloud-server
  3. 1
      packages/neon/integration_test/screenshot_test.dart
  4. 1
      packages/neon/lib/main.dart
  5. 4
      packages/neon/lib/src/blocs/accounts.dart
  6. 74
      packages/neon/lib/src/blocs/user_status.dart
  7. 20
      packages/neon/lib/src/widgets/account_avatar.dart
  8. 41
      packages/nextcloud/lib/src/nextcloud.openapi.dart
  9. 6
      packages/nextcloud/lib/src/nextcloud.openapi.g.dart
  10. 62
      packages/nextcloud/lib/src/nextcloud.openapi.json
  11. 2
      packages/nextcloud/lib/src/version_supported.dart
  12. 4
      packages/nextcloud/test/helper.dart
  13. 0
      packages/nextcloud/test/overlay/.gitkeep
  14. 42
      packages/nextcloud/test/overlay/apps/user_status/appinfo/routes.php
  15. 114
      packages/nextcloud/test/overlay/apps/user_status/lib/Controller/HeartbeatController.php
  16. 22
      packages/nextcloud/test/user_status_test.dart
  17. 54
      specs/core.json
  18. 2
      specs/notifications.json
  19. 2
      specs/provisioning_api.json
  20. 2
      specs/templates/appinfo_core.xml
  21. 286
      specs/templates/core.json
  22. 2
      specs/templates/notifications.json
  23. 136
      specs/templates/provisioning_api.json
  24. 4
      specs/templates/user_status.json
  25. 12
      specs/user_status.json
  26. 5
      tool/Dockerfile.dev
  27. 1
      tool/update.sh

2
external/nextcloud-notifications vendored

@ -1 +1 @@
Subproject commit 7190056dd64da2f2c4b2fd3fd8d40d26cb768937
Subproject commit 65bb0849179cf93c161387a730f4abc79a782f77

2
external/nextcloud-server vendored

@ -1 +1 @@
Subproject commit 3aabb381b9e7ffc5b13f951b8fb89494fe903a2c
Subproject commit 20ea9a25353129b56d46951fe7d23939665ab2b2

1
packages/neon/integration_test/screenshot_test.dart

@ -115,6 +115,7 @@ Future pumpAppPage(
final accountsBloc = AccountsBloc(
requestManager,
platform,
Storage('accounts', sharedPreferences),
sharedPreferences,
globalOptions,

1
packages/neon/lib/main.dart

@ -42,6 +42,7 @@ Future main() async {
final accountsBloc = AccountsBloc(
requestManager,
platform,
Storage('accounts', sharedPreferences),
sharedPreferences,
globalOptions,

4
packages/neon/lib/src/blocs/accounts.dart

@ -29,6 +29,7 @@ abstract class AccountsBlocStates {
class AccountsBloc extends $AccountsBloc {
AccountsBloc(
this._requestManager,
this._platform,
this._storage,
this._sharedPreferences,
this._globalOptions,
@ -156,12 +157,13 @@ class AccountsBloc extends $AccountsBloc {
return _userStatusBlocs[account.id] = UserStatusBloc(
_requestManager,
_platform,
account,
_activeAccountSubject,
);
}
final RequestManager _requestManager;
final NeonPlatform _platform;
final Storage _storage;
final SharedPreferences _sharedPreferences;
final GlobalOptions _globalOptions;

74
packages/neon/lib/src/blocs/user_status.dart

@ -1,11 +1,11 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/neon.dart';
import 'package:nextcloud/nextcloud.dart';
import 'package:rx_bloc/rx_bloc.dart';
import 'package:rxdart/rxdart.dart';
import 'package:window_manager/window_manager.dart';
part 'user_status.rxb.g.dart';
@ -19,67 +19,47 @@ abstract class UserStatusBlocStates {
class UserStatusBloc extends $UserStatusBloc {
UserStatusBloc(
this._requestManager,
this._platform,
this._account,
this._activeAccountStream,
) {
_activeAccountStreamSubscription = _activeAccountStream.listen((final activeAccount) {
_cancelTimer();
final thisAccountActive = activeAccount == _account;
_timer = instantPeriodicTimer(
const Duration(minutes: 5),
(final _) async {
if (thisAccountActive) {
await _heartbeat();
}
_loadUserStatus();
},
);
});
}
void _loadUserStatus() {
// TODO: Fix for no user status
_requestManager
.wrapNextcloud<UserStatus?, UserStatusGetUserStatus>(
_account.client.id,
'user-status',
() async => _account.client.userStatus.getStatus(),
(final response) => response.ocs.data.userStatus,
previousData: _userStatusSubject.valueOrNull?.data,
)
.listen(_userStatusSubject.add);
_timer = instantPeriodicTimer(
const Duration(minutes: 5),
(final _) async {
await _heartbeat();
},
);
}
Future _heartbeat() async {
return;
// TODO: https://github.com/jld3103/nextcloud-neon/issues/10
// ignore: dead_code
try {
await _account.client.userStatus.heartbeat(status: UserStatusType.online);
} catch (e) {
debugPrint(e.toString());
}
}
void _cancelTimer() {
if (_timer != null) {
_timer!.cancel();
_timer = null;
}
final isAway =
_platform.canUseWindowManager && (!(await windowManager.isFocused()) || !(await windowManager.isVisible()));
_requestManager.wrapWithoutCache(
() async {
try {
return await _account.client.userStatus.heartbeat(
status: isAway ? UserStatusType.away : UserStatusType.online,
);
} on ApiException catch (e) {
if (e.statusCode == 204) {
return null;
}
rethrow;
}
},
).listen(_userStatusSubject.add);
}
final RequestManager _requestManager;
final NeonPlatform _platform;
final Account _account;
final BehaviorSubject<Account?> _activeAccountStream;
late final StreamSubscription<Account?> _activeAccountStreamSubscription;
Timer? _timer;
late Timer _timer;
final _userStatusSubject = BehaviorSubject<Result<UserStatus?>>();
@override
void dispose() {
_cancelTimer();
_timer.cancel();
unawaited(_activeAccountStreamSubscription.cancel());
unawaited(_userStatusSubject.close());
super.dispose();

20
packages/neon/lib/src/widgets/account_avatar.dart

@ -12,6 +12,7 @@ class AccountAvatar extends StatelessWidget {
@override
Widget build(final BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final size = (kAvatarSize * MediaQuery.of(context).devicePixelRatio).toInt();
return Stack(
alignment: Alignment.center,
@ -21,11 +22,20 @@ class AccountAvatar extends StatelessWidget {
child: ClipOval(
child: CachedAPIImage(
account: account,
cacheKey: 'avatar-${account.id}-$size',
download: () async => account.client.core.getAvatar(
userId: account.username,
size: size,
),
cacheKey: 'avatar-${account.id}-${isDark ? 'dark' : 'light'}$size',
download: () async {
if (isDark) {
return account.client.core.getDarkAvatar(
userId: account.username,
size: size,
);
} else {
return account.client.core.getAvatar(
userId: account.username,
size: size,
);
}
},
),
),
),

41
packages/nextcloud/lib/src/nextcloud.openapi.dart

@ -209,6 +209,8 @@ class CoreServerCapabilities_Ocs_Data_Capabilities_Core {
CoreServerCapabilities_Ocs_Data_Capabilities_Core({
required this.pollinterval,
required this.webdavRoot,
required this.referenceApi,
required this.referenceRegex,
});
factory CoreServerCapabilities_Ocs_Data_Capabilities_Core.fromJson(Map<String, dynamic> json) =>
@ -219,6 +221,12 @@ class CoreServerCapabilities_Ocs_Data_Capabilities_Core {
@JsonKey(name: 'webdav-root')
final String webdavRoot;
@JsonKey(name: 'reference-api')
final bool referenceApi;
@JsonKey(name: 'reference-regex')
final String referenceRegex;
// coverage:ignore-start
Map<String, dynamic> toJson() => _$CoreServerCapabilities_Ocs_Data_Capabilities_CoreToJson(this);
// coverage:ignore-end
@ -560,11 +568,16 @@ class CoreServerCapabilities_Ocs_Data_Capabilities_Ocm {
@JsonSerializable()
class CoreServerCapabilities_Ocs_Data_Capabilities_Dav {
CoreServerCapabilities_Ocs_Data_Capabilities_Dav({required this.chunking});
CoreServerCapabilities_Ocs_Data_Capabilities_Dav({
this.bulkupload,
required this.chunking,
});
factory CoreServerCapabilities_Ocs_Data_Capabilities_Dav.fromJson(Map<String, dynamic> json) =>
_$CoreServerCapabilities_Ocs_Data_Capabilities_DavFromJson(json);
final String? bulkupload;
final String chunking;
// coverage:ignore-start
@ -1593,6 +1606,28 @@ class CoreClient {
throw ApiException.fromResponse(response); // coverage:ignore-line
}
Future<Uint8List> getDarkAvatar({
required String userId,
required int size,
}) async {
var path = '/avatar/{userId}/{size}/dark';
final queryParameters = <String, dynamic>{};
final headers = <String, String>{};
Uint8List? body;
path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId.toString()));
path = path.replaceAll('{size}', Uri.encodeQueryComponent(size.toString()));
final response = await rootClient.doRequest(
'get',
Uri(path: path, queryParameters: queryParameters).toString(),
headers,
body,
);
if (response.statusCode == 200) {
return response.body;
}
throw ApiException.fromResponse(response); // coverage:ignore-line
}
Future<Uint8List> getAvatar({
required String userId,
required int size,
@ -3818,7 +3853,7 @@ class UserStatusClient {
throw ApiException.fromResponse(response); // coverage:ignore-line
}
Future heartbeat({required UserStatusType status}) async {
Future<UserStatus> heartbeat({required UserStatusType status}) async {
var path = '/ocs/v1.php/apps/user_status/api/v1/heartbeat';
final queryParameters = <String, dynamic>{};
final headers = <String, String>{};
@ -3831,7 +3866,7 @@ class UserStatusClient {
body,
);
if (response.statusCode == 200) {
return;
return UserStatus.fromJson(json.decode(utf8.decode(response.body)) as Map<String, dynamic>);
}
throw ApiException.fromResponse(response); // coverage:ignore-line
}

6
packages/nextcloud/lib/src/nextcloud.openapi.g.dart

@ -70,6 +70,8 @@ CoreServerCapabilities_Ocs_Data_Capabilities_Core _$CoreServerCapabilities_Ocs_D
CoreServerCapabilities_Ocs_Data_Capabilities_Core(
pollinterval: json['pollinterval'] as int,
webdavRoot: json['webdav-root'] as String,
referenceApi: json['reference-api'] as bool,
referenceRegex: json['reference-regex'] as String,
);
Map<String, dynamic> _$CoreServerCapabilities_Ocs_Data_Capabilities_CoreToJson(
@ -77,6 +79,8 @@ Map<String, dynamic> _$CoreServerCapabilities_Ocs_Data_Capabilities_CoreToJson(
<String, dynamic>{
'pollinterval': instance.pollinterval,
'webdav-root': instance.webdavRoot,
'reference-api': instance.referenceApi,
'reference-regex': instance.referenceRegex,
};
CoreServerCapabilities_Ocs_Data_Capabilities_Bruteforce
@ -345,12 +349,14 @@ Map<String, dynamic> _$CoreServerCapabilities_Ocs_Data_Capabilities_OcmToJson(
CoreServerCapabilities_Ocs_Data_Capabilities_Dav _$CoreServerCapabilities_Ocs_Data_Capabilities_DavFromJson(
Map<String, dynamic> json) =>
CoreServerCapabilities_Ocs_Data_Capabilities_Dav(
bulkupload: json['bulkupload'] as String?,
chunking: json['chunking'] as String,
);
Map<String, dynamic> _$CoreServerCapabilities_Ocs_Data_Capabilities_DavToJson(
CoreServerCapabilities_Ocs_Data_Capabilities_Dav instance) =>
<String, dynamic>{
'bulkupload': instance.bulkupload,
'chunking': instance.chunking,
};

62
packages/nextcloud/lib/src/nextcloud.openapi.json

@ -182,7 +182,9 @@
"type": "object",
"required": [
"pollinterval",
"webdav-root"
"webdav-root",
"reference-api",
"reference-regex"
],
"properties": {
"pollinterval": {
@ -190,6 +192,12 @@
},
"webdav-root": {
"type": "string"
},
"reference-api": {
"type": "boolean"
},
"reference-regex": {
"type": "string"
}
}
},
@ -466,6 +474,9 @@
"chunking"
],
"properties": {
"bulkupload": {
"type": "string"
},
"chunking": {
"type": "string"
}
@ -2299,6 +2310,45 @@
}
}
},
"/avatar/{userId}/{size}/dark": {
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "size",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"get": {
"operationId": "get-dark-avatar",
"tags": [
"core"
],
"responses": {
"200": {
"description": "",
"content": {
"image/png": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
}
}
},
"/avatar/{userId}/{size}": {
"parameters": [
{
@ -3678,7 +3728,6 @@
}
},
"/ocs/v1.php/apps/user_status/api/v1/heartbeat": {
"description": "Depends on https://github.com/nextcloud/server/pull/32646",
"put": {
"operationId": "heartbeat",
"tags": [
@ -3696,7 +3745,14 @@
],
"responses": {
"200": {
"description": ""
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserStatus"
}
}
}
}
}
}

2
packages/nextcloud/lib/src/version_supported.dart

@ -4,7 +4,7 @@ part of '../nextcloud.dart';
extension CoreVersionSupported on CoreClient {
/// Checks if the app on the server is supported by the client
Future<bool> isSupported([final CoreServerCapabilities_Ocs_Data? capabilities]) async =>
(capabilities ?? (await getCapabilities()).ocs.data).version.major == 24;
(capabilities ?? (await getCapabilities()).ocs.data).version.major == 25;
}
// ignore: public_member_api_docs

4
packages/nextcloud/test/helper.dart

@ -8,7 +8,7 @@ import 'package:nextcloud/nextcloud.dart';
import 'package:process_run/cmd_run.dart';
import 'package:test/test.dart';
const String nextcloudVersion = '24.0.6';
const String nextcloudVersion = '25.0.0';
const String defaultUsername = 'user1';
const String defaultPassword = 'user1';
@ -250,8 +250,6 @@ class TestDockerHelper {
'RUN ./occ maintenance:install --admin-pass admin --admin-email admin@example.com',
'RUN ./occ app:disable password_policy',
'RUN ./occ config:system:set allow_local_remote_servers --value=true',
'RUN sed -i "s/localhost/host.docker.internal/" /usr/src/nextcloud/apps/notifications/lib/Controller/PushController.php',
'ADD overlay /usr/src/nextcloud/',
generateCreateTestUserInstruction(),
if (apps != null) ...[
for (final app in apps) ...[

0
packages/nextcloud/test/overlay/.gitkeep

42
packages/nextcloud/test/overlay/apps/user_status/appinfo/routes.php

@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020, Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or 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.
*
* 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/>.
*
*/
return [
'ocs' => [
// Routes for querying statuses
['name' => 'Statuses#findAll', 'url' => '/api/v1/statuses', 'verb' => 'GET'],
['name' => 'Statuses#find', 'url' => '/api/v1/statuses/{userId}', 'verb' => 'GET'],
// Routes for manipulating your own status
['name' => 'UserStatus#getStatus', 'url' => '/api/v1/user_status', 'verb' => 'GET'],
['name' => 'UserStatus#setStatus', 'url' => '/api/v1/user_status/status', 'verb' => 'PUT'],
['name' => 'UserStatus#setPredefinedMessage', 'url' => '/api/v1/user_status/message/predefined', 'verb' => 'PUT'],
['name' => 'UserStatus#setCustomMessage', 'url' => '/api/v1/user_status/message/custom', 'verb' => 'PUT'],
['name' => 'UserStatus#clearMessage', 'url' => '/api/v1/user_status/message', 'verb' => 'DELETE'],
// Routes for listing default routes
['name' => 'PredefinedStatus#findAll', 'url' => '/api/v1/predefined_statuses/', 'verb' => 'GET'],
// Route for doing heartbeats
['name' => 'Heartbeat#heartbeat', 'url' => '/api/v1/heartbeat', 'verb' => 'PUT'],
],
];

114
packages/nextcloud/test/overlay/apps/user_status/lib/Controller/HeartbeatController.php

@ -1,114 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020, Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or 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.
*
* 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/>.
*
*/
namespace OCA\UserStatus\Controller;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Service\StatusService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IRequest;
use OCP\IUserSession;
use OCP\User\Events\UserLiveStatusEvent;
use OCP\UserStatus\IUserStatus;
class HeartbeatController extends OCSController {
/** @var IEventDispatcher */
private $eventDispatcher;
/** @var IUserSession */
private $userSession;
/** @var ITimeFactory */
private $timeFactory;
/** @var StatusService */
private $service;
public function __construct(string $appName,
IRequest $request,
IEventDispatcher $eventDispatcher,
IUserSession $userSession,
ITimeFactory $timeFactory,
StatusService $service) {
parent::__construct($appName, $request);
$this->eventDispatcher = $eventDispatcher;
$this->userSession = $userSession;
$this->timeFactory = $timeFactory;
$this->service = $service;
}
/**
* @NoAdminRequired
*
* @param string $status
* @return JSONResponse
*/
public function heartbeat(string $status): JSONResponse {
if (!\in_array($status, [IUserStatus::ONLINE, IUserStatus::AWAY], true)) {
return new JSONResponse([], Http::STATUS_BAD_REQUEST);
}
$user = $this->userSession->getUser();
if ($user === null) {
return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
}
$event = new UserLiveStatusEvent(
$user,
$status,
$this->timeFactory->getTime()
);
$this->eventDispatcher->dispatchTyped($event);
$userStatus = $event->getUserStatus();
if (!$userStatus) {
return new JSONResponse([], Http::STATUS_NO_CONTENT);
}
/** @psalm-suppress UndefinedInterfaceMethod */
return new JSONResponse($this->formatStatus($userStatus->getInternal()));
}
private function formatStatus(UserStatus $status): array {
return [
'userId' => $status->getUserId(),
'message' => $status->getCustomMessage(),
'messageId' => $status->getMessageId(),
'messageIsPredefined' => $status->getMessageId() !== null,
'icon' => $status->getCustomIcon(),
'clearAt' => $status->getClearAt(),
'status' => $status->getStatus(),
'statusIsUserDefined' => $status->getIsUserDefined(),
];
}
}

22
packages/nextcloud/test/user_status_test.dart

@ -158,18 +158,16 @@ Future main() async {
});
test('Heartbeat', () async {
await client.userStatus.heartbeat(status: UserStatusType.online);
final response = await client.userStatus.getStatus();
expect(response.ocs.data.userStatus!.userId, 'user1');
expect(response.ocs.data.userStatus!.message, null);
expect(response.ocs.data.userStatus!.messageId, null);
expect(response.ocs.data.userStatus!.messageIsPredefined, false);
expect(response.ocs.data.userStatus!.icon, null);
expect(response.ocs.data.userStatus!.clearAt.userStatusClearAt, null);
expect(response.ocs.data.userStatus!.clearAt.int_, null);
expect(response.ocs.data.userStatus!.status, UserStatusType.online);
expect(response.ocs.data.userStatus!.statusIsUserDefined, false);
final response = await client.userStatus.heartbeat(status: UserStatusType.online);
expect(response.userId, 'user1');
expect(response.message, null);
expect(response.messageId, null);
expect(response.messageIsPredefined, false);
expect(response.icon, null);
expect(response.clearAt.userStatusClearAt, null);
expect(response.clearAt.int_, null);
expect(response.status, UserStatusType.online);
expect(response.statusIsUserDefined, false);
});
});
}

54
specs/core.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Core",
"version": "24.0.6",
"version": "25.0.0",
"description": "Core functionality of Nextcloud",
"license": {
"name": "agpl",
@ -168,7 +168,9 @@
"type": "object",
"required": [
"pollinterval",
"webdav-root"
"webdav-root",
"reference-api",
"reference-regex"
],
"properties": {
"pollinterval": {
@ -176,6 +178,12 @@
},
"webdav-root": {
"type": "string"
},
"reference-api": {
"type": "boolean"
},
"reference-regex": {
"type": "string"
}
}
},
@ -452,6 +460,9 @@
"chunking"
],
"properties": {
"bulkupload": {
"type": "string"
},
"chunking": {
"type": "string"
}
@ -1249,6 +1260,45 @@
}
}
},
"/avatar/{userId}/{size}/dark": {
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "size",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"get": {
"operationId": "get-dark-avatar",
"tags": [
"core"
],
"responses": {
"200": {
"description": "",
"content": {
"image/png": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
}
}
}
},
"/avatar/{userId}/{size}": {
"parameters": [
{

2
specs/notifications.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Notifications",
"version": "2.12.1",
"version": "2.13.1",
"description": "This app provides a backend and frontend for the notification API available in Nextcloud.",
"license": {
"name": "agpl",

2
specs/provisioning_api.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Provisioning API",
"version": "1.14.0",
"version": "1.15.0",
"description": "This application enables a set of APIs that external systems can use to manage users, groups and apps.",
"license": {
"name": "agpl",

2
specs/templates/appinfo_core.xml

@ -4,6 +4,6 @@
<name>Core</name>
<summary>Core functionality of Nextcloud</summary>
<description><![CDATA[Core functionality of Nextcloud]]></description>
<version>24.0.6</version>
<version>25.0.0</version>
<licence>agpl</licence>
</info>

286
specs/templates/core.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Core",
"version": "24.0.6",
"version": "25.0.0",
"description": "Core functionality of Nextcloud",
"license": {
"name": "agpl",
@ -199,6 +199,44 @@
}
}
},
"/core/avatar/{userId}/{size}/dark": {
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "size",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"get": {
"operationId": "avatar-getavatardark-TODO",
"tags": [
"core"
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/core/avatar/{userId}/{size}": {
"parameters": [
{
@ -247,7 +285,7 @@
{
"name": "path",
"in": "query",
"required": true,
"required": false,
"schema": {
"type": "string"
}
@ -295,7 +333,7 @@
{
"name": "crop",
"in": "query",
"required": true,
"required": false,
"schema": {
"type": "array"
}
@ -335,6 +373,44 @@
}
}
},
"/core/avatar/guest/{guestName}/{size}/dark": {
"parameters": [
{
"name": "guestName",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "size",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"get": {
"operationId": "guestavatar-getavatardark-TODO",
"tags": [
"core"
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/core/avatar/guest/{guestName}/{size}": {
"parameters": [
{
@ -361,6 +437,17 @@
"tags": [
"core"
],
"parameters": [
{
"name": "darkTheme",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 0
}
}
],
"responses": {
"200": {
"description": "",
@ -1318,18 +1405,10 @@
}
}
},
"/core/svg/core/{folder}/{fileName}": {
"/core/core/references/preview/{referenceId}": {
"parameters": [
{
"name": "folder",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "fileName",
"name": "referenceId",
"in": "path",
"required": true,
"schema": {
@ -1338,70 +1417,10 @@
}
],
"get": {
"operationId": "svg-getsvgfromcore-TODO",
"operationId": "reference-preview-TODO",
"tags": [
"core"
],
"parameters": [
{
"name": "color",
"in": "query",
"required": false,
"schema": {
"type": "string",
"default": "ffffff"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/core/svg/{app}/{fileName}": {
"parameters": [
{
"name": "app",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "fileName",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"get": {
"operationId": "svg-getsvgfromapp-TODO",
"tags": [
"core"
],
"parameters": [
{
"name": "color",
"in": "query",
"required": false,
"schema": {
"type": "string",
"default": "ffffff"
}
}
],
"responses": {
"200": {
"description": "",
@ -1980,7 +1999,7 @@
{
"name": "itemType",
"in": "query",
"required": true,
"required": false,
"schema": {
"type": "string"
}
@ -1988,7 +2007,7 @@
{
"name": "itemId",
"in": "query",
"required": true,
"required": false,
"schema": {
"type": "string"
}
@ -2418,6 +2437,121 @@
}
}
},
"/ocs/v1.php/core/resolve": {
"get": {
"operationId": "referenceapi-resolveone-TODO",
"tags": [
"core"
],
"parameters": [
{
"name": "reference",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
},
"post": {
"operationId": "referenceapi-resolve-TODO",
"tags": [
"core"
],
"parameters": [
{
"name": "references",
"in": "query",
"required": true,
"schema": {
"type": "array"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/ocs/v1.php/core/extract": {
"post": {
"operationId": "referenceapi-extract-TODO",
"tags": [
"core"
],
"parameters": [
{
"name": "text",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "resolve",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 0
}
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/ocs/v1.php/core/{targetUserId}": {
"parameters": [
{

2
specs/templates/notifications.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Notifications",
"version": "2.12.1",
"version": "2.13.1",
"description": "This app provides a backend and frontend for the notification API available in Nextcloud.",
"license": {
"name": "agpl",

136
specs/templates/provisioning_api.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Provisioning API",
"version": "1.14.0",
"version": "1.15.0",
"description": "This application enables a set of APIs that external systems can use to manage users, groups and apps.",
"license": {
"name": "agpl",
@ -1317,6 +1317,140 @@
}
}
},
"/ocs/v1.php/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}": {
"parameters": [
{
"name": "appId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "configKey",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"post": {
"operationId": "preferences-setpreference-TODO",
"tags": [
"provisioning_api"
],
"parameters": [
{
"name": "configValue",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
},
"delete": {
"operationId": "preferences-deletepreference-TODO",
"tags": [
"provisioning_api"
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/ocs/v1.php/apps/provisioning_api/api/v1/config/users/{appId}": {
"parameters": [
{
"name": "appId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"post": {
"operationId": "preferences-setmultiplepreferences-TODO",
"tags": [
"provisioning_api"
],
"parameters": [
{
"name": "configs",
"in": "query",
"required": true,
"schema": {
"type": "array"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
},
"delete": {
"operationId": "preferences-deletemultiplepreference-TODO",
"tags": [
"provisioning_api"
],
"parameters": [
{
"name": "configKeys",
"in": "query",
"required": true,
"schema": {
"type": "array"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/apps/provisioning_api/mailVerification/{key}/{token}/{userId}": {
"parameters": [
{

4
specs/templates/user_status.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "User status",
"version": "1.4.0",
"version": "1.5.0",
"description": "User status",
"license": {
"name": "agpl",
@ -257,7 +257,7 @@
}
}
},
"/apps/user_status/heartbeat": {
"/ocs/v1.php/apps/user_status/api/v1/heartbeat": {
"put": {
"operationId": "heartbeat-heartbeat-TODO",
"tags": [

12
specs/user_status.json

@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "User status",
"version": "1.4.0",
"version": "1.5.0",
"description": "User status",
"license": {
"name": "agpl",
@ -542,7 +542,6 @@
}
},
"/ocs/v1.php/apps/user_status/api/v1/heartbeat": {
"description": "Depends on https://github.com/nextcloud/server/pull/32646",
"put": {
"operationId": "heartbeat",
"tags": [
@ -560,7 +559,14 @@
],
"responses": {
"200": {
"description": ""
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserStatus"
}
}
}
}
}
}

5
tool/Dockerfile.dev

@ -1,4 +1,4 @@
FROM nextcloud:24.0.6
FROM nextcloud:25.0.0
WORKDIR /usr/src/nextcloud
RUN chown -R www-data:www-data .
USER www-data
@ -8,9 +8,6 @@ RUN ./occ app:disable password_policy
RUN ./occ config:system:set allow_local_remote_servers --value=true
RUN ./occ config:system:set trusted_domains 1 --value=10.0.2.2
RUN sed -i "s/localhost/host.docker.internal/" /usr/src/nextcloud/apps/notifications/lib/Controller/PushController.php
ADD overlay /usr/src/nextcloud/
RUN OC_PASS="user1" ./occ user:add --password-from-env --display-name "User One" user1
RUN OC_PASS="user2" ./occ user:add --password-from-env --display-name "User Two" user2

1
tool/update.sh

@ -24,6 +24,7 @@ elif [ -d "external/nextcloud-$1" ]; then
git fetch --tags
latest_tag="$(git tag --sort=v:refname | grep -vi "rc" | grep -vi "alpha" | grep -vi "beta" | tail -n 1)"
git reset --hard "$latest_tag"
git submodule update
)
else
echo "$1 not found"

Loading…
Cancel
Save