diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 1c6a826d..d769f5a6 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -101,38 +101,6 @@ jobs: needs: - job_001 job_004: - name: "all; PKG: packages/nextcloud_push_proxy; `dart analyze --fatal-infos .`" - runs-on: ubuntu-latest - steps: - - name: Cache Pub hosted dependencies - uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 - with: - path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud_push_proxy;commands:analyze_0" - restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud_push_proxy - os:ubuntu-latest;pub-cache-hosted;sdk:stable - os:ubuntu-latest;pub-cache-hosted - os:ubuntu-latest - - name: Setup Dart SDK - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 - with: - sdk: stable - - id: checkout - name: Checkout repository - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - id: packages_nextcloud_push_proxy_pub_upgrade - name: packages/nextcloud_push_proxy; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/nextcloud_push_proxy - - name: "packages/nextcloud_push_proxy; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'" - working-directory: packages/nextcloud_push_proxy - needs: - - job_001 - job_005: name: "all; PKG: packages/nextcloud_test; `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -164,7 +132,7 @@ jobs: working-directory: packages/nextcloud_test needs: - job_001 - job_006: + job_005: name: "all; PKG: packages/sort_box; `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -196,7 +164,7 @@ jobs: working-directory: packages/sort_box needs: - job_001 - job_007: + job_006: name: "all; PKG: packages/spec_templates; `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -228,7 +196,7 @@ jobs: working-directory: packages/spec_templates needs: - job_001 - job_008: + job_007: name: "all; PKG: packages/dynamite; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -260,7 +228,7 @@ jobs: working-directory: packages/dynamite needs: - job_001 - job_009: + job_008: name: "all; PKG: packages/file_icons; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -292,7 +260,7 @@ jobs: working-directory: packages/file_icons needs: - job_001 - job_010: + job_009: name: "all; PKG: packages/neon; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -324,7 +292,7 @@ jobs: working-directory: packages/neon needs: - job_001 - job_011: + job_010: name: "all; PKG: packages/nextcloud; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -356,39 +324,7 @@ jobs: working-directory: packages/nextcloud needs: - job_001 - job_012: - name: "all; PKG: packages/nextcloud_push_proxy; `dart format --output=none --set-exit-if-changed --line-length 120 .`" - runs-on: ubuntu-latest - steps: - - name: Cache Pub hosted dependencies - uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 - with: - path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud_push_proxy;commands:format" - restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud_push_proxy - os:ubuntu-latest;pub-cache-hosted;sdk:stable - os:ubuntu-latest;pub-cache-hosted - os:ubuntu-latest - - name: Setup Dart SDK - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 - with: - sdk: stable - - id: checkout - name: Checkout repository - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - id: packages_nextcloud_push_proxy_pub_upgrade - name: packages/nextcloud_push_proxy; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: packages/nextcloud_push_proxy - - name: "packages/nextcloud_push_proxy; dart format --output=none --set-exit-if-changed --line-length 120 ." - run: "dart format --output=none --set-exit-if-changed --line-length 120 ." - if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'" - working-directory: packages/nextcloud_push_proxy - needs: - - job_001 - job_013: + job_011: name: "all; PKG: packages/nextcloud_test; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -420,7 +356,7 @@ jobs: working-directory: packages/nextcloud_test needs: - job_001 - job_014: + job_012: name: "all; PKG: packages/settings; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -452,7 +388,7 @@ jobs: working-directory: packages/settings needs: - job_001 - job_015: + job_013: name: "all; PKG: packages/sort_box; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -484,7 +420,7 @@ jobs: working-directory: packages/sort_box needs: - job_001 - job_016: + job_014: name: "all; PKG: packages/spec_templates; `dart format --output=none --set-exit-if-changed --line-length 120 .`" runs-on: ubuntu-latest steps: @@ -516,7 +452,7 @@ jobs: working-directory: packages/spec_templates needs: - job_001 - job_017: + job_015: name: "all; PKG: packages/file_icons; `flutter analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -548,7 +484,7 @@ jobs: working-directory: packages/file_icons needs: - job_001 - job_018: + job_016: name: "all; PKG: packages/neon; `flutter analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -580,7 +516,7 @@ jobs: working-directory: packages/neon needs: - job_001 - job_019: + job_017: name: "all; PKG: packages/settings; `flutter analyze --fatal-infos .`" runs-on: ubuntu-latest steps: @@ -612,7 +548,7 @@ jobs: working-directory: packages/settings needs: - job_001 - job_020: + job_018: name: "all; PKG: packages/nextcloud; `dart test`" runs-on: ubuntu-latest steps: @@ -644,7 +580,7 @@ jobs: working-directory: packages/nextcloud needs: - job_001 - job_021: + job_019: name: "all; PKG: packages/sort_box; `dart test`" runs-on: ubuntu-latest steps: diff --git a/packages/nextcloud/lib/src/helpers.dart b/packages/nextcloud/lib/src/helpers.dart index b4f116c3..a6b4895f 100644 --- a/packages/nextcloud/lib/src/helpers.dart +++ b/packages/nextcloud/lib/src/helpers.dart @@ -2,64 +2,24 @@ part of '../nextcloud.dart'; -extension UserDetailsDisplayName on openapi.NextcloudProvisioningApiUserDetails { - /// This is used to work around an API change that wasn't made for every endpoint - /// See https://github.com/nextcloud/server/commit/5086335643b6181284ee50f57b95525002842992 - String? getDisplayName() => displayname ?? displayName; -} - -extension NextcloudNotificationsPushProxy on NextcloudNotificationsClient { - /// Registers a device at the push proxy server - Future registerDeviceAtPushProxy( - final String pushToken, - final NextcloudNotificationsPushServerSubscription subscription, - final String proxyServer, - ) async { - 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) { - // coverage:ignore-start - throw NextcloudApiException( - response.statusCode, - {}, // TODO - await response.bodyBytes, - ); - // coverage:ignore-end - } - } - - /// Generates the push token hash which is just sha512 - String generatePushTokenHash(final String pushToken) => sha512.convert(utf8.encode(pushToken)).toString(); -} +/// 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 -NextcloudNotificationsPushNotificationDecryptedSubject decryptPushNotificationSubject( +NextcloudNotificationsNotificationDecryptedSubject decryptPushNotificationSubject( final RSAPrivateKey privateKey, final String subject, ) => - NextcloudNotificationsPushNotificationDecryptedSubject.fromJson( + NextcloudNotificationsNotificationDecryptedSubject.fromJson( json.decode(privateKey.decrypt(subject)) as Map, ); +extension UserDetailsDisplayName on openapi.NextcloudProvisioningApiUserDetails { + /// This is used to work around an API change that wasn't made for every endpoint + /// See https://github.com/nextcloud/server/commit/5086335643b6181284ee50f57b95525002842992 + String? getDisplayName() => displayname ?? displayName; +} + /// See https://github.com/nextcloud/news/blob/4a107b3d53c4fe651ac704251b99e04a53cd587f/lib/Db/ListType.php enum NewsListType { feed(0), diff --git a/packages/nextcloud/lib/src/nextcloud.openapi.dart b/packages/nextcloud/lib/src/nextcloud.openapi.dart index 54a2ecb6..cfd669c4 100644 --- a/packages/nextcloud/lib/src/nextcloud.openapi.dart +++ b/packages/nextcloud/lib/src/nextcloud.openapi.dart @@ -5178,8 +5178,8 @@ class NextcloudUserStatusPredefinedStatuses { } @JsonSerializable() -class NextcloudNotificationsPushNotificationDecryptedSubject { - NextcloudNotificationsPushNotificationDecryptedSubject({ +class NextcloudNotificationsNotificationDecryptedSubject { + NextcloudNotificationsNotificationDecryptedSubject({ this.nid, this.app, this.subject, @@ -5190,13 +5190,13 @@ class NextcloudNotificationsPushNotificationDecryptedSubject { }); // coverage:ignore-start - factory NextcloudNotificationsPushNotificationDecryptedSubject.fromJson(Map json) => - _$NextcloudNotificationsPushNotificationDecryptedSubjectFromJson(json); + factory NextcloudNotificationsNotificationDecryptedSubject.fromJson(Map json) => + _$NextcloudNotificationsNotificationDecryptedSubjectFromJson(json); // coverage:ignore-end // coverage:ignore-start - factory NextcloudNotificationsPushNotificationDecryptedSubject.fromJsonString(String data) => - NextcloudNotificationsPushNotificationDecryptedSubject.fromJson(json.decode(data) as Map); + factory NextcloudNotificationsNotificationDecryptedSubject.fromJsonString(String data) => + NextcloudNotificationsNotificationDecryptedSubject.fromJson(json.decode(data) as Map); // coverage:ignore-end final int? nid; @@ -5215,43 +5215,9 @@ class NextcloudNotificationsPushNotificationDecryptedSubject { final bool? deleteAll; // coverage:ignore-start - Map toJson() => _$NextcloudNotificationsPushNotificationDecryptedSubjectToJson(this); + Map toJson() => _$NextcloudNotificationsNotificationDecryptedSubjectToJson(this); // coverage:ignore-end - static String? toJsonString(NextcloudNotificationsPushNotificationDecryptedSubject? data) => - data == null ? null : json.encode(data.toJson()); -} - -@JsonSerializable() -class NextcloudNotificationsPushNotification { - NextcloudNotificationsPushNotification({ - required this.accountID, - required this.priority, - required this.type, - required this.subject, - }); - - // coverage:ignore-start - factory NextcloudNotificationsPushNotification.fromJson(Map json) => - _$NextcloudNotificationsPushNotificationFromJson(json); - // coverage:ignore-end - - // coverage:ignore-start - factory NextcloudNotificationsPushNotification.fromJsonString(String data) => - NextcloudNotificationsPushNotification.fromJson(json.decode(data) as Map); - // coverage:ignore-end - - final String accountID; - - final String priority; - - final String type; - - final NextcloudNotificationsPushNotificationDecryptedSubject subject; - - // coverage:ignore-start - Map toJson() => _$NextcloudNotificationsPushNotificationToJson(this); - // coverage:ignore-end - static String? toJsonString(NextcloudNotificationsPushNotification? data) => + static String? toJsonString(NextcloudNotificationsNotificationDecryptedSubject? data) => data == null ? null : json.encode(data.toJson()); } @@ -5773,15 +5739,10 @@ final _deserializers = { NextcloudUserStatusPredefinedStatus.fromJson(data as Map), List: (final data) => (data as List).map((final e) => NextcloudUserStatusPredefinedStatus.fromJson(e as Map)).toList(), - NextcloudNotificationsPushNotification: (final data) => - NextcloudNotificationsPushNotification.fromJson(data as Map), - List: (final data) => (data as List) - .map((final e) => NextcloudNotificationsPushNotification.fromJson(e as Map)) - .toList(), - NextcloudNotificationsPushNotificationDecryptedSubject: (final data) => - NextcloudNotificationsPushNotificationDecryptedSubject.fromJson(data as Map), - List: (final data) => (data as List) - .map((final e) => NextcloudNotificationsPushNotificationDecryptedSubject.fromJson(e as Map)) + NextcloudNotificationsNotificationDecryptedSubject: (final data) => + NextcloudNotificationsNotificationDecryptedSubject.fromJson(data as Map), + List: (final data) => (data as List) + .map((final e) => NextcloudNotificationsNotificationDecryptedSubject.fromJson(e as Map)) .toList(), }; @@ -6036,11 +5997,8 @@ final _serializers = { List: (final data) => data.map((final e) => e.toJson()).toList(), NextcloudUserStatusPredefinedStatus: (final data) => data.toJson(), List: (final data) => data.map((final e) => e.toJson()).toList(), - NextcloudNotificationsPushNotification: (final data) => data.toJson(), - List: (final data) => data.map((final e) => e.toJson()).toList(), - NextcloudNotificationsPushNotificationDecryptedSubject: (final data) => data.toJson(), - List: (final data) => - data.map((final e) => e.toJson()).toList(), + NextcloudNotificationsNotificationDecryptedSubject: (final data) => data.toJson(), + List: (final data) => data.map((final e) => e.toJson()).toList(), }; T deserializeNextcloud(final dynamic data) => _deserializers[T]!(data) as T; diff --git a/packages/nextcloud/lib/src/nextcloud.openapi.g.dart b/packages/nextcloud/lib/src/nextcloud.openapi.g.dart index 3b45fd43..c5bb7fa6 100644 --- a/packages/nextcloud/lib/src/nextcloud.openapi.g.dart +++ b/packages/nextcloud/lib/src/nextcloud.openapi.g.dart @@ -2193,13 +2193,13 @@ Map _$NextcloudUserStatusPredefinedStatusesToJson(NextcloudUser 'ocs': instance.ocs.toJson(), }; -NextcloudNotificationsPushNotificationDecryptedSubject _$NextcloudNotificationsPushNotificationDecryptedSubjectFromJson( +NextcloudNotificationsNotificationDecryptedSubject _$NextcloudNotificationsNotificationDecryptedSubjectFromJson( Map json) { $checkKeys( json, allowedKeys: const ['nid', 'app', 'subject', 'type', 'id', 'delete', 'delete-all'], ); - return NextcloudNotificationsPushNotificationDecryptedSubject( + return NextcloudNotificationsNotificationDecryptedSubject( nid: json['nid'] as int?, app: json['app'] as String?, subject: json['subject'] as String?, @@ -2210,8 +2210,8 @@ NextcloudNotificationsPushNotificationDecryptedSubject _$NextcloudNotificationsP ); } -Map _$NextcloudNotificationsPushNotificationDecryptedSubjectToJson( - NextcloudNotificationsPushNotificationDecryptedSubject instance) => +Map _$NextcloudNotificationsNotificationDecryptedSubjectToJson( + NextcloudNotificationsNotificationDecryptedSubject instance) => { 'nid': instance.nid, 'app': instance.app, @@ -2221,24 +2221,3 @@ Map _$NextcloudNotificationsPushNotificationDecryptedSubjectToJ 'delete': instance.delete, 'delete-all': instance.deleteAll, }; - -NextcloudNotificationsPushNotification _$NextcloudNotificationsPushNotificationFromJson(Map json) { - $checkKeys( - json, - allowedKeys: const ['accountID', 'priority', 'type', 'subject'], - ); - return NextcloudNotificationsPushNotification( - accountID: json['accountID'] as String, - priority: json['priority'] as String, - type: json['type'] as String, - subject: NextcloudNotificationsPushNotificationDecryptedSubject.fromJson(json['subject'] as Map), - ); -} - -Map _$NextcloudNotificationsPushNotificationToJson(NextcloudNotificationsPushNotification instance) => - { - 'accountID': instance.accountID, - 'priority': instance.priority, - 'type': instance.type, - 'subject': instance.subject.toJson(), - }; diff --git a/packages/nextcloud/lib/src/nextcloud.openapi.json b/packages/nextcloud/lib/src/nextcloud.openapi.json index d83dd6bb..177e7066 100644 --- a/packages/nextcloud/lib/src/nextcloud.openapi.json +++ b/packages/nextcloud/lib/src/nextcloud.openapi.json @@ -1471,30 +1471,7 @@ } } }, - "NotificationsPushNotification": { - "type": "object", - "required": [ - "accountID", - "priority", - "type", - "subject" - ], - "properties": { - "accountID": { - "type": "string" - }, - "priority": { - "type": "string" - }, - "type": { - "type": "string" - }, - "subject": { - "$ref": "#/components/schemas/NotificationsPushNotificationDecryptedSubject" - } - } - }, - "NotificationsPushNotificationDecryptedSubject": { + "NotificationsNotificationDecryptedSubject": { "type": "object", "properties": { "nid": { diff --git a/packages/nextcloud/pubspec.yaml b/packages/nextcloud/pubspec.yaml index d9e2b3d0..e412c8bd 100644 --- a/packages/nextcloud/pubspec.yaml +++ b/packages/nextcloud/pubspec.yaml @@ -6,7 +6,7 @@ environment: dependencies: cookie_jar: ^3.0.1 - crypto: ^3.0.1 + crypto: ^3.0.2 crypton: ^2.0.5 intl: ^0.17.0 json_annotation: ^4.7.0 @@ -19,8 +19,6 @@ dev_dependencies: dynamite: path: ../dynamite json_serializable: ^6.3.2 - nextcloud_push_proxy: - path: ../nextcloud_push_proxy nextcloud_test: path: ../nextcloud_test nit_picking: diff --git a/packages/nextcloud/test/notifications.dart b/packages/nextcloud/test/notifications.dart index b446525d..0d10ee1c 100644 --- a/packages/nextcloud/test/notifications.dart +++ b/packages/nextcloud/test/notifications.dart @@ -1,8 +1,6 @@ import 'dart:async'; -import 'dart:io'; import 'package:nextcloud/nextcloud.dart'; -import 'package:nextcloud_push_proxy/nextcloud_push_proxy.dart'; import 'package:nextcloud_test/nextcloud_test.dart'; import 'package:test/test.dart'; @@ -117,95 +115,12 @@ Future run(final DockerImage image) async { // ignore: avoid_redundant_argument_values RSAKeypair generateKeypair() => RSAKeypair.fromRandom(keySize: 2048); - test('Register device and receive notification', () async { - const pushToken = '789'; - final keypair = generateKeypair(); - - final pushProxy = NextcloudPushProxy(); - - late int port; - while (true) { - port = randomPort(); - try { - await pushProxy.create( - logging: false, - port: port, - ); - break; - } on SocketException catch (e) { - if (e.osError?.errorCode != 98) { - rethrow; - } - } - } - - final subscription = (await client.notifications.registerDevice( - pushTokenHash: client.notifications.generatePushTokenHash(pushToken), - devicePublicKey: keypair.publicKey.toFormattedPEM(), - proxyServer: 'http://host.docker.internal:$port/', - )) - .ocs - .data; - expect(subscription.publicKey, hasLength(451)); - RSAPublicKey.fromPEM(subscription.publicKey); - expect(subscription.deviceIdentifier, isNotEmpty); - expect(subscription.signature, isNotEmpty); - expect(subscription.message, isNull); - - final deviceCompleter = Completer(); - final notificationCompleter = Completer(); - - 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 = 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( - userId: 'admin', - shortMessage: '123', - longMessage: '456', - ); - - await deviceCompleter.future; - await notificationCompleter.future; - await pushProxy.close(); - }); - - test('Remove push device', () async { + test('Register and remove push device', () async { const pushToken = '789'; final keypair = generateKeypair(); final subscription = (await client.notifications.registerDevice( - pushTokenHash: client.notifications.generatePushTokenHash(pushToken), + pushTokenHash: generatePushTokenHash(pushToken), devicePublicKey: keypair.publicKey.toFormattedPEM(), proxyServer: 'https://example.com/', )) diff --git a/packages/nextcloud_push_proxy/.gitignore b/packages/nextcloud_push_proxy/.gitignore deleted file mode 100644 index 1a1d9ab8..00000000 --- a/packages/nextcloud_push_proxy/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -# Files and directories created by pub. -.dart_tool/ -.packages - -# Conventional directory for build outputs. -build/ - -# Omit committing pubspec.lock for library packages; see -# https://dart.dev/guides/libraries/private-files#pubspeclock. -pubspec.lock - -tmp/ diff --git a/packages/nextcloud_push_proxy/Dockerfile b/packages/nextcloud_push_proxy/Dockerfile deleted file mode 100644 index 7efde200..00000000 --- a/packages/nextcloud_push_proxy/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM dart:stable as builder - -WORKDIR /app - -ADD pubspec.yaml . -RUN dart pub get - - -ADD lib ./lib -ADD bin ./bin -RUN dart compile exe bin/unified_push.dart -o bin/nextcloud-push-proxy - -FROM debian:bullseye-slim - -COPY --from=builder /app/bin/nextcloud-push-proxy /usr/local/bin/ - -CMD ["nextcloud-push-proxy", "/data/devices.json"] diff --git a/packages/nextcloud_push_proxy/LICENSE b/packages/nextcloud_push_proxy/LICENSE deleted file mode 120000 index 30cff740..00000000 --- a/packages/nextcloud_push_proxy/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE \ No newline at end of file diff --git a/packages/nextcloud_push_proxy/analysis_options.yaml b/packages/nextcloud_push_proxy/analysis_options.yaml deleted file mode 100644 index 0ed2fb9f..00000000 --- a/packages/nextcloud_push_proxy/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:nit_picking/dart.yaml diff --git a/packages/nextcloud_push_proxy/bin/unified_push.dart b/packages/nextcloud_push_proxy/bin/unified_push.dart deleted file mode 100644 index 860c9298..00000000 --- a/packages/nextcloud_push_proxy/bin/unified_push.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:crypto/crypto.dart'; -import 'package:nextcloud_push_proxy/nextcloud_push_proxy.dart'; - -Future main(final List args) async { - if (args.length != 1) { - throw Exception('Provide the file where to store devices'); - } - final devices = []; - final devicesFile = File(args[0]); - if (devicesFile.existsSync()) { - devices.addAll( - (json.decode(devicesFile.readAsStringSync()) as List) - .map((final d) => PushProxyDevice.fromJson(d as Map)), - ); - } - - final server = NextcloudPushProxy(); - - watchSignals((final signal) async { - print('Got exit signal, shutting down'); - await server.close(); - exit(1); - }); - - await server.create(); - - server.onNewDevice.listen((final device) { - if (!devices.map((final d) => d.pushToken).contains(device.pushToken)) { - devices.add(device); - devicesFile - ..createSync(recursive: true) - ..writeAsString(json.encode(devices.map((final d) => d.toJson()).toList())); - } - }); - - server.onNewNotification.listen((final notification) async { - for (final device in devices) { - if (notification.pushTokenHash == sha512.convert(utf8.encode(device.pushToken)).toString()) { - final request = await HttpClient().postUrl(Uri.parse(device.pushToken)) - ..followRedirects = false - ..persistentConnection = true - ..add(utf8.encode(json.encode(notification.toPushNotificationData()))); - - final response = await request.close(); - if (response.statusCode > 299) { - print('Failed to send notification'); - } - } - } - }); - - print('Listening on *:8080'); -} - -void watchSignals(final Function(ProcessSignal signal) callback) { - for (final signal in [ - ProcessSignal.sighup, - ProcessSignal.sigint, - ProcessSignal.sigterm, - ProcessSignal.sigusr1, - ProcessSignal.sigusr2, - ]) { - signal.watch().listen(callback); - } -} diff --git a/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart b/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart deleted file mode 100644 index 64053b9c..00000000 --- a/packages/nextcloud_push_proxy/lib/nextcloud_push_proxy.dart +++ /dev/null @@ -1,163 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:shelf/shelf.dart'; -import 'package:shelf/shelf_io.dart'; -import 'package:shelf_router/shelf_router.dart'; - -/// Implements the listening part of a Nextcloud push proxy -class NextcloudPushProxy { - HttpServer? _server; - - late StreamController _onNewDeviceController; - late StreamController _onNewNotificationController; - - Stream? _onNewDeviceStream; - Stream? _onNewNotificationStream; - - /// Listens for new devices - Stream get onNewDevice { - if (_onNewDeviceStream == null) { - throw Exception('Server not created'); - } - return _onNewDeviceStream!; - } - - /// Listens for new notifications - Stream get onNewNotification { - if (_onNewNotificationStream == null) { - throw Exception('Server not created'); - } - return _onNewNotificationStream!; - } - - late final _router = Router() - ..post('/devices', _devicesHandler) - ..post('/notifications', _notificationsHandler) - ..get('/health', (final _) async => Response.ok('')); - - Future _devicesHandler(final Request request) async { - final data = Uri(query: await request.readAsString()).queryParameters; - _onNewDeviceController.add( - PushProxyDevice( - pushToken: data['pushToken']!, - deviceIdentifier: data['deviceIdentifier']!, - deviceIdentifierSignature: data['deviceIdentifierSignature']!, - userPublicKey: data['userPublicKey']!, - ), - ); - return Response.ok(''); - } - - Future _notificationsHandler(final Request request) async { - final data = Uri(query: await request.readAsString()).queryParameters; - for (final notification in data.values) { - final notificationData = json.decode(notification) as Map; - _onNewNotificationController.add( - PushProxyNotification( - deviceIdentifier: notificationData['deviceIdentifier']! as String, - pushTokenHash: notificationData['pushTokenHash']! as String, - subject: notificationData['subject']! as String, - signature: notificationData['signature']! as String, - priority: notificationData['priority']! as String, - type: notificationData['type']! as String, - ), - ); - } - return Response.ok(''); - } - - /// Creates a server listening on the [port] - Future create({ - final bool logging = true, - final int port = 8080, - }) async { - if (_server != null) { - throw Exception('Server already created'); - } - - _onNewDeviceController = StreamController(); - _onNewNotificationController = StreamController(); - _onNewDeviceStream = _onNewDeviceController.stream.asBroadcastStream(); - _onNewNotificationStream = _onNewNotificationController.stream.asBroadcastStream(); - - var handler = Cascade().add(_router.call).handler; - if (logging) { - handler = logRequests().addHandler(handler); - } - final server = await serve( - handler, - InternetAddress.anyIPv4, - port, - ); - server.autoCompress = true; - - _server = server; - } - - /// Closes the server - Future close() async { - if (_server != null) { - await _server!.close(); - _server = null; - await _onNewDeviceController.close(); - await _onNewNotificationController.close(); - } - } -} - -class PushProxyDevice { - PushProxyDevice({ - required this.pushToken, - required this.deviceIdentifier, - required this.deviceIdentifierSignature, - required this.userPublicKey, - }); - - factory PushProxyDevice.fromJson(final Map data) => PushProxyDevice( - pushToken: data['pushToken'] as String, - deviceIdentifier: data['deviceIdentifier'] as String, - deviceIdentifierSignature: data['deviceIdentifierSignature'] as String, - userPublicKey: data['userPublicKey'] as String, - ); - - Map toJson() => { - 'pushToken': pushToken, - 'deviceIdentifier': deviceIdentifier, - 'deviceIdentifierSignature': deviceIdentifierSignature, - 'userPublicKey': userPublicKey, - }; - - final String pushToken; - final String deviceIdentifier; - final String deviceIdentifierSignature; - final String userPublicKey; -} - -class PushProxyNotification { - PushProxyNotification({ - required this.deviceIdentifier, - required this.pushTokenHash, - required this.subject, - required this.signature, - required this.priority, - required this.type, - }); - - final String deviceIdentifier; - final String pushTokenHash; - final String subject; - final String signature; - final String priority; - final String type; - - Map toPushNotificationData() => { - 'subject': subject, - 'signature': signature, - 'priority': priority, - 'type': type, - }; -} diff --git a/packages/nextcloud_push_proxy/mono_pkg.yaml b/packages/nextcloud_push_proxy/mono_pkg.yaml deleted file mode 100644 index 60bc3bfd..00000000 --- a/packages/nextcloud_push_proxy/mono_pkg.yaml +++ /dev/null @@ -1,7 +0,0 @@ -sdk: - - stable - -stages: - - all: - - analyze: --fatal-infos . - - format: --output=none --set-exit-if-changed --line-length 120 . diff --git a/packages/nextcloud_push_proxy/pubspec.yaml b/packages/nextcloud_push_proxy/pubspec.yaml deleted file mode 100644 index fd8700a2..00000000 --- a/packages/nextcloud_push_proxy/pubspec.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: nextcloud_push_proxy -version: 1.0.0 - -environment: - sdk: '>=2.19.0 <3.0.0' - -dependencies: - crypto: ^3.0.2 - shelf: ^1.3.1 - shelf_router: ^1.1.3 - -dev_dependencies: - nit_picking: - git: - url: https://github.com/stack11/dart_nit_picking - ref: 0b2ee0d diff --git a/specs/notifications.json b/specs/notifications.json index 52b54be9..08b818fe 100644 --- a/specs/notifications.json +++ b/specs/notifications.json @@ -277,30 +277,7 @@ } } }, - "PushNotification": { - "type": "object", - "required": [ - "accountID", - "priority", - "type", - "subject" - ], - "properties": { - "accountID": { - "type": "string" - }, - "priority": { - "type": "string" - }, - "type": { - "type": "string" - }, - "subject": { - "$ref": "#/components/schemas/PushNotificationDecryptedSubject" - } - } - }, - "PushNotificationDecryptedSubject": { + "NotificationDecryptedSubject": { "type": "object", "properties": { "nid": { diff --git a/tool/run-dev-instance.sh b/tool/run-dev-instance.sh index 6539bf6d..e5222a6e 100755 --- a/tool/run-dev-instance.sh +++ b/tool/run-dev-instance.sh @@ -20,10 +20,6 @@ fi echo "TEST_HOST=$ip TEST_USER=user1 TEST_PASSWORD=user1" > packages/neon/assets/.env -( - cd packages/nextcloud_push_proxy - fvm dart run bin/unified_push.dart ./tmp/devices.json -) & function cleanup() { rm packages/neon/assets/.env