diff --git a/.gitmodules b/.gitmodules index 787dc672..117f9b69 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 611fc781..6b5ae81c 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 00000000..62c670f2 --- /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 00000000..6fafeb7b --- /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 00000000..58ddd9ab --- /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 00000000..c983d548 --- /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 00000000..2cd835c7 --- /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 00000000..45319629 --- /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 00000000..48f88537 --- /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 00000000..53f4e3d6 --- /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 00000000..57fc6d59 --- /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 00000000..c9f80d1c --- /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 00000000..a32f0de9 --- /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 00000000..b2091f59 --- /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 00000000..64f5dd69 --- /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 00000000..f28ad419 --- /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 00000000..35581a35 --- /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 11772ab4..c240ef2b 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 085db14b..97656ec4 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 35ead488..00331144 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 5d7e664c..c0653380 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 00000000..60138dc8 --- /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 00000000..7a6bbe0e --- /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 00000000..69aca6f0 --- /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 00000000..6b7ccd22 --- /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 00000000..f8190763 --- /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 00000000..e5f3157b --- /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 00000000..dbf5b865 --- /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 00000000..6b7883ce --- /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 00000000..b180f52e --- /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 00000000..6643159d --- /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 00000000..90ec5a56 --- /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 00000000..4d1cf34b --- /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 00000000..dea9bfd3 --- /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 00000000..b5477ae2 --- /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 00000000..0cb005f8 --- /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 00000000..e4843785 --- /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 00000000..c2489cc3 --- /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 00000000..d62fe5a8 --- /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 141c5b81..59c241bd 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 5717ada5..b2abb531 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 00000000..6d40416f --- /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 97e53cc2..d014f154 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 00000000..a3458604 --- /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 00000000..41119898 --- /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 0cea57f0..b06fe699 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