From 5509319a8bec4ea4d869346ea145deb2b511dee6 Mon Sep 17 00:00:00 2001 From: jld3103 Date: Thu, 14 Jul 2022 17:10:39 +0200 Subject: [PATCH 1/2] nextcloud_push_proxy: Minimal library implementation --- .github/workflows/dart.yml | 30 +++- .idea/nextcloud-harbour.iml | 5 + packages/nextcloud_push_proxy/.gitignore | 10 ++ packages/nextcloud_push_proxy/LICENSE | 12 ++ .../analysis_options.yaml | 5 + .../lib/nextcloud_push_proxy.dart | 143 ++++++++++++++++++ packages/nextcloud_push_proxy/mono_pkg.yaml | 7 + packages/nextcloud_push_proxy/pubspec.yaml | 15 ++ 8 files changed, 221 insertions(+), 6 deletions(-) create mode 100644 packages/nextcloud_push_proxy/.gitignore create mode 100644 packages/nextcloud_push_proxy/LICENSE create mode 100644 packages/nextcloud_push_proxy/analysis_options.yaml create mode 100644 packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart create mode 100644 packages/nextcloud_push_proxy/mono_pkg.yaml create mode 100644 packages/nextcloud_push_proxy/pubspec.yaml diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 08b11ef143a..4df1fc8aa14 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -35,16 +35,16 @@ jobs: - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: - name: "analyze; PKGS: packages/file_icons, packages/harbour, packages/nextcloud, packages/settings, packages/sort_box, packages/spec_templates; `dart format --output=none --set-exit-if-changed --line-length 120 .`" + name: "analyze; PKGS: packages/file_icons, packages/harbour, packages/nextcloud, packages/nextcloud_push_proxy, packages/settings, packages/sort_box, packages/spec_templates; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@4504faf7e9bcf8f3ed0bc863c4e1d21499ab8ef8 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/settings-packages/sort_box-packages/spec_templates;commands:format" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/nextcloud_push_proxy-packages/settings-packages/sort_box-packages/spec_templates;commands:format" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/settings-packages/sort_box-packages/spec_templates + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/nextcloud_push_proxy-packages/settings-packages/sort_box-packages/spec_templates os:ubuntu-latest;pub-cache-hosted;sdk:stable os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -80,6 +80,15 @@ jobs: if: "always() && steps.packages_nextcloud_pub_upgrade.conclusion == 'success'" working-directory: packages/nextcloud run: "dart format --output=none --set-exit-if-changed --line-length 120 ." + - id: packages_nextcloud_push_proxy_pub_upgrade + name: packages/nextcloud_push_proxy; flutter pub pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/nextcloud_push_proxy + run: flutter pub pub upgrade + - name: "packages/nextcloud_push_proxy; dart format --output=none --set-exit-if-changed --line-length 120 ." + if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'" + working-directory: packages/nextcloud_push_proxy + run: "dart format --output=none --set-exit-if-changed --line-length 120 ." - id: packages_settings_pub_upgrade name: packages/settings; flutter pub pub upgrade if: "always() && steps.checkout.conclusion == 'success'" @@ -158,16 +167,16 @@ jobs: needs: - job_001 job_004: - name: "analyze; PKGS: packages/nextcloud, packages/sort_box, packages/spec_templates; `dart analyze`" + name: "analyze; PKGS: packages/nextcloud, packages/nextcloud_push_proxy, packages/sort_box, packages/spec_templates; `dart analyze`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies uses: actions/cache@4504faf7e9bcf8f3ed0bc863c4e1d21499ab8ef8 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/sort_box-packages/spec_templates;commands:analyze_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/nextcloud_push_proxy-packages/sort_box-packages/spec_templates;commands:analyze_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/sort_box-packages/spec_templates + os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/nextcloud_push_proxy-packages/sort_box-packages/spec_templates os:ubuntu-latest;pub-cache-hosted;sdk:stable os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest @@ -185,6 +194,15 @@ jobs: if: "always() && steps.packages_nextcloud_pub_upgrade.conclusion == 'success'" working-directory: packages/nextcloud run: dart analyze + - id: packages_nextcloud_push_proxy_pub_upgrade + name: packages/nextcloud_push_proxy; dart pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: packages/nextcloud_push_proxy + run: dart pub upgrade + - name: packages/nextcloud_push_proxy; dart analyze + if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'" + working-directory: packages/nextcloud_push_proxy + run: dart analyze - id: packages_sort_box_pub_upgrade name: packages/sort_box; dart pub upgrade if: "always() && steps.checkout.conclusion == 'success'" diff --git a/.idea/nextcloud-harbour.iml b/.idea/nextcloud-harbour.iml index 4db18808617..1078fb02a35 100644 --- a/.idea/nextcloud-harbour.iml +++ b/.idea/nextcloud-harbour.iml @@ -44,6 +44,11 @@ + + + + + diff --git a/packages/nextcloud_push_proxy/.gitignore b/packages/nextcloud_push_proxy/.gitignore new file mode 100644 index 00000000000..65c34dc86e3 --- /dev/null +++ b/packages/nextcloud_push_proxy/.gitignore @@ -0,0 +1,10 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build outputs. +build/ + +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/packages/nextcloud_push_proxy/LICENSE b/packages/nextcloud_push_proxy/LICENSE new file mode 100644 index 00000000000..195a269712b --- /dev/null +++ b/packages/nextcloud_push_proxy/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2022, jld3103 +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/nextcloud_push_proxy/analysis_options.yaml b/packages/nextcloud_push_proxy/analysis_options.yaml new file mode 100644 index 00000000000..0cc523ce327 --- /dev/null +++ b/packages/nextcloud_push_proxy/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:nit_picking/dart.yaml + +linter: + rules: + prefer_final_parameters: false # Disabled until super.X is no longer complained about in constructors diff --git a/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart b/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart new file mode 100644 index 00000000000..56bbff58edd --- /dev/null +++ b/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart @@ -0,0 +1,143 @@ +// ignore_for_file: public_member_api_docs + +library nextcloud_push_proxy; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:shelf/shelf.dart'; +import 'package:shelf/shelf_io.dart'; +import 'package:shelf_router/shelf_router.dart'; + +/// Implements the listening part of a Nextcloud push proxy +class NextcloudPushProxy { + HttpServer? _server; + + late StreamController _onNewDeviceController; + late StreamController _onNewNotificationController; + + Stream? _onNewDeviceStream; + Stream? _onNewNotificationStream; + + /// Listens for new devices + Stream get onNewDevice { + if (_onNewDeviceStream == null) { + throw Exception('Server not created'); + } + return _onNewDeviceStream!; + } + + /// Listens for new notifications + Stream get onNewNotification { + if (_onNewNotificationStream == null) { + throw Exception('Server not created'); + } + return _onNewNotificationStream!; + } + + late final _router = Router() + ..post('/devices', _devicesHandler) + ..post('/notifications', _notificationsHandler); + + Future _devicesHandler(Request request) async { + final data = Uri(query: await request.readAsString()).queryParameters; + _onNewDeviceController.add( + PushProxyDevice( + pushToken: data['pushToken']!, + deviceIdentifier: data['deviceIdentifier']!, + deviceIdentifierSignature: data['deviceIdentifierSignature']!, + userPublicKey: data['userPublicKey']!, + ), + ); + return Response.ok(''); + } + + Future _notificationsHandler(Request request) async { + final data = Uri(query: await request.readAsString()).queryParameters; + for (final notification in data.values) { + final notificationData = json.decode(notification) as Map; + _onNewNotificationController.add( + PushProxyNotification( + deviceIdentifier: notificationData['deviceIdentifier']! as String, + pushTokenHash: notificationData['pushTokenHash']! as String, + subject: notificationData['subject']! as String, + signature: notificationData['signature']! as String, + priority: notificationData['priority']! as String, + type: notificationData['type']! as String, + ), + ); + } + return Response.ok(''); + } + + /// Creates a server listening on the [port] + Future create({ + final bool logging = true, + final int port = 8080, + }) async { + if (_server != null) { + throw Exception('Server already created'); + } + + _onNewDeviceController = StreamController(); + _onNewNotificationController = StreamController(); + _onNewDeviceStream = _onNewDeviceController.stream.asBroadcastStream(); + _onNewNotificationStream = _onNewNotificationController.stream.asBroadcastStream(); + + var handler = Cascade().add(_router).handler; + if (logging) { + handler = logRequests().addHandler(handler); + } + final server = await serve( + handler, + InternetAddress.anyIPv4, + port, + ); + server.autoCompress = true; + + _server = server; + } + + /// Closes the server + Future close() async { + if (_server != null) { + await _server!.close(); + _server = null; + await _onNewDeviceController.close(); + await _onNewNotificationController.close(); + } + } +} + +class PushProxyDevice { + PushProxyDevice({ + required this.pushToken, + required this.deviceIdentifier, + required this.deviceIdentifierSignature, + required this.userPublicKey, + }); + + final String pushToken; + final String deviceIdentifier; + final String deviceIdentifierSignature; + final String userPublicKey; +} + +class PushProxyNotification { + PushProxyNotification({ + required this.deviceIdentifier, + required this.pushTokenHash, + required this.subject, + required this.signature, + required this.priority, + required this.type, + }); + + final String deviceIdentifier; + final String pushTokenHash; + final String subject; + final String signature; + final String priority; + final String type; +} diff --git a/packages/nextcloud_push_proxy/mono_pkg.yaml b/packages/nextcloud_push_proxy/mono_pkg.yaml new file mode 100644 index 00000000000..e3d1d89cdd0 --- /dev/null +++ b/packages/nextcloud_push_proxy/mono_pkg.yaml @@ -0,0 +1,7 @@ +sdk: + - stable + +stages: + - analyze: + - analyze + - format: --output=none --set-exit-if-changed --line-length 120 . diff --git a/packages/nextcloud_push_proxy/pubspec.yaml b/packages/nextcloud_push_proxy/pubspec.yaml new file mode 100644 index 00000000000..ee60bb9d6d8 --- /dev/null +++ b/packages/nextcloud_push_proxy/pubspec.yaml @@ -0,0 +1,15 @@ +name: nextcloud_push_proxy +version: 1.0.0 + +environment: + sdk: '>=2.17.0 <3.0.0' + +dependencies: + shelf: ^1.3.1 + shelf_router: ^1.1.3 + +dev_dependencies: + nit_picking: + git: + url: https://github.com/stack11/dart_nit_picking + ref: f29382f From 978f483f025d0cb0626af970bf1bd5f3f70e8856 Mon Sep 17 00:00:00 2001 From: jld3103 Date: Thu, 14 Jul 2022 17:12:32 +0200 Subject: [PATCH 2/2] nextcloud: Implement notifications API and add push proxy integration tests --- .gitmodules | 3 + .idea/vcs.xml | 1 + external/nextcloud-notifications | 1 + .../doc/notifications/AdminNotification.md | 16 + .../nextcloud/doc/notifications/DefaultApi.md | 318 ++++++++++++++ .../doc/notifications/EmptyResponse.md | 15 + .../doc/notifications/EmptyResponseOcs.md | 16 + .../notifications/GetNotificationResponse.md | 15 + .../GetNotificationResponseOcs.md | 16 + .../ListNotificationsResponse.md | 15 + .../ListNotificationsResponseOcs.md | 16 + .../doc/notifications/Notification.md | 29 ++ .../PushNotificationDecryptedSubject.md | 19 + .../doc/notifications/PushServerDevice.md | 17 + .../PushServerRegistrationResponse.md | 15 + .../PushServerRegistrationResponseOcs.md | 16 + .../notifications/PushServerSubscription.md | 17 + packages/nextcloud/lib/nextcloud.dart | 5 + packages/nextcloud/lib/src/client.dart | 9 + .../lib/src/clients/custom/webdav/client.dart | 16 +- .../lib/src/clients/custom/webdav/webdav.dart | 1 + .../clients/generated/notifications/api.dart | 39 ++ .../notifications/api/default_api.dart | 364 ++++++++++++++++ .../generated/notifications/api_client.dart | 329 +++++++++++++++ .../model/admin_notification.dart | 139 +++++++ .../notifications/model/empty_response.dart | 124 ++++++ .../model/empty_response_ocs.dart | 125 ++++++ .../model/get_notification_response.dart | 124 ++++++ .../model/get_notification_response_ocs.dart | 133 ++++++ .../model/list_notifications_response.dart | 124 ++++++ .../list_notifications_response_ocs.dart | 125 ++++++ .../notifications/model/notification.dart | 316 ++++++++++++++ .../push_notification_decrypted_subject.dart | 187 +++++++++ .../model/push_server_device.dart | 158 +++++++ .../push_server_registration_response.dart | 125 ++++++ ...push_server_registration_response_ocs.dart | 133 ++++++ .../model/push_server_subscription.dart | 158 +++++++ .../lib/src/clients/notifications.dart | 98 +++++ .../src/http_client_response_extension.dart | 12 + packages/nextcloud/pubspec.yaml | 5 +- packages/nextcloud/test/helper.dart | 48 ++- .../nextcloud/test/notifications_test.dart | 220 ++++++++++ packages/nextcloud/test/webdav_test.dart | 12 +- specs/notifications.json | 389 ++++++++++++++++++ specs/templates/notifications.json | 235 +++++++++++ tool/generate-nextcloud.sh | 2 + 46 files changed, 4278 insertions(+), 22 deletions(-) create mode 160000 external/nextcloud-notifications create mode 100644 packages/nextcloud/doc/notifications/AdminNotification.md create mode 100644 packages/nextcloud/doc/notifications/DefaultApi.md create mode 100644 packages/nextcloud/doc/notifications/EmptyResponse.md create mode 100644 packages/nextcloud/doc/notifications/EmptyResponseOcs.md create mode 100644 packages/nextcloud/doc/notifications/GetNotificationResponse.md create mode 100644 packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md create mode 100644 packages/nextcloud/doc/notifications/ListNotificationsResponse.md create mode 100644 packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md create mode 100644 packages/nextcloud/doc/notifications/Notification.md create mode 100644 packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md create mode 100644 packages/nextcloud/doc/notifications/PushServerDevice.md create mode 100644 packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md create mode 100644 packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md create mode 100644 packages/nextcloud/doc/notifications/PushServerSubscription.md create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/api.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response_ocs.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response_ocs.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/notification.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/push_notification_decrypted_subject.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_device.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response_ocs.dart create mode 100644 packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_subscription.dart create mode 100644 packages/nextcloud/lib/src/clients/notifications.dart create mode 100644 packages/nextcloud/lib/src/http_client_response_extension.dart create mode 100644 packages/nextcloud/test/notifications_test.dart create mode 100644 specs/notifications.json create mode 100644 specs/templates/notifications.json diff --git a/.gitmodules b/.gitmodules index 787dc6729d3..117f9b69075 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "external/nextcloud-notes"] path = external/nextcloud-notes url = https://github.com/nextcloud/notes +[submodule "external/nextcloud-notifications"] + path = external/nextcloud-notifications + url = https://github.com/nextcloud/notifications diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 611fc781df6..6b5ae81c302 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -4,6 +4,7 @@ + diff --git a/external/nextcloud-notifications b/external/nextcloud-notifications new file mode 160000 index 00000000000..62c670f2cf9 --- /dev/null +++ b/external/nextcloud-notifications @@ -0,0 +1 @@ +Subproject commit 62c670f2cf9674b95e2f7b94f7bf0cd3887f3418 diff --git a/packages/nextcloud/doc/notifications/AdminNotification.md b/packages/nextcloud/doc/notifications/AdminNotification.md new file mode 100644 index 00000000000..6fafeb7bb5b --- /dev/null +++ b/packages/nextcloud/doc/notifications/AdminNotification.md @@ -0,0 +1,16 @@ +# openapi.model.AdminNotification + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**shortMessage** | **String** | | [optional] +**longMessage** | **String** | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/DefaultApi.md b/packages/nextcloud/doc/notifications/DefaultApi.md new file mode 100644 index 00000000000..58ddd9ab4aa --- /dev/null +++ b/packages/nextcloud/doc/notifications/DefaultApi.md @@ -0,0 +1,318 @@ +# openapi.api.DefaultApi + +## Load the API package +```dart +import 'package:openapi/api.dart'; +``` + +All URIs are relative to *https://localhost:8080/ocs/v1.php/apps/notifications* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**deleteAllNotifications**](DefaultApi.md#deleteallnotifications) | **DELETE** /api/v2/notifications | +[**deleteNotification**](DefaultApi.md#deletenotification) | **DELETE** /api/v2/notifications/{id} | +[**getNotification**](DefaultApi.md#getnotification) | **GET** /api/v2/notifications/{id} | +[**listNotifications**](DefaultApi.md#listnotifications) | **GET** /api/v2/notifications | +[**registerDevice**](DefaultApi.md#registerdevice) | **POST** /api/v2/push | +[**removeDevice**](DefaultApi.md#removedevice) | **DELETE** /api/v2/push | +[**sendAdminNotification**](DefaultApi.md#sendadminnotification) | **POST** /api/v2/admin_notifications/{userId} | + + +# **deleteAllNotifications** +> String deleteAllNotifications() + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); + +try { + final result = api_instance.deleteAllNotifications(); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->deleteAllNotifications: $e\n'); +} +``` + +### Parameters +This endpoint does not need any parameter. + +### Return type + +**String** + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **deleteNotification** +> EmptyResponse deleteNotification(id) + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); +final id = 56; // int | + +try { + final result = api_instance.deleteNotification(id); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->deleteNotification: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **id** | **int**| | + +### Return type + +[**EmptyResponse**](EmptyResponse.md) + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **getNotification** +> GetNotificationResponse getNotification(id) + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); +final id = 56; // int | + +try { + final result = api_instance.getNotification(id); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->getNotification: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **id** | **int**| | + +### Return type + +[**GetNotificationResponse**](GetNotificationResponse.md) + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **listNotifications** +> String listNotifications() + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); + +try { + final result = api_instance.listNotifications(); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->listNotifications: $e\n'); +} +``` + +### Parameters +This endpoint does not need any parameter. + +### Return type + +**String** + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **registerDevice** +> PushServerRegistrationResponse registerDevice(pushServerDevice) + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); +final pushServerDevice = PushServerDevice(); // PushServerDevice | + +try { + final result = api_instance.registerDevice(pushServerDevice); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->registerDevice: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **pushServerDevice** | [**PushServerDevice**](PushServerDevice.md)| | + +### Return type + +[**PushServerRegistrationResponse**](PushServerRegistrationResponse.md) + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **removeDevice** +> String removeDevice() + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); + +try { + final result = api_instance.removeDevice(); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->removeDevice: $e\n'); +} +``` + +### Parameters +This endpoint does not need any parameter. + +### Return type + +**String** + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **sendAdminNotification** +> EmptyResponse sendAdminNotification(userId, adminNotification) + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure HTTP basic authorization: basic_auth +//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME' +//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD'; + +final api_instance = DefaultApi(); +final userId = userId_example; // String | +final adminNotification = AdminNotification(); // AdminNotification | + +try { + final result = api_instance.sendAdminNotification(userId, adminNotification); + print(result); +} catch (e) { + print('Exception when calling DefaultApi->sendAdminNotification: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **userId** | **String**| | + **adminNotification** | [**AdminNotification**](AdminNotification.md)| | + +### Return type + +[**EmptyResponse**](EmptyResponse.md) + +### Authorization + +[basic_auth](../README.md#basic_auth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/packages/nextcloud/doc/notifications/EmptyResponse.md b/packages/nextcloud/doc/notifications/EmptyResponse.md new file mode 100644 index 00000000000..c983d5488fc --- /dev/null +++ b/packages/nextcloud/doc/notifications/EmptyResponse.md @@ -0,0 +1,15 @@ +# openapi.model.EmptyResponse + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ocs** | [**EmptyResponseOcs**](EmptyResponseOcs.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/EmptyResponseOcs.md b/packages/nextcloud/doc/notifications/EmptyResponseOcs.md new file mode 100644 index 00000000000..2cd835c7e7f --- /dev/null +++ b/packages/nextcloud/doc/notifications/EmptyResponseOcs.md @@ -0,0 +1,16 @@ +# openapi.model.EmptyResponseOcs + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**meta** | [**Object**](.md) | Stub | [optional] +**data** | **List** | | [optional] [default to const []] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/GetNotificationResponse.md b/packages/nextcloud/doc/notifications/GetNotificationResponse.md new file mode 100644 index 00000000000..45319629e2b --- /dev/null +++ b/packages/nextcloud/doc/notifications/GetNotificationResponse.md @@ -0,0 +1,15 @@ +# openapi.model.GetNotificationResponse + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ocs** | [**GetNotificationResponseOcs**](GetNotificationResponseOcs.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md b/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md new file mode 100644 index 00000000000..48f88537c51 --- /dev/null +++ b/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md @@ -0,0 +1,16 @@ +# openapi.model.GetNotificationResponseOcs + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**meta** | [**Object**](.md) | Stub | [optional] +**data** | [**Notification**](Notification.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/ListNotificationsResponse.md b/packages/nextcloud/doc/notifications/ListNotificationsResponse.md new file mode 100644 index 00000000000..53f4e3d644e --- /dev/null +++ b/packages/nextcloud/doc/notifications/ListNotificationsResponse.md @@ -0,0 +1,15 @@ +# openapi.model.ListNotificationsResponse + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ocs** | [**ListNotificationsResponseOcs**](ListNotificationsResponseOcs.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md b/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md new file mode 100644 index 00000000000..57fc6d59d39 --- /dev/null +++ b/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md @@ -0,0 +1,16 @@ +# openapi.model.ListNotificationsResponseOcs + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**meta** | [**Object**](.md) | Stub | [optional] +**data** | [**List**](Notification.md) | | [optional] [default to const []] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/Notification.md b/packages/nextcloud/doc/notifications/Notification.md new file mode 100644 index 00000000000..c9f80d1c13c --- /dev/null +++ b/packages/nextcloud/doc/notifications/Notification.md @@ -0,0 +1,29 @@ +# openapi.model.Notification + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**notificationId** | **int** | | [optional] +**app** | **String** | | [optional] +**user** | **String** | | [optional] +**datetime** | **String** | | [optional] +**objectType** | **String** | | [optional] +**objectId** | **String** | | [optional] +**subject** | **String** | | [optional] +**message** | **String** | | [optional] +**link** | **String** | | [optional] +**subjectRich** | **String** | | [optional] +**subjectRichParameters** | **List** | | [optional] [default to const []] +**messageRich** | **String** | | [optional] +**messageRichParameters** | **List** | | [optional] [default to const []] +**icon** | **String** | | [optional] +**actions** | **List** | | [optional] [default to const []] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md b/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md new file mode 100644 index 00000000000..a32f0de9aa6 --- /dev/null +++ b/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md @@ -0,0 +1,19 @@ +# openapi.model.PushNotificationDecryptedSubject + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**nid** | **int** | | [optional] +**app** | **String** | | [optional] +**subject** | **String** | | [optional] +**type** | **String** | | [optional] +**id** | **String** | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/PushServerDevice.md b/packages/nextcloud/doc/notifications/PushServerDevice.md new file mode 100644 index 00000000000..b2091f59ea5 --- /dev/null +++ b/packages/nextcloud/doc/notifications/PushServerDevice.md @@ -0,0 +1,17 @@ +# openapi.model.PushServerDevice + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**pushTokenHash** | **String** | | [optional] +**devicePublicKey** | **String** | | [optional] +**proxyServer** | **String** | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md b/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md new file mode 100644 index 00000000000..64f5dd69a7b --- /dev/null +++ b/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md @@ -0,0 +1,15 @@ +# openapi.model.PushServerRegistrationResponse + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ocs** | [**PushServerRegistrationResponseOcs**](PushServerRegistrationResponseOcs.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md b/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md new file mode 100644 index 00000000000..f28ad4195de --- /dev/null +++ b/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md @@ -0,0 +1,16 @@ +# openapi.model.PushServerRegistrationResponseOcs + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**meta** | [**Object**](.md) | Stub | [optional] +**data** | [**PushServerSubscription**](PushServerSubscription.md) | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/doc/notifications/PushServerSubscription.md b/packages/nextcloud/doc/notifications/PushServerSubscription.md new file mode 100644 index 00000000000..35581a35a7f --- /dev/null +++ b/packages/nextcloud/doc/notifications/PushServerSubscription.md @@ -0,0 +1,17 @@ +# openapi.model.PushServerSubscription + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**publicKey** | **String** | | [optional] +**deviceIdentifier** | **String** | | [optional] +**signature** | **String** | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/packages/nextcloud/lib/nextcloud.dart b/packages/nextcloud/lib/nextcloud.dart index 11772ab42e7..c240ef2b88d 100644 --- a/packages/nextcloud/lib/nextcloud.dart +++ b/packages/nextcloud/lib/nextcloud.dart @@ -1,5 +1,7 @@ library nextcloud; +export 'package:crypton/crypton.dart' show RSAKeypair, RSAPublicKey, RSAPrivateKey; + export 'src/app_type.dart'; export 'src/client.dart'; export 'src/clients/common/api.dart'; @@ -11,12 +13,15 @@ export 'src/clients/generated/news/api.dart' hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi; export 'src/clients/generated/notes/api.dart' hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi; +export 'src/clients/generated/notifications/api.dart' + hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi; export 'src/clients/generated/provisioning_api/api.dart' hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi; export 'src/clients/generated/user_status/api.dart' hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi; export 'src/clients/news.dart'; export 'src/clients/notes.dart'; +export 'src/clients/notifications.dart'; export 'src/clients/provisioning_api.dart'; export 'src/clients/user_status.dart'; export 'src/clients/webdav.dart'; diff --git a/packages/nextcloud/lib/src/client.dart b/packages/nextcloud/lib/src/client.dart index 085db14beae..97656ec4589 100644 --- a/packages/nextcloud/lib/src/client.dart +++ b/packages/nextcloud/lib/src/client.dart @@ -29,6 +29,11 @@ class NextcloudClient { authentication, _addCommonSettings, ); + _notifications = NextcloudNotificationsClient( + baseURL, + authentication, + _addCommonSettings, + ); _provisioningApi = NextcloudProvisioningApiClient( baseURL, authentication, @@ -103,6 +108,7 @@ class NextcloudClient { late NextcloudCoreClient _core; late NextcloudNewsClient _news; late NextcloudNotesClient _notes; + late NextcloudNotificationsClient _notifications; late NextcloudProvisioningApiClient _provisioningApi; late NextcloudUserStatusClient _userStatus; @@ -118,6 +124,9 @@ class NextcloudClient { /// Client for Nextcloud Notes app NextcloudNotesClient get notes => _notes; + /// Client for Nextcloud Notifications API + NextcloudNotificationsClient get notifications => _notifications; + /// Client for Provisioning APIs NextcloudProvisioningApiClient get provisioningApi => _provisioningApi; diff --git a/packages/nextcloud/lib/src/clients/custom/webdav/client.dart b/packages/nextcloud/lib/src/clients/custom/webdav/client.dart index 35ead488408..00331144ea1 100644 --- a/packages/nextcloud/lib/src/clients/custom/webdav/client.dart +++ b/packages/nextcloud/lib/src/clients/custom/webdav/client.dart @@ -30,12 +30,6 @@ class WebDavClient { 'http://sabredav.org/ns': 's', // mostly used in error responses }; - Future _responseToBodyBytes(final HttpClientResponse response) async => - Uint8List.fromList((await response.toList()).reduce((final value, final element) => [...value, ...element])); - - Future _responseToBodyString(final HttpClientResponse response) async => - utf8.decode(await _responseToBodyBytes(response)); - Future _send( final String method, final String url, @@ -66,7 +60,7 @@ class WebDavClient { if (!expectedCodes.contains(response.statusCode)) { throw ApiException( response.statusCode, - await _responseToBodyString(response), + await response.body, ); } @@ -233,7 +227,7 @@ class WebDavClient { return treeFromWebDavXml( basePath, namespaces, - await _responseToBodyString(response), + await response.body, )..removeAt(0); } @@ -284,7 +278,7 @@ class WebDavClient { return treeFromWebDavXml( basePath, namespaces, - await _responseToBodyString(response), + await response.body, ); } @@ -306,7 +300,7 @@ class WebDavClient { return fileFromWebDavXml( basePath, namespaces, - await _responseToBodyString(response), + await response.body, ); } @@ -350,7 +344,7 @@ class WebDavClient { [200, 207], data: Stream.value(Uint8List.fromList(utf8.encode(builder.buildDocument().toString()))), ); - return checkUpdateFromWebDavXml(await _responseToBodyString(response)); + return checkUpdateFromWebDavXml(await response.body); } /// Move a file from [sourcePath] to [destinationPath] diff --git a/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart b/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart index 5d7e664cb38..c0653380272 100644 --- a/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart +++ b/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart @@ -6,6 +6,7 @@ import 'dart:typed_data'; import 'package:intl/intl.dart'; import 'package:nextcloud/src/clients/common/api.dart'; +import 'package:nextcloud/src/http_client_response_extension.dart'; import 'package:xml/xml.dart'; import 'package:xml/xml.dart' as xml; diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api.dart new file mode 100644 index 00000000000..60138dc8d3e --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/api.dart @@ -0,0 +1,39 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +library openapi.api; + +import 'package:nextcloud/src/clients/common/api.dart'; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:http/http.dart'; +import 'package:intl/intl.dart'; +import 'package:meta/meta.dart'; + +part 'api_client.dart'; + +part 'api/default_api.dart'; + +part 'model/admin_notification.dart'; +part 'model/empty_response.dart'; +part 'model/empty_response_ocs.dart'; +part 'model/get_notification_response.dart'; +part 'model/get_notification_response_ocs.dart'; +part 'model/list_notifications_response.dart'; +part 'model/list_notifications_response_ocs.dart'; +part 'model/notification.dart'; +part 'model/push_notification_decrypted_subject.dart'; +part 'model/push_server_device.dart'; +part 'model/push_server_registration_response.dart'; +part 'model/push_server_registration_response_ocs.dart'; +part 'model/push_server_subscription.dart'; diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart new file mode 100644 index 00000000000..7a6bbe0ecc5 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart @@ -0,0 +1,364 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class DefaultApi extends ApiInstance { + DefaultApi(ApiClient apiClient) : super(apiClient); + + /// Performs an HTTP 'DELETE /api/v2/notifications' operation and returns the [Response]. + Future deleteAllNotificationsWithHttpInfo() async { + // ignore: prefer_const_declarations + final path = r'/api/v2/notifications'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'DELETE', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + Future deleteAllNotifications() async { + final response = await deleteAllNotificationsWithHttpInfo(); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'String', + ) as String; + } + return null; + } + + /// Performs an HTTP 'DELETE /api/v2/notifications/{id}' operation and returns the [Response]. + /// Parameters: + /// + /// * [int] id (required): + Future deleteNotificationWithHttpInfo( + int id, + ) async { + // ignore: prefer_const_declarations + final path = r'/api/v2/notifications/{id}'.replaceAll('{id}', id.toString()); + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'DELETE', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [int] id (required): + Future deleteNotification( + int id, + ) async { + final response = await deleteNotificationWithHttpInfo( + id, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'EmptyResponse', + ) as EmptyResponse; + } + return null; + } + + /// Performs an HTTP 'GET /api/v2/notifications/{id}' operation and returns the [Response]. + /// Parameters: + /// + /// * [int] id (required): + Future getNotificationWithHttpInfo( + int id, + ) async { + // ignore: prefer_const_declarations + final path = r'/api/v2/notifications/{id}'.replaceAll('{id}', id.toString()); + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [int] id (required): + Future getNotification( + int id, + ) async { + final response = await getNotificationWithHttpInfo( + id, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'GetNotificationResponse', + ) as GetNotificationResponse; + } + return null; + } + + /// Performs an HTTP 'GET /api/v2/notifications' operation and returns the [Response]. + Future listNotificationsWithHttpInfo() async { + // ignore: prefer_const_declarations + final path = r'/api/v2/notifications'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + Future listNotifications() async { + final response = await listNotificationsWithHttpInfo(); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'String', + ) as String; + } + return null; + } + + /// Performs an HTTP 'POST /api/v2/push' operation and returns the [Response]. + /// Parameters: + /// + /// * [PushServerDevice] pushServerDevice (required): + Future registerDeviceWithHttpInfo( + PushServerDevice pushServerDevice, + ) async { + // ignore: prefer_const_declarations + final path = r'/api/v2/push'; + + // ignore: prefer_final_locals + Object? postBody = pushServerDevice; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + return apiClient.invokeAPI( + path, + 'POST', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [PushServerDevice] pushServerDevice (required): + Future registerDevice( + PushServerDevice pushServerDevice, + ) async { + final response = await registerDeviceWithHttpInfo( + pushServerDevice, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'PushServerRegistrationResponse', + ) as PushServerRegistrationResponse; + } + return null; + } + + /// Performs an HTTP 'DELETE /api/v2/push' operation and returns the [Response]. + Future removeDeviceWithHttpInfo() async { + // ignore: prefer_const_declarations + final path = r'/api/v2/push'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'DELETE', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + Future removeDevice() async { + final response = await removeDeviceWithHttpInfo(); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'String', + ) as String; + } + return null; + } + + /// Performs an HTTP 'POST /api/v2/admin_notifications/{userId}' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] userId (required): + /// + /// * [AdminNotification] adminNotification (required): + Future sendAdminNotificationWithHttpInfo( + String userId, + AdminNotification adminNotification, + ) async { + // ignore: prefer_const_declarations + final path = r'/api/v2/admin_notifications/{userId}'.replaceAll('{userId}', userId); + + // ignore: prefer_final_locals + Object? postBody = adminNotification; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + return apiClient.invokeAPI( + path, + 'POST', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] userId (required): + /// + /// * [AdminNotification] adminNotification (required): + Future sendAdminNotification( + String userId, + AdminNotification adminNotification, + ) async { + final response = await sendAdminNotificationWithHttpInfo( + userId, + adminNotification, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync( + await decodeBodyBytes(response), + 'EmptyResponse', + ) as EmptyResponse; + } + return null; + } +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart new file mode 100644 index 00000000000..69aca6f01b8 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart @@ -0,0 +1,329 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class ApiClient extends BaseApiClient { + ApiClient({this.basePath = 'https://localhost:8080/ocs/v1.php/apps/notifications', this.authentication}); + + final String basePath; + + var _client = Client(); + + /// Returns the current HTTP [Client] instance to use in this class. + /// + /// The return value is guaranteed to never be null. + Client get client => _client; + + /// Requests to use a new HTTP [Client] in this class. + set client(Client newClient) { + _client = newClient; + } + + final _defaultHeaderMap = {}; + final Authentication? authentication; + + void addDefaultHeader(String key, String value) { + _defaultHeaderMap[key] = value; + } + + Map get defaultHeaderMap => _defaultHeaderMap; + + // We don't use a Map for queryParams. + // If collectionFormat is 'multi', a key might appear multiple times. + Future invokeAPI( + String path, + String method, + List queryParams, + Object? body, + Map headerParams, + Map formParams, + String? contentType, + ) async { + _updateParamsForAuth(queryParams, headerParams); + + headerParams.addAll(_defaultHeaderMap); + if (contentType != null) { + headerParams['Content-Type'] = contentType; + } + + final urlEncodedQueryParams = queryParams.map((param) => '$param'); + final queryString = urlEncodedQueryParams.isNotEmpty ? '?${urlEncodedQueryParams.join('&')}' : ''; + final uri = Uri.parse('$basePath$path$queryString'); + + try { + // Special case for uploading a single file which isn't a 'multipart/form-data'. + if (body is MultipartFile && + (contentType == null || !contentType.toLowerCase().startsWith('multipart/form-data'))) { + final request = StreamedRequest(method, uri); + request.headers.addAll(headerParams); + request.contentLength = body.length; + body.finalize().listen( + request.sink.add, + onDone: request.sink.close, + // ignore: avoid_types_on_closure_parameters + onError: (Object error, StackTrace trace) => request.sink.close(), + cancelOnError: true, + ); + final response = await _client.send(request); + return Response.fromStream(response); + } + + if (body is MultipartRequest) { + final request = MultipartRequest(method, uri); + request.fields.addAll(body.fields); + request.files.addAll(body.files); + request.headers.addAll(body.headers); + request.headers.addAll(headerParams); + final response = await _client.send(request); + return Response.fromStream(response); + } + + final msgBody = contentType == 'application/x-www-form-urlencoded' ? formParams : await serializeAsync(body); + final nullableHeaderParams = headerParams.isEmpty ? null : headerParams; + + switch (method) { + case 'POST': + return await _client.post( + uri, + headers: nullableHeaderParams, + body: msgBody, + ); + case 'PUT': + return await _client.put( + uri, + headers: nullableHeaderParams, + body: msgBody, + ); + case 'DELETE': + return await _client.delete( + uri, + headers: nullableHeaderParams, + body: msgBody, + ); + case 'PATCH': + return await _client.patch( + uri, + headers: nullableHeaderParams, + body: msgBody, + ); + case 'HEAD': + return await _client.head( + uri, + headers: nullableHeaderParams, + ); + case 'GET': + return await _client.get( + uri, + headers: nullableHeaderParams, + ); + } + } on SocketException catch (error, trace) { + throw ApiException.withInner( + HttpStatus.badRequest, + 'Socket operation failed: $method $path', + error, + trace, + ); + } on TlsException catch (error, trace) { + throw ApiException.withInner( + HttpStatus.badRequest, + 'TLS/SSL communication failed: $method $path', + error, + trace, + ); + } on IOException catch (error, trace) { + throw ApiException.withInner( + HttpStatus.badRequest, + 'I/O operation failed: $method $path', + error, + trace, + ); + } on ClientException catch (error, trace) { + throw ApiException.withInner( + HttpStatus.badRequest, + 'HTTP connection failed: $method $path', + error, + trace, + ); + } on Exception catch (error, trace) { + throw ApiException.withInner( + HttpStatus.badRequest, + 'Exception occurred: $method $path', + error, + trace, + ); + } + + throw ApiException( + HttpStatus.badRequest, + 'Invalid HTTP operation: $method $path', + ); + } + + Future deserializeAsync( + String json, + String targetType, { + bool growable = false, + }) async => + // ignore: deprecated_member_use_from_same_package + deserialize(json, targetType, growable: growable); + + @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use deserializeAsync() instead.') + dynamic deserialize( + String json, + String targetType, { + bool growable = false, + }) { + // Remove all spaces. Necessary for regular expressions as well. + targetType = targetType.replaceAll(' ', ''); // ignore: parameter_assignments + + // If the expected target type is String, nothing to do... + return targetType == 'String' ? json : _deserialize(jsonDecode(json), targetType, growable: growable); + } + + // ignore: deprecated_member_use_from_same_package + Future serializeAsync(Object? value) async => serialize(value); + + @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use serializeAsync() instead.') + String serialize(Object? value) => value == null ? '' : json.encode(value); + + /// Update query and header parameters based on authentication settings. + void _updateParamsForAuth( + List queryParams, + Map headerParams, + ) { + if (authentication != null) { + authentication!.applyToParams(queryParams, headerParams); + } + } + + static dynamic _deserialize(dynamic value, String targetType, {bool growable = false}) { + try { + switch (targetType) { + case 'String': + return value is String ? value : value.toString(); + case 'int': + return value is int ? value : int.parse('$value'); + case 'double': + return value is double ? value : double.parse('$value'); + case 'bool': + if (value is bool) { + return value; + } + final valueString = '$value'.toLowerCase(); + return valueString == 'true' || valueString == '1'; + case 'AdminNotification': + return AdminNotification.fromJson(value); + case 'EmptyResponse': + return EmptyResponse.fromJson(value); + case 'EmptyResponseOcs': + return EmptyResponseOcs.fromJson(value); + case 'GetNotificationResponse': + return GetNotificationResponse.fromJson(value); + case 'GetNotificationResponseOcs': + return GetNotificationResponseOcs.fromJson(value); + case 'ListNotificationsResponse': + return ListNotificationsResponse.fromJson(value); + case 'ListNotificationsResponseOcs': + return ListNotificationsResponseOcs.fromJson(value); + case 'Notification': + return Notification.fromJson(value); + case 'PushNotificationDecryptedSubject': + return PushNotificationDecryptedSubject.fromJson(value); + case 'PushServerDevice': + return PushServerDevice.fromJson(value); + case 'PushServerRegistrationResponse': + return PushServerRegistrationResponse.fromJson(value); + case 'PushServerRegistrationResponseOcs': + return PushServerRegistrationResponseOcs.fromJson(value); + case 'PushServerSubscription': + return PushServerSubscription.fromJson(value); + default: + dynamic match; + if (value is List && (match = apiRegList.firstMatch(targetType)?.group(1)) != null) { + return value + .map((dynamic v) => _deserialize( + v, + match, + growable: growable, + )) + .toList(growable: growable); + } + if (value is Set && (match = apiRegSet.firstMatch(targetType)?.group(1)) != null) { + return value + .map((dynamic v) => _deserialize( + v, + match, + growable: growable, + )) + .toSet(); + } + if (value is Map && (match = apiRegMap.firstMatch(targetType)?.group(1)) != null) { + return Map.fromIterables( + value.keys.cast(), + value.values.map((dynamic v) => _deserialize( + v, + match, + growable: growable, + )), + ); + } + } + } on Exception catch (error, trace) { + throw ApiException.withInner( + HttpStatus.internalServerError, + 'Exception during deserialization.', + error, + trace, + ); + } + throw ApiException( + HttpStatus.internalServerError, + 'Could not find a suitable class for deserialization', + ); + } +} + +/// Primarily intended for use in an isolate. +class DeserializationMessage { + const DeserializationMessage({ + required this.json, + required this.targetType, + this.growable = false, + }); + + /// The JSON value to deserialize. + final String json; + + /// Target type to deserialize to. + final String targetType; + + /// Whether to make deserialized lists or maps growable. + final bool growable; +} + +/// Primarily intended for use in an isolate. +Future deserializeAsync(DeserializationMessage message) async { + // Remove all spaces. Necessary for regular expressions as well. + final targetType = message.targetType.replaceAll(' ', ''); + + // If the expected target type is String, nothing to do... + return targetType == 'String' + ? message.json + : ApiClient._deserialize( + jsonDecode(message.json), + targetType, + growable: message.growable, + ); +} + +/// Primarily intended for use in an isolate. +Future serializeAsync(Object? value) async => value == null ? '' : json.encode(value); diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart new file mode 100644 index 00000000000..6b7ccd2205c --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart @@ -0,0 +1,139 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class AdminNotification { + /// Returns a new [AdminNotification] instance. + AdminNotification({ + this.shortMessage, + this.longMessage, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? shortMessage; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? longMessage; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AdminNotification && other.shortMessage == shortMessage && other.longMessage == longMessage; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (shortMessage == null ? 0 : shortMessage!.hashCode) + (longMessage == null ? 0 : longMessage!.hashCode); + + @override + String toString() => 'AdminNotification[shortMessage=$shortMessage, longMessage=$longMessage]'; + + Map toJson() { + final _json = {}; + if (shortMessage != null) { + _json[r'shortMessage'] = shortMessage; + } + if (longMessage != null) { + _json[r'longMessage'] = longMessage; + } + return _json; + } + + /// Returns a new [AdminNotification] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static AdminNotification? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "AdminNotification[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "AdminNotification[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return AdminNotification( + shortMessage: mapValueOfType(json, r'shortMessage'), + longMessage: mapValueOfType(json, r'longMessage'), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = AdminNotification.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = AdminNotification.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of AdminNotification-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = AdminNotification.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart new file mode 100644 index 00000000000..f8190763ce1 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart @@ -0,0 +1,124 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class EmptyResponse { + /// Returns a new [EmptyResponse] instance. + EmptyResponse({ + this.ocs, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + EmptyResponseOcs? ocs; + + @override + bool operator ==(Object other) => identical(this, other) || other is EmptyResponse && other.ocs == ocs; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (ocs == null ? 0 : ocs!.hashCode); + + @override + String toString() => 'EmptyResponse[ocs=$ocs]'; + + Map toJson() { + final _json = {}; + if (ocs != null) { + _json[r'ocs'] = ocs; + } + return _json; + } + + /// Returns a new [EmptyResponse] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static EmptyResponse? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "EmptyResponse[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "EmptyResponse[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return EmptyResponse( + ocs: EmptyResponseOcs.fromJson(json[r'ocs']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = EmptyResponse.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = EmptyResponse.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of EmptyResponse-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = EmptyResponse.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart new file mode 100644 index 00000000000..e5f3157b5fc --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart @@ -0,0 +1,125 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class EmptyResponseOcs { + /// Returns a new [EmptyResponseOcs] instance. + EmptyResponseOcs({ + this.meta, + this.data = const [], + }); + + /// Stub + Object? meta; + + List data; + + @override + bool operator ==(Object other) => + identical(this, other) || other is EmptyResponseOcs && other.meta == meta && other.data == data; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (meta == null ? 0 : meta!.hashCode) + (data.hashCode); + + @override + String toString() => 'EmptyResponseOcs[meta=$meta, data=$data]'; + + Map toJson() { + final _json = {}; + if (meta != null) { + _json[r'meta'] = meta; + } + _json[r'data'] = data; + return _json; + } + + /// Returns a new [EmptyResponseOcs] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static EmptyResponseOcs? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "EmptyResponseOcs[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "EmptyResponseOcs[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return EmptyResponseOcs( + meta: mapValueOfType(json, r'meta'), + data: json[r'data'] is List ? (json[r'data'] as List).cast() : const [], + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = EmptyResponseOcs.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = EmptyResponseOcs.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of EmptyResponseOcs-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = EmptyResponseOcs.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response.dart new file mode 100644 index 00000000000..dbf5b865b9c --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response.dart @@ -0,0 +1,124 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class GetNotificationResponse { + /// Returns a new [GetNotificationResponse] instance. + GetNotificationResponse({ + this.ocs, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + GetNotificationResponseOcs? ocs; + + @override + bool operator ==(Object other) => identical(this, other) || other is GetNotificationResponse && other.ocs == ocs; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (ocs == null ? 0 : ocs!.hashCode); + + @override + String toString() => 'GetNotificationResponse[ocs=$ocs]'; + + Map toJson() { + final _json = {}; + if (ocs != null) { + _json[r'ocs'] = ocs; + } + return _json; + } + + /// Returns a new [GetNotificationResponse] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static GetNotificationResponse? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "GetNotificationResponse[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "GetNotificationResponse[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return GetNotificationResponse( + ocs: GetNotificationResponseOcs.fromJson(json[r'ocs']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = GetNotificationResponse.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = GetNotificationResponse.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of GetNotificationResponse-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = GetNotificationResponse.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response_ocs.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response_ocs.dart new file mode 100644 index 00000000000..6b7883ce1c3 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/get_notification_response_ocs.dart @@ -0,0 +1,133 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class GetNotificationResponseOcs { + /// Returns a new [GetNotificationResponseOcs] instance. + GetNotificationResponseOcs({ + this.meta, + this.data, + }); + + /// Stub + Object? meta; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + Notification? data; + + @override + bool operator ==(Object other) => + identical(this, other) || other is GetNotificationResponseOcs && other.meta == meta && other.data == data; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (meta == null ? 0 : meta!.hashCode) + (data == null ? 0 : data!.hashCode); + + @override + String toString() => 'GetNotificationResponseOcs[meta=$meta, data=$data]'; + + Map toJson() { + final _json = {}; + if (meta != null) { + _json[r'meta'] = meta; + } + if (data != null) { + _json[r'data'] = data; + } + return _json; + } + + /// Returns a new [GetNotificationResponseOcs] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static GetNotificationResponseOcs? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "GetNotificationResponseOcs[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "GetNotificationResponseOcs[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return GetNotificationResponseOcs( + meta: mapValueOfType(json, r'meta'), + data: Notification.fromJson(json[r'data']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = GetNotificationResponseOcs.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = GetNotificationResponseOcs.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of GetNotificationResponseOcs-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = GetNotificationResponseOcs.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response.dart new file mode 100644 index 00000000000..b180f52e379 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response.dart @@ -0,0 +1,124 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class ListNotificationsResponse { + /// Returns a new [ListNotificationsResponse] instance. + ListNotificationsResponse({ + this.ocs, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + ListNotificationsResponseOcs? ocs; + + @override + bool operator ==(Object other) => identical(this, other) || other is ListNotificationsResponse && other.ocs == ocs; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (ocs == null ? 0 : ocs!.hashCode); + + @override + String toString() => 'ListNotificationsResponse[ocs=$ocs]'; + + Map toJson() { + final _json = {}; + if (ocs != null) { + _json[r'ocs'] = ocs; + } + return _json; + } + + /// Returns a new [ListNotificationsResponse] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static ListNotificationsResponse? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "ListNotificationsResponse[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "ListNotificationsResponse[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return ListNotificationsResponse( + ocs: ListNotificationsResponseOcs.fromJson(json[r'ocs']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = ListNotificationsResponse.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = ListNotificationsResponse.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of ListNotificationsResponse-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = ListNotificationsResponse.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response_ocs.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response_ocs.dart new file mode 100644 index 00000000000..6643159d07b --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/list_notifications_response_ocs.dart @@ -0,0 +1,125 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class ListNotificationsResponseOcs { + /// Returns a new [ListNotificationsResponseOcs] instance. + ListNotificationsResponseOcs({ + this.meta, + this.data = const [], + }); + + /// Stub + Object? meta; + + List data; + + @override + bool operator ==(Object other) => + identical(this, other) || other is ListNotificationsResponseOcs && other.meta == meta && other.data == data; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (meta == null ? 0 : meta!.hashCode) + (data.hashCode); + + @override + String toString() => 'ListNotificationsResponseOcs[meta=$meta, data=$data]'; + + Map toJson() { + final _json = {}; + if (meta != null) { + _json[r'meta'] = meta; + } + _json[r'data'] = data; + return _json; + } + + /// Returns a new [ListNotificationsResponseOcs] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static ListNotificationsResponseOcs? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "ListNotificationsResponseOcs[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "ListNotificationsResponseOcs[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return ListNotificationsResponseOcs( + meta: mapValueOfType(json, r'meta'), + data: Notification.listFromJson(json[r'data']) ?? const [], + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = ListNotificationsResponseOcs.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = ListNotificationsResponseOcs.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of ListNotificationsResponseOcs-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = ListNotificationsResponseOcs.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/notification.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/notification.dart new file mode 100644 index 00000000000..90ec5a56440 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/notification.dart @@ -0,0 +1,316 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class Notification { + /// Returns a new [Notification] instance. + Notification({ + this.notificationId, + this.app, + this.user, + this.datetime, + this.objectType, + this.objectId, + this.subject, + this.message, + this.link, + this.subjectRich, + this.subjectRichParameters = const [], + this.messageRich, + this.messageRichParameters = const [], + this.icon, + this.actions = const [], + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? notificationId; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? app; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? user; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? datetime; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? objectType; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? objectId; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? subject; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? message; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? link; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? subjectRich; + + List subjectRichParameters; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? messageRich; + + List messageRichParameters; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? icon; + + List actions; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Notification && + other.notificationId == notificationId && + other.app == app && + other.user == user && + other.datetime == datetime && + other.objectType == objectType && + other.objectId == objectId && + other.subject == subject && + other.message == message && + other.link == link && + other.subjectRich == subjectRich && + other.subjectRichParameters == subjectRichParameters && + other.messageRich == messageRich && + other.messageRichParameters == messageRichParameters && + other.icon == icon && + other.actions == actions; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (notificationId == null ? 0 : notificationId!.hashCode) + + (app == null ? 0 : app!.hashCode) + + (user == null ? 0 : user!.hashCode) + + (datetime == null ? 0 : datetime!.hashCode) + + (objectType == null ? 0 : objectType!.hashCode) + + (objectId == null ? 0 : objectId!.hashCode) + + (subject == null ? 0 : subject!.hashCode) + + (message == null ? 0 : message!.hashCode) + + (link == null ? 0 : link!.hashCode) + + (subjectRich == null ? 0 : subjectRich!.hashCode) + + (subjectRichParameters.hashCode) + + (messageRich == null ? 0 : messageRich!.hashCode) + + (messageRichParameters.hashCode) + + (icon == null ? 0 : icon!.hashCode) + + (actions.hashCode); + + @override + String toString() => + 'Notification[notificationId=$notificationId, app=$app, user=$user, datetime=$datetime, objectType=$objectType, objectId=$objectId, subject=$subject, message=$message, link=$link, subjectRich=$subjectRich, subjectRichParameters=$subjectRichParameters, messageRich=$messageRich, messageRichParameters=$messageRichParameters, icon=$icon, actions=$actions]'; + + Map toJson() { + final _json = {}; + if (notificationId != null) { + _json[r'notification_id'] = notificationId; + } + if (app != null) { + _json[r'app'] = app; + } + if (user != null) { + _json[r'user'] = user; + } + if (datetime != null) { + _json[r'datetime'] = datetime; + } + if (objectType != null) { + _json[r'object_type'] = objectType; + } + if (objectId != null) { + _json[r'object_id'] = objectId; + } + if (subject != null) { + _json[r'subject'] = subject; + } + if (message != null) { + _json[r'message'] = message; + } + if (link != null) { + _json[r'link'] = link; + } + if (subjectRich != null) { + _json[r'subjectRich'] = subjectRich; + } + _json[r'subjectRichParameters'] = subjectRichParameters; + if (messageRich != null) { + _json[r'messageRich'] = messageRich; + } + _json[r'messageRichParameters'] = messageRichParameters; + if (icon != null) { + _json[r'icon'] = icon; + } + _json[r'actions'] = actions; + return _json; + } + + /// Returns a new [Notification] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static Notification? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "Notification[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "Notification[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return Notification( + notificationId: mapValueOfType(json, r'notification_id'), + app: mapValueOfType(json, r'app'), + user: mapValueOfType(json, r'user'), + datetime: mapValueOfType(json, r'datetime'), + objectType: mapValueOfType(json, r'object_type'), + objectId: mapValueOfType(json, r'object_id'), + subject: mapValueOfType(json, r'subject'), + message: mapValueOfType(json, r'message'), + link: mapValueOfType(json, r'link'), + subjectRich: mapValueOfType(json, r'subjectRich'), + subjectRichParameters: + json[r'subjectRichParameters'] is List ? (json[r'subjectRichParameters'] as List).cast() : const [], + messageRich: mapValueOfType(json, r'messageRich'), + messageRichParameters: + json[r'messageRichParameters'] is List ? (json[r'messageRichParameters'] as List).cast() : const [], + icon: mapValueOfType(json, r'icon'), + actions: json[r'actions'] is List ? (json[r'actions'] as List).cast() : const [], + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = Notification.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = Notification.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of Notification-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = Notification.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/push_notification_decrypted_subject.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_notification_decrypted_subject.dart new file mode 100644 index 00000000000..4d1cf34b5f9 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_notification_decrypted_subject.dart @@ -0,0 +1,187 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PushNotificationDecryptedSubject { + /// Returns a new [PushNotificationDecryptedSubject] instance. + PushNotificationDecryptedSubject({ + this.nid, + this.app, + this.subject, + this.type, + this.id, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + int? nid; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? app; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? subject; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? type; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? id; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PushNotificationDecryptedSubject && + other.nid == nid && + other.app == app && + other.subject == subject && + other.type == type && + other.id == id; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (nid == null ? 0 : nid!.hashCode) + + (app == null ? 0 : app!.hashCode) + + (subject == null ? 0 : subject!.hashCode) + + (type == null ? 0 : type!.hashCode) + + (id == null ? 0 : id!.hashCode); + + @override + String toString() => 'PushNotificationDecryptedSubject[nid=$nid, app=$app, subject=$subject, type=$type, id=$id]'; + + Map toJson() { + final _json = {}; + if (nid != null) { + _json[r'nid'] = nid; + } + if (app != null) { + _json[r'app'] = app; + } + if (subject != null) { + _json[r'subject'] = subject; + } + if (type != null) { + _json[r'type'] = type; + } + if (id != null) { + _json[r'id'] = id; + } + return _json; + } + + /// Returns a new [PushNotificationDecryptedSubject] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PushNotificationDecryptedSubject? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "PushNotificationDecryptedSubject[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "PushNotificationDecryptedSubject[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PushNotificationDecryptedSubject( + nid: mapValueOfType(json, r'nid'), + app: mapValueOfType(json, r'app'), + subject: mapValueOfType(json, r'subject'), + type: mapValueOfType(json, r'type'), + id: mapValueOfType(json, r'id'), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PushNotificationDecryptedSubject.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushNotificationDecryptedSubject.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PushNotificationDecryptedSubject-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushNotificationDecryptedSubject.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_device.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_device.dart new file mode 100644 index 00000000000..dea9bfd34fe --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_device.dart @@ -0,0 +1,158 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PushServerDevice { + /// Returns a new [PushServerDevice] instance. + PushServerDevice({ + this.pushTokenHash, + this.devicePublicKey, + this.proxyServer, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? pushTokenHash; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? devicePublicKey; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? proxyServer; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PushServerDevice && + other.pushTokenHash == pushTokenHash && + other.devicePublicKey == devicePublicKey && + other.proxyServer == proxyServer; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (pushTokenHash == null ? 0 : pushTokenHash!.hashCode) + + (devicePublicKey == null ? 0 : devicePublicKey!.hashCode) + + (proxyServer == null ? 0 : proxyServer!.hashCode); + + @override + String toString() => + 'PushServerDevice[pushTokenHash=$pushTokenHash, devicePublicKey=$devicePublicKey, proxyServer=$proxyServer]'; + + Map toJson() { + final _json = {}; + if (pushTokenHash != null) { + _json[r'pushTokenHash'] = pushTokenHash; + } + if (devicePublicKey != null) { + _json[r'devicePublicKey'] = devicePublicKey; + } + if (proxyServer != null) { + _json[r'proxyServer'] = proxyServer; + } + return _json; + } + + /// Returns a new [PushServerDevice] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PushServerDevice? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "PushServerDevice[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "PushServerDevice[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PushServerDevice( + pushTokenHash: mapValueOfType(json, r'pushTokenHash'), + devicePublicKey: mapValueOfType(json, r'devicePublicKey'), + proxyServer: mapValueOfType(json, r'proxyServer'), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PushServerDevice.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerDevice.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PushServerDevice-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerDevice.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response.dart new file mode 100644 index 00000000000..b5477ae2681 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response.dart @@ -0,0 +1,125 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PushServerRegistrationResponse { + /// Returns a new [PushServerRegistrationResponse] instance. + PushServerRegistrationResponse({ + this.ocs, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + PushServerRegistrationResponseOcs? ocs; + + @override + bool operator ==(Object other) => + identical(this, other) || other is PushServerRegistrationResponse && other.ocs == ocs; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (ocs == null ? 0 : ocs!.hashCode); + + @override + String toString() => 'PushServerRegistrationResponse[ocs=$ocs]'; + + Map toJson() { + final _json = {}; + if (ocs != null) { + _json[r'ocs'] = ocs; + } + return _json; + } + + /// Returns a new [PushServerRegistrationResponse] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PushServerRegistrationResponse? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "PushServerRegistrationResponse[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "PushServerRegistrationResponse[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PushServerRegistrationResponse( + ocs: PushServerRegistrationResponseOcs.fromJson(json[r'ocs']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PushServerRegistrationResponse.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerRegistrationResponse.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PushServerRegistrationResponse-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerRegistrationResponse.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response_ocs.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response_ocs.dart new file mode 100644 index 00000000000..0cb005f8f10 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_registration_response_ocs.dart @@ -0,0 +1,133 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PushServerRegistrationResponseOcs { + /// Returns a new [PushServerRegistrationResponseOcs] instance. + PushServerRegistrationResponseOcs({ + this.meta, + this.data, + }); + + /// Stub + Object? meta; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + PushServerSubscription? data; + + @override + bool operator ==(Object other) => + identical(this, other) || other is PushServerRegistrationResponseOcs && other.meta == meta && other.data == data; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (meta == null ? 0 : meta!.hashCode) + (data == null ? 0 : data!.hashCode); + + @override + String toString() => 'PushServerRegistrationResponseOcs[meta=$meta, data=$data]'; + + Map toJson() { + final _json = {}; + if (meta != null) { + _json[r'meta'] = meta; + } + if (data != null) { + _json[r'data'] = data; + } + return _json; + } + + /// Returns a new [PushServerRegistrationResponseOcs] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PushServerRegistrationResponseOcs? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "PushServerRegistrationResponseOcs[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "PushServerRegistrationResponseOcs[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PushServerRegistrationResponseOcs( + meta: mapValueOfType(json, r'meta'), + data: PushServerSubscription.fromJson(json[r'data']), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PushServerRegistrationResponseOcs.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerRegistrationResponseOcs.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PushServerRegistrationResponseOcs-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerRegistrationResponseOcs.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_subscription.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_subscription.dart new file mode 100644 index 00000000000..e484378587c --- /dev/null +++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/push_server_subscription.dart @@ -0,0 +1,158 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class PushServerSubscription { + /// Returns a new [PushServerSubscription] instance. + PushServerSubscription({ + this.publicKey, + this.deviceIdentifier, + this.signature, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? publicKey; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? deviceIdentifier; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? signature; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PushServerSubscription && + other.publicKey == publicKey && + other.deviceIdentifier == deviceIdentifier && + other.signature == signature; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (publicKey == null ? 0 : publicKey!.hashCode) + + (deviceIdentifier == null ? 0 : deviceIdentifier!.hashCode) + + (signature == null ? 0 : signature!.hashCode); + + @override + String toString() => + 'PushServerSubscription[publicKey=$publicKey, deviceIdentifier=$deviceIdentifier, signature=$signature]'; + + Map toJson() { + final _json = {}; + if (publicKey != null) { + _json[r'publicKey'] = publicKey; + } + if (deviceIdentifier != null) { + _json[r'deviceIdentifier'] = deviceIdentifier; + } + if (signature != null) { + _json[r'signature'] = signature; + } + return _json; + } + + /// Returns a new [PushServerSubscription] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static PushServerSubscription? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), 'Required key "PushServerSubscription[$key]" is missing from JSON.'); + assert(json[key] != null, 'Required key "PushServerSubscription[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return PushServerSubscription( + publicKey: mapValueOfType(json, r'publicKey'), + deviceIdentifier: mapValueOfType(json, r'deviceIdentifier'), + signature: mapValueOfType(json, r'signature'), + ); + } + return null; + } + + static List? listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = PushServerSubscription.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerSubscription.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of PushServerSubscription-objects as value to a dart map + static Map> mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = PushServerSubscription.listFromJson( + entry.value, + growable: growable, + ); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/packages/nextcloud/lib/src/clients/notifications.dart b/packages/nextcloud/lib/src/clients/notifications.dart new file mode 100644 index 00000000000..c2489cc3cc0 --- /dev/null +++ b/packages/nextcloud/lib/src/clients/notifications.dart @@ -0,0 +1,98 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:crypto/crypto.dart'; +import 'package:crypton/crypton.dart'; +import 'package:nextcloud/src/clients/common/api.dart'; +import 'package:nextcloud/src/clients/generated/notifications/api.dart'; +import 'package:nextcloud/src/http_client_response_extension.dart'; + +// ignore: public_member_api_docs +class NextcloudNotificationsClient extends DefaultApi { + // ignore: public_member_api_docs + NextcloudNotificationsClient( + final String baseURL, + final Authentication authentication, + final ApiClient Function(ApiClient) addCommonSettings, + ) : super( + addCommonSettings( + ApiClient( + basePath: '$baseURL/ocs/v1.php/apps/notifications', + authentication: authentication, + ), + ), + ); + + @override + @Deprecated('Use registerDeviceAtServer instead') + Future registerDevice(PushServerDevice pushServerDevice) => + throw Exception('Use registerDeviceAtServer instead'); + + /// Registers a device at the Nextcloud server + Future registerDeviceAtServer( + final String pushToken, + final RSAPublicKey devicePublicKey, + final String proxyServer, + ) { + _validateProxyServerURL(proxyServer); + return super.registerDevice( + PushServerDevice( + pushTokenHash: generatePushTokenHash(pushToken), + devicePublicKey: devicePublicKey.toFormattedPEM(), + proxyServer: proxyServer, + ), + ); + } + + /// Registers a device at the push proxy server + Future registerDeviceAtPushProxy( + final String pushToken, + final PushServerSubscription subscription, + final String proxyServer, + ) async { + _validateProxyServerURL(proxyServer); + final request = await HttpClient().postUrl(Uri.parse('${proxyServer}devices')) + ..followRedirects = false + ..persistentConnection = true; + + request.headers.add(HttpHeaders.contentTypeHeader, 'application/x-www-form-urlencoded'); + + request.add( + utf8.encode( + Uri( + queryParameters: { + 'pushToken': pushToken, + 'deviceIdentifier': subscription.deviceIdentifier!, + 'deviceIdentifierSignature': subscription.signature!, + 'userPublicKey': subscription.publicKey!, + }, + ).query, + ), + ); + + final response = await request.close(); + + if (response.statusCode != 200) { + throw ApiException( + response.statusCode, + await response.body, + ); + } + } + + /// Generates the push token hash which is just sha512 + String generatePushTokenHash(final String pushToken) => sha512.convert(utf8.encode(pushToken)).toString(); + + /// Decrypts the subject of a push notification + PushNotificationDecryptedSubject decryptPushNotificationSubject( + final RSAPrivateKey privateKey, + final String subject, + ) => + PushNotificationDecryptedSubject.fromJson(json.decode(privateKey.decrypt(subject)) as Map)!; + + void _validateProxyServerURL(final String proxyServer) { + if (!proxyServer.endsWith('/')) { + throw Exception('proxyServer URL has to end with a /'); + } + } +} diff --git a/packages/nextcloud/lib/src/http_client_response_extension.dart b/packages/nextcloud/lib/src/http_client_response_extension.dart new file mode 100644 index 00000000000..d62fe5a8ef7 --- /dev/null +++ b/packages/nextcloud/lib/src/http_client_response_extension.dart @@ -0,0 +1,12 @@ +// ignore_for_file: public_member_api_docs + +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +extension HttpClientResponseBody on HttpClientResponse { + Future get bodyBytes async => + Uint8List.fromList((await toList()).reduce((final value, final element) => [...value, ...element])); + + Future get body async => utf8.decode(await bodyBytes); +} diff --git a/packages/nextcloud/pubspec.yaml b/packages/nextcloud/pubspec.yaml index 141c5b811af..59c241bd7af 100644 --- a/packages/nextcloud/pubspec.yaml +++ b/packages/nextcloud/pubspec.yaml @@ -5,6 +5,8 @@ environment: sdk: '>=2.17.0 <3.0.0' dependencies: + crypto: ^3.0.2 + crypton: ^2.0.5 http: ^0.13.4 intl: ^0.17.0 meta: ^1.7.0 @@ -12,7 +14,8 @@ dependencies: dev_dependencies: # coverage: ^1.3.2 - crypto: ^3.0.1 + nextcloud_push_proxy: + path: ../nextcloud_push_proxy nit_picking: git: url: https://github.com/stack11/dart_nit_picking diff --git a/packages/nextcloud/test/helper.dart b/packages/nextcloud/test/helper.dart index 5717ada510f..b2abb531c6c 100644 --- a/packages/nextcloud/test/helper.dart +++ b/packages/nextcloud/test/helper.dart @@ -136,10 +136,14 @@ class TestHelper { final String dockerImageName, { final String? username = defaultUsername, final String? password = defaultPassword, + final bool useAppPassword = false, final AppType appType = AppType.unknown, final String? userAgentSuffix, }) async { - final port = 1024 + Random().nextInt(65535 - 1024); + // ignore: prefer_asserts_with_message + assert(!useAppPassword || (username != null && password != null)); + + final port = randomPort(); final result = await runExecutableArguments( 'docker', @@ -149,6 +153,8 @@ class TestHelper { '-d', '-p', '$port:80', + '--add-host', + 'host.docker.internal:host-gateway', dockerImageName, ], ); @@ -159,11 +165,38 @@ class TestHelper { final containerID = result.stdout.toString().replaceAll('\n', ''); + var clientPassword = password; + if (useAppPassword) { + final inputStream = StreamController>(); + final process = runExecutableArguments( + 'docker', + [ + 'exec', + '-i', + containerID, + 'php', + '-f', + 'occ', + 'user:add-app-password', + username!, + ], + stdin: inputStream.stream, + ); + inputStream.add(utf8.encode(password!)); + await inputStream.close(); + + final result = await process; + if (result.exitCode != 0) { + throw Exception('Failed to run generate app password command\n${result.stderr}\n${result.stdout}'); + } + clientPassword = (result.stdout as String).split('\n')[1]; + } + final client = TestNextcloudClient( 'http://localhost:$port', containerID, username: username, - password: password, + password: clientPassword, appType: appType, userAgentSuffix: userAgentSuffix, ); @@ -222,6 +255,9 @@ class TestDockerHelper { generateInstallAppInstruction(app), ], ], + // Required to workaround restrictions for localhost and http only push proxies + '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/', '', ]; @@ -293,3 +329,11 @@ extension ListExtension on List { extension MapExtension on Map { Map removeNulls() => removeNullsFromMap(this); } + +int randomPort() => 1024 + Random().nextInt(65535 - 1024); + +void expectDateInReasonableTimeRange(final DateTime actual, final DateTime expected) { + const duration = Duration(seconds: 5); + expect(actual.isAfter(expected.subtract(duration)), isTrue); + expect(actual.isBefore(expected.add(duration)), isTrue); +} diff --git a/packages/nextcloud/test/notifications_test.dart b/packages/nextcloud/test/notifications_test.dart new file mode 100644 index 00000000000..6d40416f9bc --- /dev/null +++ b/packages/nextcloud/test/notifications_test.dart @@ -0,0 +1,220 @@ +import 'dart:async'; + +import 'package:nextcloud/nextcloud.dart'; +import 'package:nextcloud_push_proxy/nextcloud_push_proxy.dart'; +import 'package:test/test.dart'; + +import 'helper.dart'; + +Future main() async { + final dockerImageName = await TestHelper.prepareDockerImage(); + + group('notifications', () { + late TestNextcloudClient client; + setUp(() async { + client = await TestHelper.getPreparedClient( + dockerImageName, + username: 'admin', + ); + }); + tearDown(() => client.destroy()); + + Future sendTestNotification() async { + await validateResponse( + client.notifications, + client.notifications.sendAdminNotificationWithHttpInfo( + 'admin', + AdminNotification( + shortMessage: '123', + longMessage: '456', + ), + ), + ); + } + + test('Send admin notification', () async { + await sendTestNotification(); + }); + + test('List notifications', () async { + await sendTestNotification(); + + final startTime = DateTime.now().toUtc(); + final response = (await validateResponse( + client.notifications, + client.notifications.listNotificationsWithHttpInfo(), + ))!; + expect(response.ocs!.data, hasLength(1)); + expect(response.ocs!.data[0].notificationId, 1); + expect(response.ocs!.data[0].app, 'admin_notifications'); + expect(response.ocs!.data[0].user, 'admin'); + expectDateInReasonableTimeRange(DateTime.parse(response.ocs!.data[0].datetime!), startTime); + expect(response.ocs!.data[0].objectType, 'admin_notifications'); + expect(response.ocs!.data[0].objectId, isNotNull); + expect(response.ocs!.data[0].subject, '123'); + expect(response.ocs!.data[0].message, '456'); + expect(response.ocs!.data[0].link, ''); + expect(response.ocs!.data[0].subjectRich, ''); + expect(response.ocs!.data[0].subjectRichParameters, hasLength(0)); + expect(response.ocs!.data[0].messageRich, ''); + expect(response.ocs!.data[0].messageRichParameters, hasLength(0)); + expect(response.ocs!.data[0].icon, isNotEmpty); + expect(response.ocs!.data[0].actions, hasLength(0)); + }); + + test('Get notification', () async { + await sendTestNotification(); + + final startTime = DateTime.now().toUtc(); + final response = (await validateResponse( + client.notifications, + client.notifications.getNotificationWithHttpInfo(1), + ))!; + expect(response.ocs!.data!.notificationId, 1); + expect(response.ocs!.data!.app, 'admin_notifications'); + expect(response.ocs!.data!.user, 'admin'); + expectDateInReasonableTimeRange(DateTime.parse(response.ocs!.data!.datetime!), startTime); + expect(response.ocs!.data!.objectType, 'admin_notifications'); + expect(response.ocs!.data!.objectId, isNotNull); + expect(response.ocs!.data!.subject, '123'); + expect(response.ocs!.data!.message, '456'); + expect(response.ocs!.data!.link, ''); + expect(response.ocs!.data!.subjectRich, ''); + expect(response.ocs!.data!.subjectRichParameters, hasLength(0)); + expect(response.ocs!.data!.messageRich, ''); + expect(response.ocs!.data!.messageRichParameters, hasLength(0)); + expect(response.ocs!.data!.icon, isNotEmpty); + expect(response.ocs!.data!.actions, hasLength(0)); + }); + + test('Delete notification', () async { + await sendTestNotification(); + await validateResponse( + client.notifications, + client.notifications.deleteNotificationWithHttpInfo(1), + ); + + final response = (await validateResponse( + client.notifications, + client.notifications.listNotificationsWithHttpInfo(), + ))!; + expect(response.ocs!.data, hasLength(0)); + }); + + test('Delete all notifications', () async { + await sendTestNotification(); + await sendTestNotification(); + await validateResponse( + client.notifications, + client.notifications.deleteAllNotificationsWithHttpInfo(), + ); + + final response = (await validateResponse( + client.notifications, + client.notifications.listNotificationsWithHttpInfo(), + ))!; + expect(response.ocs!.data, hasLength(0)); + }); + }); + + group('push notifications', () { + late TestNextcloudClient client; + setUp(() async { + client = await TestHelper.getPreparedClient( + dockerImageName, + username: 'admin', + // We need to use app passwords in order to register push devices + useAppPassword: true, + ); + }); + tearDown(() => client.destroy()); + + // The key size has to be 2048, other sizes are not accepted by Nextcloud (at the moment at least) + // ignore: avoid_redundant_argument_values + RSAKeypair generateKeypair() => RSAKeypair.fromRandom(keySize: 2048); + + test('Register device and receive notification', () async { + const pushToken = '789'; + final port = randomPort(); + final keypair = generateKeypair(); + + final pushProxy = NextcloudPushProxy(); + + final subscription = (await client.notifications.registerDeviceAtServer( + pushToken, + keypair.publicKey, + 'http://host.docker.internal:$port/', + ))! + .ocs! + .data!; + expect(subscription.publicKey, hasLength(451)); + RSAPublicKey.fromPEM(subscription.publicKey!); + expect(subscription.deviceIdentifier, isNotEmpty); + expect(subscription.signature, isNotEmpty); + + final deviceCompleter = Completer(); + final notificationCompleter = Completer(); + + await pushProxy.create( + logging: false, + port: port, + ); + pushProxy.onNewDevice.listen((final device) async { + expect(device.pushToken, pushToken); + expect(device.deviceIdentifier, isNotEmpty); + expect(device.deviceIdentifierSignature, isNotEmpty); + expect(device.userPublicKey, isNotEmpty); + + deviceCompleter.complete(); + }); + pushProxy.onNewNotification.listen((final notification) async { + expect(notification.deviceIdentifier, subscription.deviceIdentifier); + expect(notification.pushTokenHash, client.notifications.generatePushTokenHash(pushToken)); + expect(notification.subject, isNotEmpty); + expect(notification.signature, isNotEmpty); + expect(notification.priority, 'normal'); + expect(notification.type, 'alert'); + + final decryptedSubject = + client.notifications.decryptPushNotificationSubject(keypair.privateKey, notification.subject); + expect(decryptedSubject.nid, isNotNull); + expect(decryptedSubject.app, 'admin_notifications'); + expect(decryptedSubject.subject, '123'); + expect(decryptedSubject.type, 'admin_notifications'); + expect(decryptedSubject.id, isNotEmpty); + + notificationCompleter.complete(); + }); + + await client.notifications.registerDeviceAtPushProxy( + pushToken, + subscription, + 'http://localhost:$port/', + ); + await client.notifications.sendAdminNotification( + 'admin', + AdminNotification( + shortMessage: '123', + longMessage: '456', + ), + ); + + await deviceCompleter.future; + await notificationCompleter.future; + await pushProxy.close(); + }); + + test('Remove push device', () async { + await client.notifications.registerDeviceAtServer( + '789', + generateKeypair().publicKey, + 'https://example.com/', + ); + + await validateResponse( + client.notifications, + client.notifications.removeDeviceWithHttpInfo(), + ); + }); + }); +} diff --git a/packages/nextcloud/test/webdav_test.dart b/packages/nextcloud/test/webdav_test.dart index 97e53cc205e..d014f154bc3 100644 --- a/packages/nextcloud/test/webdav_test.dart +++ b/packages/nextcloud/test/webdav_test.dart @@ -43,8 +43,7 @@ Future main() async { final file = files.singleWhere((final f) => f.name == 'Nextcloud.png'); expect(file.hasPreview, isTrue); expect(file.mimeType, 'image/png'); - expect(file.lastModified!.isBefore(DateTime.now()), isTrue); - expect(file.lastModified!.isAfter(DateTime.now().subtract(const Duration(seconds: 5))), isTrue); + expectDateInReasonableTimeRange(file.lastModified!, DateTime.now()); expect(file.size!, 50598); }); @@ -154,8 +153,7 @@ Future main() async { ); expect(file.hasPreview, isTrue); expect(file.mimeType, 'image/png'); - expect(file.lastModified!.isBefore(DateTime.now()), isTrue); - expect(file.lastModified!.isAfter(DateTime.now().subtract(const Duration(seconds: 5))), isTrue); + expectDateInReasonableTimeRange(file.lastModified!, DateTime.now()); expect(file.size!, 50598); }); @@ -176,8 +174,7 @@ Future main() async { expect(file.isDirectory, isTrue); expect(file.name, 'test'); expect(file.mimeType, null); - expect(file.lastModified!.isBefore(DateTime.now()), isTrue); - expect(file.lastModified!.isAfter(DateTime.now().subtract(const Duration(seconds: 5))), isTrue); + expectDateInReasonableTimeRange(file.lastModified!, DateTime.now()); expect(file.size!, data.lengthInBytes); }); @@ -225,8 +222,7 @@ Future main() async { ); expect(file.favorite, isTrue); expect(file.createdDate!.isAtSameMomentAs(createdDate), isTrue); - expect(file.uploadedDate!.isAfter(uploadTime), isTrue); - expect(file.uploadedDate!.isBefore(DateTime.now()), isTrue); + expectDateInReasonableTimeRange(file.uploadedDate!, uploadTime); }); test('Set custom properties', () async { diff --git a/specs/notifications.json b/specs/notifications.json new file mode 100644 index 00000000000..a3458604eeb --- /dev/null +++ b/specs/notifications.json @@ -0,0 +1,389 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Notifications", + "version": "2.12.0", + "description": "This app provides a backend and frontend for the notification API available in Nextcloud.", + "license": { + "name": "agpl" + } + }, + "servers": [ + { + "url": "https://{hostname}:{port}/ocs/v1.php/apps/notifications", + "variables": { + "hostname": { + "default": "localhost" + }, + "port": { + "default": "8080" + } + } + } + ], + "security": [ + { + "basic_auth": [] + } + ], + "components": { + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + } + }, + "schemas": { + "OCSMeta": { + "deprecated": true, + "description": "Stub" + }, + "AdminNotification": { + "type": "object", + "properties": { + "shortMessage": { + "type": "string" + }, + "longMessage": { + "type": "string" + } + } + }, + "EmptyResponse": { + "type": "object", + "properties": { + "ocs": { + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "Notification": { + "type": "object", + "properties": { + "notification_id": { + "type": "integer" + }, + "app": { + "type": "string" + }, + "user": { + "type": "string" + }, + "datetime": { + "type": "string" + }, + "object_type": { + "type": "string" + }, + "object_id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "message": { + "type": "string" + }, + "link": { + "type": "string" + }, + "subjectRich": { + "type": "string" + }, + "subjectRichParameters": { + "type": "array", + "items": { + "description": "TODO", + "type": "string" + } + }, + "messageRich": { + "type": "string" + }, + "messageRichParameters": { + "type": "array", + "items": { + "description": "TODO", + "type": "string" + } + }, + "icon": { + "type": "string" + }, + "actions": { + "type": "array", + "items": { + "description": "TODO", + "type": "string" + } + } + } + }, + "ListNotificationsResponse": { + "type": "object", + "properties": { + "ocs": { + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Notification" + } + } + } + } + } + }, + "GetNotificationResponse": { + "type": "object", + "properties": { + "ocs": { + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Notification" + } + } + } + } + }, + "PushServerDevice": { + "type": "object", + "properties": { + "pushTokenHash": { + "type": "string" + }, + "devicePublicKey": { + "type": "string" + }, + "proxyServer": { + "type": "string" + } + } + }, + "PushServerSubscription": { + "type": "object", + "properties": { + "publicKey": { + "type": "string" + }, + "deviceIdentifier": { + "type": "string" + }, + "signature": { + "type": "string" + } + } + }, + "PushServerRegistrationResponse": { + "type": "object", + "properties": { + "ocs": { + "type": "object", + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/PushServerSubscription" + } + } + } + } + }, + "PushNotificationDecryptedSubject": { + "type": "object", + "properties": { + "nid": { + "type": "integer" + }, + "app": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "type": { + "type": "string" + }, + "id": { + "type": "string" + } + } + } + } + }, + "paths": { + "/api/v2/notifications": { + "get": { + "operationId": "list-notifications", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "delete": { + "operationId": "delete-all-notifications", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/v2/notifications/{id}": { + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "get": { + "operationId": "get-notification", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetNotificationResponse" + } + } + } + } + } + }, + "delete": { + "operationId": "delete-notification", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + } + } + } + }, + "/api/v2/push": { + "post": { + "operationId": "register-device", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PushServerDevice" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PushServerRegistrationResponse" + } + } + } + } + } + }, + "delete": { + "operationId": "remove-device", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/v2/admin_notifications/{userId}": { + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "operationId": "send-admin-notification", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminNotification" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + } + } + } + } + } +} diff --git a/specs/templates/notifications.json b/specs/templates/notifications.json new file mode 100644 index 00000000000..41119898fe9 --- /dev/null +++ b/specs/templates/notifications.json @@ -0,0 +1,235 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Notifications", + "version": "2.12.0", + "description": "This app provides a backend and frontend for the notification API available in Nextcloud.", + "license": { + "name": "agpl" + } + }, + "servers": [ + { + "url": "https://{hostname}:{port}/ocs/v1.php/apps/notifications", + "variables": { + "hostname": { + "default": "localhost" + }, + "port": { + "default": "8080" + } + } + } + ], + "security": [ + { + "basic_auth": [] + } + ], + "components": { + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + } + } + }, + "paths": { + "/api/{apiVersion}/notifications": { + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "endpoint-listnotifications-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "delete": { + "operationId": "endpoint-deleteallnotifications-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/{apiVersion}/notifications/{id}": { + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "get": { + "operationId": "endpoint-getnotification-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "delete": { + "operationId": "endpoint-deletenotification-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/{apiVersion}/push": { + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "TODO" + } + } + ], + "post": { + "operationId": "push-registerdevice-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "delete": { + "operationId": "push-removedevice-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/{apiVersion}/admin_notifications/{userId}": { + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "TODO" + } + }, + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "operationId": "api-generatenotification-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + }, + "/api/{apiVersion}/settings": { + "parameters": [ + { + "name": "apiVersion", + "in": "path", + "required": true, + "schema": { + "type": "TODO" + } + } + ], + "post": { + "operationId": "settings-personal-TODO", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/tool/generate-nextcloud.sh b/tool/generate-nextcloud.sh index 0cea57f01fd..b06fe69959b 100755 --- a/tool/generate-nextcloud.sh +++ b/tool/generate-nextcloud.sh @@ -99,6 +99,7 @@ mkdir -p /tmp/nextcloud-harbour spec_templates_generate external/nextcloud-news false spec_templates_generate external/nextcloud-notes false +spec_templates_generate external/nextcloud-notifications false spec_templates_generate external/nextcloud-server/apps/provisioning_api false spec_templates_generate external/nextcloud-server/apps/user_status false spec_templates_generate external/nextcloud-server/core true @@ -107,6 +108,7 @@ openapi_generate "common" true openapi_generate "core" false openapi_generate "news" false openapi_generate "notes" false +openapi_generate "notifications" false openapi_generate "provisioning_api" false openapi_generate "user_status" false