Browse Source

Merge pull request #710 from nextcloud/feature/notifications-generated-spec

Feature/notifications generated spec
pull/725/head
Kate 1 year ago committed by GitHub
parent
commit
892441736f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      external/nextcloud-notifications
  2. 2
      packages/app/integration_test/screenshot_test.dart
  3. 4
      packages/neon/neon/lib/src/blocs/push_notifications.dart
  4. 4
      packages/neon/neon/lib/src/utils/push_utils.dart
  5. 13
      packages/neon/neon_notifications/lib/blocs/notifications.dart
  6. 6
      packages/nextcloud/lib/src/api/core.openapi.dart
  7. 60
      packages/nextcloud/lib/src/api/core.openapi.g.dart
  8. 6
      packages/nextcloud/lib/src/api/core.openapi.json
  9. 1525
      packages/nextcloud/lib/src/api/notifications.openapi.dart
  10. 4991
      packages/nextcloud/lib/src/api/notifications.openapi.g.dart
  11. 2034
      packages/nextcloud/lib/src/api/notifications.openapi.json
  12. 27
      packages/nextcloud/test/notifications_test.dart
  13. 28
      tool/generate-specs.sh

2
external/nextcloud-notifications vendored

@ -1 +1 @@
Subproject commit 09d3a1c9abcdd1c0ec4d8531907b56ac9f368666 Subproject commit 9e4bfdcf04d3a17402f4b22166e1afd4fc7ff833

2
packages/app/integration_test/screenshot_test.dart

