Skip to content

Commit c0a7384

Browse files
authored
APNS server in Vapor (home-assistant#2024)
## Summary Implements the push send and rate limit information in Swift using Vapor. ## Any other notes This will allow us to get off Firebase, which gives a few immediate benefits: - We can send PushKit notifications for complications, widgets, and location updates. - We remove the last SDK that uses network connectivity to third parties.
1 parent 738a537 commit c0a7384

File tree

82 files changed

+1885
-66
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1885
-66
lines changed

.github/workflows/push_ci.yml

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Push CI
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'Sources/PushServer/**'
7+
push:
8+
branches:
9+
- master
10+
paths:
11+
- 'Sources/PushServer/**'
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: fwal/setup-swift@v1
18+
with:
19+
swift-version: "5.5"
20+
- uses: actions/checkout@v2
21+
- name: Run Tests
22+
run: swift test
23+
working-directory: Sources/PushServer

.github/workflows/push_deploy.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Push Deploy
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- master
8+
paths:
9+
- 'Sources/PushServer/**'
10+
11+
env:
12+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
13+
14+
jobs:
15+
deploy:
16+
name: Deploy app
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v2
20+
- uses: superfly/[email protected]
21+
with:
22+
args: "deploy Sources/PushServer -c app.fly.toml"
23+
- uses: superfly/[email protected]
24+
with:
25+
args: "deploy Sources/PushServer -c redis.fly.toml"

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
.DS_Store
44
.AppleDouble
55
.LSOverride
6+
.swiftpm
7+
.build
68

79
# Icon must end with two \r
810
Icon
@@ -82,3 +84,4 @@ Configuration/HomeAssistant.overrides.xcconfig
8284
*.profraw
8385
Brewfile.lock.json
8486
vendor/bundle
87+
.env.development

.swiftlint.yml

+1
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ excluded:
5353
- Tests
5454
- Pods
5555
- vendor
56+
- "*/**/.build"

HomeAssistant.xcodeproj/project.pbxproj

+31-14
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@
180180
116D3A3D2724D83300EF5D21 /* OnboardingAuth.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 116D3A3C2724D83300EF5D21 /* OnboardingAuth.test.swift */; };
181181
116D3A442724EFFB00EF5D21 /* OnboardingAuthTokenExchange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 116D3A422724EDF100EF5D21 /* OnboardingAuthTokenExchange.swift */; };
182182
116D3A4627252C3200EF5D21 /* OnboardingAuthStepConfig.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 116D3A4527252C3200EF5D21 /* OnboardingAuthStepConfig.test.swift */; };
183+
116E2AAD27765D0100B330F2 /* SharedPush in Frameworks */ = {isa = PBXBuildFile; productRef = 116E2AAC27765D0100B330F2 /* SharedPush */; };
184+
116E2AAF27765D0600B330F2 /* SharedPush in Frameworks */ = {isa = PBXBuildFile; productRef = 116E2AAE27765D0600B330F2 /* SharedPush */; };
183185
1171506B24DFCDE60065E874 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1171506A24DFCDE60065E874 /* WidgetKit.framework */; };
184186
1171506D24DFCDE60065E874 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1171506C24DFCDE60065E874 /* SwiftUI.framework */; };
185187
1171507024DFCDE60065E874 /* Widgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1171506F24DFCDE60065E874 /* Widgets.swift */; };
@@ -287,9 +289,6 @@
287289
11A71C8D24A593A800D9565F /* ZoneManagerCollector.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11A71C8C24A593A800D9565F /* ZoneManagerCollector.test.swift */; };
288290
11A71C8F24A5946B00D9565F /* FakeCLLocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11A71C8E24A5946B00D9565F /* FakeCLLocationManager.swift */; };
289291
11A71C9124A598AB00D9565F /* ZoneManagerProcessor.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11A71C9024A598AB00D9565F /* ZoneManagerProcessor.test.swift */; };
290-
11AA9977266B0CEC00B829E1 /* NotificationParserLegacy.test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11AA9976266B0CEC00B829E1 /* NotificationParserLegacy.test.swift */; };
291-
11AA9A8A266B140A00B829E1 /* NotificationParserLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11AA9A89266B140A00B829E1 /* NotificationParserLegacy.swift */; };
292-
11AA9A8B266B140A00B829E1 /* NotificationParserLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11AA9A89266B140A00B829E1 /* NotificationParserLegacy.swift */; };
293292
11ADB13E24C29E6900FF5EB2 /* ZoneManagerRegionFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11ADB13D24C29E6900FF5EB2 /* ZoneManagerRegionFilter.swift */; };
294293
11ADF940267D34B10040A7E3 /* NotificationsCommandManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11ADF93E267D34AD0040A7E3 /* NotificationsCommandManager.swift */; };
295294
11ADF941267D34B20040A7E3 /* NotificationsCommandManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11ADF93E267D34AD0040A7E3 /* NotificationsCommandManager.swift */; };
@@ -394,7 +393,6 @@
394393
11CFD78227364F450082D557 /* Identifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11CFD78027364F450082D557 /* Identifier.swift */; };
395394
11CFD784273662DF0082D557 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11CFD783273662DF0082D557 /* Server.swift */; };
396395
11CFD785273662DF0082D557 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11CFD783273662DF0082D557 /* Server.swift */; };
397-
11D7059F271B7CF400B2F7EB /* notification_test_cases.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 11D7059E271B7CF300B2F7EB /* notification_test_cases.bundle */; };
398396
11D826F124E39F2E005B8A86 /* CoreNFC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11D826F024E39F2D005B8A86 /* CoreNFC.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
399397
11DA6B4B27137A60008ADFAF /* InputAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11DA6B4A27137A60008ADFAF /* InputAccessoryView.swift */; };
400398
11DA6B4D2713900E008ADFAF /* OnboardingPermissionWorkflowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11DA6B4C2713900E008ADFAF /* OnboardingPermissionWorkflowController.swift */; };
@@ -1273,6 +1271,7 @@
12731271
116D3A3C2724D83300EF5D21 /* OnboardingAuth.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingAuth.test.swift; sourceTree = "<group>"; };
12741272
116D3A422724EDF100EF5D21 /* OnboardingAuthTokenExchange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingAuthTokenExchange.swift; sourceTree = "<group>"; };
12751273
116D3A4527252C3200EF5D21 /* OnboardingAuthStepConfig.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingAuthStepConfig.test.swift; sourceTree = "<group>"; };
1274+
116E2AAB27765CF300B330F2 /* SharedPush */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SharedPush; path = Sources/PushServer/SharedPush; sourceTree = "<group>"; };
12761275
1171506924DFCDE60065E874 /* HomeAssistant-Extensions-Widgets.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "HomeAssistant-Extensions-Widgets.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
12771276
1171506A24DFCDE60065E874 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
12781277
1171506C24DFCDE60065E874 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
@@ -1362,8 +1361,6 @@
13621361
11A71C8C24A593A800D9565F /* ZoneManagerCollector.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoneManagerCollector.test.swift; sourceTree = "<group>"; };
13631362
11A71C8E24A5946B00D9565F /* FakeCLLocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeCLLocationManager.swift; sourceTree = "<group>"; };
13641363
11A71C9024A598AB00D9565F /* ZoneManagerProcessor.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoneManagerProcessor.test.swift; sourceTree = "<group>"; };
1365-
11AA9976266B0CEC00B829E1 /* NotificationParserLegacy.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationParserLegacy.test.swift; sourceTree = "<group>"; };
1366-
11AA9A89266B140A00B829E1 /* NotificationParserLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationParserLegacy.swift; sourceTree = "<group>"; };
13671364
11ADB13D24C29E6900FF5EB2 /* ZoneManagerRegionFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoneManagerRegionFilter.swift; sourceTree = "<group>"; };
13681365
11ADF93E267D34AD0040A7E3 /* NotificationsCommandManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsCommandManager.swift; sourceTree = "<group>"; };
13691366
11AF1EC62528FB2300AAE364 /* Extension-ios.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Extension-ios.entitlements"; sourceTree = "<group>"; };
@@ -1426,7 +1423,6 @@
14261423
11CD94BA24B2D2C100BA801D /* WebhookResponseUnhandled.test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebhookResponseUnhandled.test.swift; sourceTree = "<group>"; };
14271424
11CFD78027364F450082D557 /* Identifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identifier.swift; sourceTree = "<group>"; };
14281425
11CFD783273662DF0082D557 /* Server.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Server.swift; sourceTree = "<group>"; };
1429-
11D7059E271B7CF300B2F7EB /* notification_test_cases.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = notification_test_cases.bundle; sourceTree = "<group>"; };
14301426
11D826F024E39F2D005B8A86 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = System/Library/Frameworks/CoreNFC.framework; sourceTree = SDKROOT; };
14311427
11DA6B4A27137A60008ADFAF /* InputAccessoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputAccessoryView.swift; sourceTree = "<group>"; };
14321428
11DA6B4C2713900E008ADFAF /* OnboardingPermissionWorkflowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPermissionWorkflowController.swift; sourceTree = "<group>"; };
@@ -2076,6 +2072,7 @@
20762072
buildActionMask = 2147483647;
20772073
files = (
20782074
CF58E969432B36CC112701AC /* Pods_watchOS_Shared_watchOS.framework in Frameworks */,
2075+
116E2AAF27765D0600B330F2 /* SharedPush in Frameworks */,
20792076
);
20802077
runOnlyForDeploymentPostprocessing = 0;
20812078
};
@@ -2106,6 +2103,7 @@
21062103
D0EEF301214D8EAB00D1D360 /* CoreLocation.framework in Frameworks */,
21072104
D0B25BD7213312AE00678C2C /* UserNotifications.framework in Frameworks */,
21082105
539AA1653F4BCDB61FE7C696 /* Pods_iOS_Shared_iOS.framework in Frameworks */,
2106+
116E2AAD27765D0100B330F2 /* SharedPush in Frameworks */,
21092107
);
21102108
runOnlyForDeploymentPostprocessing = 0;
21112109
};
@@ -2206,6 +2204,14 @@
22062204
path = Networking;
22072205
sourceTree = "<group>";
22082206
};
2207+
115327BC2773BF290082ED72 /* Packages */ = {
2208+
isa = PBXGroup;
2209+
children = (
2210+
116E2AAB27765CF300B330F2 /* SharedPush */,
2211+
);
2212+
name = Packages;
2213+
sourceTree = "<group>";
2214+
};
22092215
115560DF27010D6700A8F818 /* Common */ = {
22102216
isa = PBXGroup;
22112217
children = (
@@ -2414,7 +2420,6 @@
24142420
isa = PBXGroup;
24152421
children = (
24162422
11A3BD2C26192210005237E6 /* LocalPushManager.swift */,
2417-
11AA9A89266B140A00B829E1 /* NotificationParserLegacy.swift */,
24182423
11B7DBFB266BE7540090BD3B /* LocalPushEvent.swift */,
24192424
116C0C2E267EB90F00A992E4 /* UserDefaultsValueSync.swift */,
24202425
11F20BC6274C60FF00DFB163 /* PushProviderConfiguration.swift */,
@@ -3069,6 +3074,7 @@
30693074
B657A8DD1CA646EB00121384 = {
30703075
isa = PBXGroup;
30713076
children = (
3077+
115327BC2773BF290082ED72 /* Packages */,
30723078
9C4E5E20229D97FA0044C8EC /* Configuration */,
30733079
1115018C2528411200DCFA94 /* Sources */,
30743080
111501A82528414000DCFA94 /* Tests */,
@@ -3474,7 +3480,6 @@
34743480
D03D894320E0BC1800D4F28D /* Shared */ = {
34753481
isa = PBXGroup;
34763482
children = (
3477-
11D7059E271B7CF300B2F7EB /* notification_test_cases.bundle */,
34783483
118511C024B25BDC00D18F60 /* Webhook */,
34793484
11AF4D28249D88B2006C74C0 /* Sensors */,
34803485
D0A6367120DB7D1100E5C49B /* ClientEventTests.swift */,
@@ -3492,7 +3497,6 @@
34923497
110AA57A25B38C02005061A0 /* ServerAlerter.test.swift */,
34933498
11267D0825BBA9FE00F28E5C /* Updater.test.swift */,
34943499
1133F5E425F1DBEA00AD776F /* CLLocation+Sanitize.test.swift */,
3495-
11AA9976266B0CEC00B829E1 /* NotificationParserLegacy.test.swift */,
34963500
11B7DC0D266C3EEB0090BD3B /* LocalPushEvent.test.swift */,
34973501
11B7DC1E266C5D3E0090BD3B /* LocalPushManager.test.swift */,
34983502
11764A6B26817FC3007D47F3 /* UserDefaultsValueSync.test.swift */,
@@ -3924,6 +3928,9 @@
39243928
111711FB25B29B24003C149E /* PBXTargetDependency */,
39253929
);
39263930
name = "Shared-watchOS";
3931+
packageProductDependencies = (
3932+
116E2AAE27765D0600B330F2 /* SharedPush */,
3933+
);
39273934
productName = "Shared-watchOS";
39283935
productReference = B67CE82422200D420034C1D0 /* Shared.framework */;
39293936
productType = "com.apple.product-type.framework";
@@ -4005,6 +4012,9 @@
40054012
11A31C93252128B900D50A78 /* PBXTargetDependency */,
40064013
);
40074014
name = "Shared-iOS";
4015+
packageProductDependencies = (
4016+
116E2AAC27765D0100B330F2 /* SharedPush */,
4017+
);
40084018
productName = Shared;
40094019
productReference = D03D891720E0A85200D4F28D /* Shared.framework */;
40104020
productType = "com.apple.product-type.framework";
@@ -4617,7 +4627,6 @@
46174627
isa = PBXResourcesBuildPhase;
46184628
buildActionMask = 2147483647;
46194629
files = (
4620-
11D7059F271B7CF400B2F7EB /* notification_test_cases.bundle in Resources */,
46214630
C10D762EFE08D347D0538339 /* Pods-iOS-Shared-iOS-Tests-Shared-metadata.plist in Resources */,
46224631
);
46234632
runOnlyForDeploymentPostprocessing = 0;
@@ -5405,7 +5414,6 @@
54055414
11AF4D13249C7E08006C74C0 /* ActivitySensor.swift in Sources */,
54065415
11E5CF8224BBCE1B009AC30F /* ProcessInfo+BackgroundTask.swift in Sources */,
54075416
11AF4D1D249C8AA0006C74C0 /* BatterySensor.swift in Sources */,
5408-
11AA9A8B266B140A00B829E1 /* NotificationParserLegacy.swift in Sources */,
54095417
B67CE8A922200F220034C1D0 /* SettingsStore.swift in Sources */,
54105418
11AF4D26249D1931006C74C0 /* LastUpdateSensor.swift in Sources */,
54115419
11EE9B4A24C5116F00404AF8 /* ModelManager.swift in Sources */,
@@ -5597,7 +5605,6 @@
55975605
11CB98CA249E62E700B05222 /* Version+HA.swift in Sources */,
55985606
11EE9B4924C5116F00404AF8 /* ModelManager.swift in Sources */,
55995607
D0C3DC142134CD4E000C9EE1 /* CMMotion+StringExtensions.swift in Sources */,
5600-
11AA9A8A266B140A00B829E1 /* NotificationParserLegacy.swift in Sources */,
56015608
B6872E662226842100C475D1 /* MobileAppRegistrationResponse.swift in Sources */,
56025609
D0EEF305214DD0D400D1D360 /* UIColor+HA.swift in Sources */,
56035610
B613936924F728F8002B8C5D /* InputOutputDeviceSensor.swift in Sources */,
@@ -5724,7 +5731,6 @@
57245731
files = (
57255732
11B38EDF275BE29F00205C7B /* ConnectionInfo.test.swift in Sources */,
57265733
11883CC524C12C8A0036A6C6 /* CLLocation+Extensions.test.swift in Sources */,
5727-
11AA9977266B0CEC00B829E1 /* NotificationParserLegacy.test.swift in Sources */,
57285734
1109F82424A25A41002590F2 /* SensorContainer.test.swift in Sources */,
57295735
119385A7249E9F930097F497 /* StorageSensor.test.swift in Sources */,
57305736
11CD94B724B2CC7400BA801D /* WebhookResponseLocation.test.swift in Sources */,
@@ -7288,6 +7294,17 @@
72887294
defaultConfigurationName = Release;
72897295
};
72907296
/* End XCConfigurationList section */
7297+
7298+
/* Begin XCSwiftPackageProductDependency section */
7299+
116E2AAC27765D0100B330F2 /* SharedPush */ = {
7300+
isa = XCSwiftPackageProductDependency;
7301+
productName = SharedPush;
7302+
};
7303+
116E2AAE27765D0600B330F2 /* SharedPush */ = {
7304+
isa = XCSwiftPackageProductDependency;
7305+
productName = SharedPush;
7306+
};
7307+
/* End XCSwiftPackageProductDependency section */
72917308
};
72927309
rootObject = B657A8DE1CA646EB00121384 /* Project object */;
72937310
}

Sources/PushServer/.dockerignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.build/
2+
.swiftpm/

Sources/PushServer/.env.sample

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
LOG_LEVEL=
2+
APNS_TOPIC=
3+
APNS_KEY_CONTENTS=
4+
APNS_KEY_IDENTIFIER=
5+
APNS_KEY_TEAM_IDENTIFIER=
6+
REDIS_SERVER=
7+
REDIS_PASSWORD=

0 commit comments

Comments
 (0)