@ -279,7 +279,7 @@ Future main() async {
}); });
testWidgets('notifications', (final tester) async { testWidgets('notifications', (final tester) async {
await (await getAccount('admin')).client.notifications.sendAdminNotification( await (await getAccount('admin')).client.notifications.api.generateNotification(
userId: account.username, userId: account.username,
shortMessage: 'Notifications demo', shortMessage: 'Notifications demo',
longMessage: 'This is a notifications demo of the Neon app', longMessage: 'This is a notifications demo of the Neon app',

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

@ -85,7 +85,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents,
debugPrint('Registering account $instance for push notifications on $endpoint'); debugPrint('Registering account $instance for push notifications on $endpoint');
final subscription = await account.client.notifications.registerDevice( final subscription = await account.client.notifications.push.registerDevice(
pushTokenHash: generatePushTokenHash(endpoint), pushTokenHash: generatePushTokenHash(endpoint),
devicePublicKey: keypair.publicKey.toFormattedPEM(), devicePublicKey: keypair.publicKey.toFormattedPEM(),
proxyServer: '$endpoint#', // This is a hack to make the Nextcloud server directly push to the endpoint proxyServer: '$endpoint#', // This is a hack to make the Nextcloud server directly push to the endpoint
@ -121,7 +121,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents,
Future _unregisterUnifiedPushInstances(final List<Account> accounts) async { Future _unregisterUnifiedPushInstances(final List<Account> accounts) async {
for (final account in accounts) { for (final account in accounts) {
try { try {
await account.client.notifications.removeDevice(); await account.client.notifications.push.removeDevice();
await UnifiedPush.unregister(account.id); await UnifiedPush.unregister(account.id);
await _storage.remove(_keyLastEndpoint(account)); await _storage.remove(_keyLastEndpoint(account));
} catch (e) { } catch (e) {

4
packages/neon/neon/lib/src/utils/push_utils.dart

@ -103,7 +103,9 @@ class PushUtils {
account = accounts.tryFind(instance); account = accounts.tryFind(instance);
if (account != null) { if (account != null) {
notification = notification =
(await account.client.notifications.getNotification(id: pushNotification.subject.nid!)).ocs.data; (await account.client.notifications.endpoint.getNotification(id: pushNotification.subject.nid!))
.ocs
.data;
if (notification.icon?.endsWith('.svg') ?? false) { if (notification.icon?.endsWith('.svg') ?? false) {
// Only SVG icons are supported right now (should be most of them) // Only SVG icons are supported right now (should be most of them)

13
packages/neon/neon_notifications/lib/blocs/notifications.dart

@ -50,22 +50,25 @@ class NotificationsBloc extends InteractiveBloc
@override @override
Future refresh() async { Future refresh() async {
await RequestManager.instance.wrapNextcloud<List<NotificationsNotification>, NotificationsListNotifications>( await RequestManager.instance.wrapNextcloud<
List<NotificationsNotification>,
NotificationsResponse<NotificationsEndpointListNotificationsResponseApplicationJson,
NotificationsEndpointEndpointListNotificationsHeaders>>(
_account.id, _account.id,
'notifications-notifications', 'notifications-notifications',
notifications, notifications,
() async => _account.client.notifications.listNotifications(), () async => _account.client.notifications.endpoint.listNotifications(),
(final response) => response.ocs.data.toList(), (final response) => response.data.ocs.data.toList(),
); );
} }
@override @override
void deleteAllNotifications() { void deleteAllNotifications() {
wrapAction(() async => _account.client.notifications.deleteAllNotifications()); wrapAction(() async => _account.client.notifications.endpoint.deleteAllNotifications());
} }
@override @override
void deleteNotification(final int id) { void deleteNotification(final int id) {
wrapAction(() async => _account.client.notifications.deleteNotification(id: id)); wrapAction(() async => _account.client.notifications.endpoint.deleteNotification(id: id));
} }
} }

6
packages/nextcloud/lib/src/api/core.openapi.dart

@ -4664,10 +4664,10 @@ abstract class CoreNotesCapabilities
@BuiltValue(instantiable: false) @BuiltValue(instantiable: false)
abstract interface class CoreNotificationsCapabilities_NotificationsInterface { abstract interface class CoreNotificationsCapabilities_NotificationsInterface {
@BuiltValueField(wireName: 'ocs-endpoints') @BuiltValueField(wireName: 'ocs-endpoints')
BuiltList<String>? get ocsEndpoints; BuiltList<String> get ocsEndpoints;
BuiltList<String>? get push; BuiltList<String> get push;
@BuiltValueField(wireName: 'admin-notifications') @BuiltValueField(wireName: 'admin-notifications')
BuiltList<String>? get adminNotifications; BuiltList<String> get adminNotifications;
CoreNotificationsCapabilities_NotificationsInterface rebuild( CoreNotificationsCapabilities_NotificationsInterface rebuild(
final void Function(CoreNotificationsCapabilities_NotificationsInterfaceBuilder) updates, final void Function(CoreNotificationsCapabilities_NotificationsInterfaceBuilder) updates,
); );

60
packages/nextcloud/lib/src/api/core.openapi.g.dart

@ -4077,26 +4077,15 @@ class _$CoreNotificationsCapabilities_NotificationsSerializer
@override @override
Iterable<Object?> serialize(Serializers serializers, CoreNotificationsCapabilities_Notifications object, Iterable<Object?> serialize(Serializers serializers, CoreNotificationsCapabilities_Notifications object,
{FullType specifiedType = FullType.unspecified}) { {FullType specifiedType = FullType.unspecified}) {
final result = <Object?>[]; final result = <Object?>[
Object? value; 'ocs-endpoints',
value = object.ocsEndpoints; serializers.serialize(object.ocsEndpoints, specifiedType: const FullType(BuiltList, [FullType(String)])),
if (value != null) { 'push',
result serializers.serialize(object.push, specifiedType: const FullType(BuiltList, [FullType(String)])),
..add('ocs-endpoints') 'admin-notifications',
..add(serializers.serialize(value, specifiedType: const FullType(BuiltList, [FullType(String)]))); serializers.serialize(object.adminNotifications, specifiedType: const FullType(BuiltList, [FullType(String)])),
} ];
value = object.push;
if (value != null) {
result
..add('push')
..add(serializers.serialize(value, specifiedType: const FullType(BuiltList, [FullType(String)])));
}
value = object.adminNotifications;
if (value != null) {
result
..add('admin-notifications')
..add(serializers.serialize(value, specifiedType: const FullType(BuiltList, [FullType(String)])));
}
return result; return result;
} }
@ -17095,17 +17084,24 @@ abstract mixin class CoreNotificationsCapabilities_NotificationsInterfaceBuilder
class _$CoreNotificationsCapabilities_Notifications extends CoreNotificationsCapabilities_Notifications { class _$CoreNotificationsCapabilities_Notifications extends CoreNotificationsCapabilities_Notifications {
@override @override
final BuiltList<String>? ocsEndpoints; final BuiltList<String> ocsEndpoints;
@override @override
final BuiltList<String>? push; final BuiltList<String> push;
@override @override
final BuiltList<String>? adminNotifications; final BuiltList<String> adminNotifications;
factory _$CoreNotificationsCapabilities_Notifications( factory _$CoreNotificationsCapabilities_Notifications(
[void Function(CoreNotificationsCapabilities_NotificationsBuilder)? updates]) => [void Function(CoreNotificationsCapabilities_NotificationsBuilder)? updates]) =>
(CoreNotificationsCapabilities_NotificationsBuilder()..update(updates))._build(); (CoreNotificationsCapabilities_NotificationsBuilder()..update(updates))._build();
_$CoreNotificationsCapabilities_Notifications._({this.ocsEndpoints, this.push, this.adminNotifications}) : super._(); _$CoreNotificationsCapabilities_Notifications._(
{required this.ocsEndpoints, required this.push, required this.adminNotifications})
: super._() {
BuiltValueNullFieldError.checkNotNull(ocsEndpoints, r'CoreNotificationsCapabilities_Notifications', 'ocsEndpoints');
BuiltValueNullFieldError.checkNotNull(push, r'CoreNotificationsCapabilities_Notifications', 'push');
BuiltValueNullFieldError.checkNotNull(
adminNotifications, r'CoreNotificationsCapabilities_Notifications', 'adminNotifications');
}
@override @override
CoreNotificationsCapabilities_Notifications rebuild( CoreNotificationsCapabilities_Notifications rebuild(
@ -17169,9 +17165,9 @@ class CoreNotificationsCapabilities_NotificationsBuilder
CoreNotificationsCapabilities_NotificationsBuilder get _$this { CoreNotificationsCapabilities_NotificationsBuilder get _$this {
final $v = _$v; final $v = _$v;
if ($v != null) { if ($v != null) {
_ocsEndpoints = $v.ocsEndpoints?.toBuilder(); _ocsEndpoints = $v.ocsEndpoints.toBuilder();
_push = $v.push?.toBuilder(); _push = $v.push.toBuilder();
_adminNotifications = $v.adminNotifications?.toBuilder(); _adminNotifications = $v.adminNotifications.toBuilder();
_$v = null; _$v = null;
} }
return this; return this;
@ -17196,18 +17192,16 @@ class CoreNotificationsCapabilities_NotificationsBuilder
try { try {
_$result = _$v ?? _$result = _$v ??
_$CoreNotificationsCapabilities_Notifications._( _$CoreNotificationsCapabilities_Notifications._(
ocsEndpoints: _ocsEndpoints?.build(), ocsEndpoints: ocsEndpoints.build(), push: push.build(), adminNotifications: adminNotifications.build());
push: _push?.build(),
adminNotifications: _adminNotifications?.build());
} catch (_) { } catch (_) {
late String _$failedField; late String _$failedField;
try { try {
_$failedField = 'ocsEndpoints'; _$failedField = 'ocsEndpoints';
_ocsEndpoints?.build(); ocsEndpoints.build();
_$failedField = 'push'; _$failedField = 'push';
_push?.build(); push.build();
_$failedField = 'adminNotifications'; _$failedField = 'adminNotifications';
_adminNotifications?.build(); adminNotifications.build();
} catch (e) { } catch (e) {
throw BuiltValueNestedFieldError(r'CoreNotificationsCapabilities_Notifications', _$failedField, e.toString()); throw BuiltValueNestedFieldError(r'CoreNotificationsCapabilities_Notifications', _$failedField, e.toString());
} }

6
packages/nextcloud/lib/src/api/core.openapi.json

@ -898,7 +898,11 @@
"properties": { "properties": {
"notifications": { "notifications": {
"type": "object", "type": "object",
"additionalProperties": true, "required": [
"ocs-endpoints",
"push",
"admin-notifications"
],
"properties": { "properties": {
"ocs-endpoints": { "ocs-endpoints": {
"type": "array", "type": "array",

1525
packages/nextcloud/lib/src/api/notifications.openapi.dart

File diff suppressed because it is too large Load Diff

4991
packages/nextcloud/lib/src/api/notifications.openapi.g.dart

File diff suppressed because it is too large Load Diff

2034
packages/nextcloud/lib/src/api/notifications.openapi.json

File diff suppressed because it is too large Load Diff

27
packages/nextcloud/test/notifications_test.dart

@ -22,7 +22,7 @@ void main() {
tearDown(() => container.destroy()); tearDown(() => container.destroy());
Future sendTestNotification() async { Future sendTestNotification() async {
await client.notifications.sendAdminNotification( await client.notifications.api.generateNotification(
userId: 'admin', userId: 'admin',
shortMessage: '123', shortMessage: '123',
longMessage: '456', longMessage: '456',
@ -37,7 +37,7 @@ void main() {
await sendTestNotification(); await sendTestNotification();
final startTime = DateTime.now().toUtc(); final startTime = DateTime.now().toUtc();
final response = await client.notifications.listNotifications(); final response = (await client.notifications.endpoint.listNotifications()).data;
expect(response.ocs.data, hasLength(2)); expect(response.ocs.data, hasLength(2));
expect(response.ocs.data[0].notificationId, 2); expect(response.ocs.data[0].notificationId, 2);
expect(response.ocs.data[0].app, 'admin_notifications'); expect(response.ocs.data[0].app, 'admin_notifications');
@ -49,9 +49,9 @@ void main() {
expect(response.ocs.data[0].message, '456'); expect(response.ocs.data[0].message, '456');
expect(response.ocs.data[0].link, ''); expect(response.ocs.data[0].link, '');
expect(response.ocs.data[0].subjectRich, ''); expect(response.ocs.data[0].subjectRich, '');
expect(response.ocs.data[0].subjectRichParameters?.asList, isEmpty); expect(response.ocs.data[0].subjectRichParameters, isEmpty);
expect(response.ocs.data[0].messageRich, ''); expect(response.ocs.data[0].messageRich, '');
expect(response.ocs.data[0].messageRichParameters?.asList, isEmpty); expect(response.ocs.data[0].messageRichParameters, isEmpty);
expect(response.ocs.data[0].icon, isNotEmpty); expect(response.ocs.data[0].icon, isNotEmpty);
expect(response.ocs.data[0].actions, hasLength(0)); expect(response.ocs.data[0].actions, hasLength(0));
}); });
@ -60,7 +60,7 @@ void main() {
await sendTestNotification(); await sendTestNotification();
final startTime = DateTime.now().toUtc(); final startTime = DateTime.now().toUtc();
final response = await client.notifications.getNotification(id: 2); final response = await client.notifications.endpoint.getNotification(id: 2);
expect(response.ocs.data.notificationId, 2); expect(response.ocs.data.notificationId, 2);
expect(response.ocs.data.app, 'admin_notifications'); expect(response.ocs.data.app, 'admin_notifications');
expect(response.ocs.data.user, 'admin'); expect(response.ocs.data.user, 'admin');
@ -71,27 +71,27 @@ void main() {
expect(response.ocs.data.message, '456'); expect(response.ocs.data.message, '456');
expect(response.ocs.data.link, ''); expect(response.ocs.data.link, '');
expect(response.ocs.data.subjectRich, ''); expect(response.ocs.data.subjectRich, '');
expect(response.ocs.data.subjectRichParameters?.asList, isEmpty); expect(response.ocs.data.subjectRichParameters, isEmpty);
expect(response.ocs.data.messageRich, ''); expect(response.ocs.data.messageRich, '');
expect(response.ocs.data.messageRichParameters?.asList, isEmpty); expect(response.ocs.data.messageRichParameters, isEmpty);
expect(response.ocs.data.icon, isNotEmpty); expect(response.ocs.data.icon, isNotEmpty);
expect(response.ocs.data.actions, hasLength(0)); expect(response.ocs.data.actions, hasLength(0));
}); });
test('Delete notification', () async { test('Delete notification', () async {
await sendTestNotification(); await sendTestNotification();
await client.notifications.deleteNotification(id: 2); await client.notifications.endpoint.deleteNotification(id: 2);
final response = await client.notifications.listNotifications(); final response = (await client.notifications.endpoint.listNotifications()).data;
expect(response.ocs.data, hasLength(1)); expect(response.ocs.data, hasLength(1));
}); });
test('Delete all notifications', () async { test('Delete all notifications', () async {
await sendTestNotification(); await sendTestNotification();
await sendTestNotification(); await sendTestNotification();
await client.notifications.deleteAllNotifications(); await client.notifications.endpoint.deleteAllNotifications();
final response = await client.notifications.listNotifications(); final response = (await client.notifications.endpoint.listNotifications()).data;
expect(response.ocs.data, hasLength(0)); expect(response.ocs.data, hasLength(0));
}); });
}); });
@ -121,7 +121,7 @@ void main() {
const pushToken = '789'; const pushToken = '789';
final keypair = generateKeypair(); final keypair = generateKeypair();
final subscription = (await client.notifications.registerDevice( final subscription = (await client.notifications.push.registerDevice(
pushTokenHash: generatePushTokenHash(pushToken), pushTokenHash: generatePushTokenHash(pushToken),
devicePublicKey: keypair.publicKey.toFormattedPEM(), devicePublicKey: keypair.publicKey.toFormattedPEM(),
proxyServer: 'https://example.com/', proxyServer: 'https://example.com/',
@ -132,9 +132,8 @@ void main() {
RSAPublicKey.fromPEM(subscription.publicKey); RSAPublicKey.fromPEM(subscription.publicKey);
expect(subscription.deviceIdentifier, isNotEmpty); expect(subscription.deviceIdentifier, isNotEmpty);
expect(subscription.signature, isNotEmpty); expect(subscription.signature, isNotEmpty);
expect(subscription.message, isNull);
await client.notifications.removeDevice(); await client.notifications.push.removeDevice();
}); });
}, },
retry: retryCount, retry: retryCount,

28
tool/generate-specs.sh

@ -5,12 +5,20 @@ cd "$(dirname "$0")/.."
rm -rf /tmp/nextcloud-neon rm -rf /tmp/nextcloud-neon
mkdir -p /tmp/nextcloud-neon mkdir -p /tmp/nextcloud-neon
( function generate_spec() {
cd external/nextcloud-server path="$1"
composer update codename="$2"
composer install --no-dev composer exec generate-spec -- "$path" "../../packages/nextcloud/lib/src/api/$codename.openapi.json" --first-content-type --openapi-version 3.1.0
git checkout . # Remove changed files }
)
for dir in external/nextcloud-server external/nextcloud-notifications; do
(
cd "$dir"
composer update
composer install --no-dev
git checkout . # Remove changed files
)
done
for path in \ for path in \
core \ core \
@ -31,13 +39,17 @@ for path in \
apps/user_status \ apps/user_status \
apps/weather_status \ apps/weather_status \
; do ; do
codename="$(echo $path | sed "s/^apps\///")"
( (
cd external/nextcloud-server cd external/nextcloud-server
composer exec generate-spec -- "$path" "../../packages/nextcloud/lib/src/api/$codename.openapi.json" --first-content-type --openapi-version 3.1.0 generate_spec "$path" "$(basename $path)"
) )
done done
(
cd external/nextcloud-notifications
generate_spec "." "notifications"
)
( (
cd external/nextcloud-server cd external/nextcloud-server
composer exec merge-specs -- --core ../../packages/nextcloud/lib/src/api/core.openapi.json --merged /tmp/nextcloud-neon/merged.json ../../packages/nextcloud/lib/src/api/*.openapi.json --openapi-version 3.1.0 composer exec merge-specs -- --core ../../packages/nextcloud/lib/src/api/core.openapi.json --merged /tmp/nextcloud-neon/merged.json ../../packages/nextcloud/lib/src/api/*.openapi.json --openapi-version 3.1.0

Loading…
Cancel
Save