Skip to content

Commit 954d02e

Browse files
authored
fix(datastore-v1): Multi auth rule for read subscription (#3029)
Subscriptions for `read` auth rule were not processed inside Datastore. `read` auth rule can subscribe to onCreateX, onUpdateX and onDeleteX.
1 parent bcb6d5a commit 954d02e

File tree

6 files changed

+84
-19
lines changed

6 files changed

+84
-19
lines changed

Amplify/Categories/DataStore/Model/Internal/Schema/AuthRule.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@ public struct AuthRule {
6868
self.operations = operations
6969
}
7070
}
71+
72+
extension AuthRule: Hashable {
73+
74+
}

AmplifyPlugins/Core/AWSPluginsCore/Auth/AWSAuthModeStrategy.swift

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public protocol AuthModeStrategy: AnyObject {
4343

4444
func authTypesFor(schema: ModelSchema,
4545
operation: ModelOperation) -> AWSAuthorizationTypeIterator
46+
47+
func authTypesFor(schema: ModelSchema,
48+
operations: [ModelOperation]) -> AWSAuthorizationTypeIterator
4649
}
4750

4851
/// AuthorizationType iterator with an extra `count` property used
@@ -90,10 +93,17 @@ public class AWSDefaultAuthModeStrategy: AuthModeStrategy {
9093
public weak var authDelegate: AuthModeStrategyDelegate?
9194
required public init() {}
9295

93-
public func authTypesFor(schema: ModelSchema,
94-
operation: ModelOperation) -> AWSAuthorizationTypeIterator {
95-
return AWSAuthorizationTypeIterator(withValues: [])
96-
}
96+
public func authTypesFor(
97+
schema: ModelSchema,
98+
operation: ModelOperation) -> AWSAuthorizationTypeIterator {
99+
return AWSAuthorizationTypeIterator(withValues: [])
100+
}
101+
102+
public func authTypesFor(
103+
schema: ModelSchema,
104+
operations: [ModelOperation]) -> AWSAuthorizationTypeIterator {
105+
return AWSAuthorizationTypeIterator(withValues: [])
106+
}
97107
}
98108

99109
// MARK: - AWSMultiAuthModeStrategy
@@ -187,19 +197,40 @@ public class AWSMultiAuthModeStrategy: AuthModeStrategy {
187197
/// - schema: model schema
188198
/// - operation: model operation
189199
/// - Returns: an iterator for the applicable auth rules
190-
public func authTypesFor(schema: ModelSchema,
191-
operation: ModelOperation) -> AWSAuthorizationTypeIterator {
192-
var applicableAuthRules = schema.authRules
193-
.filter(modelOperation: operation)
194-
.sorted(by: AWSMultiAuthModeStrategy.comparator)
200+
public func authTypesFor(
201+
schema: ModelSchema,
202+
operation: ModelOperation
203+
) -> AWSAuthorizationTypeIterator {
204+
205+
return authTypesFor(schema: schema, operations: [operation])
206+
}
207+
208+
/// Returns the union of authorization types for the provided schema for the given list of operations
209+
/// - Parameters:
210+
/// - schema: model schema
211+
/// - operations: model operations
212+
/// - Returns: an iterator for the applicable auth rules
213+
public func authTypesFor(
214+
schema: ModelSchema,
215+
operations: [ModelOperation]
216+
) -> AWSAuthorizationTypeIterator {
217+
218+
var applicableAuthRules = Set<AuthRule>()
219+
220+
for operation in operations {
221+
let rules = schema.authRules.filter(modelOperation: operation)
222+
applicableAuthRules = applicableAuthRules.union(Set(rules))
223+
}
224+
225+
var sortedRules = applicableAuthRules.sorted(by: AWSMultiAuthModeStrategy.comparator)
195226

196227
// if there isn't a user signed in, returns only public or custom rules
197228
if let authDelegate = authDelegate, !authDelegate.isUserLoggedIn() {
198-
applicableAuthRules = applicableAuthRules.filter { rule in
229+
sortedRules = sortedRules.filter { rule in
199230
return rule.allow == .public || rule.allow == .custom
200231
}
201232
}
202-
let applicableAuthTypes = applicableAuthRules.map {
233+
let applicableAuthTypes = sortedRules.map {
203234
AWSMultiAuthModeStrategy.authTypeFor(authRule: $0)
204235
}
205236
return AWSAuthorizationTypeIterator(withValues: applicableAuthTypes)

AmplifyPlugins/Core/AWSPluginsCoreTests/Auth/AuthModeStrategyTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,29 @@ class AuthModeStrategyTests: XCTestCase {
123123
XCTAssertEqual(authTypesIterator.next(), .awsIAM)
124124
}
125125

126+
// Given: multi-auth strategy and a model schema without auth provider
127+
// When: auth types are requested with multiple operation
128+
// Then: default values based on the auth strategy should be returned
129+
func testMultiAuthShouldReturnDefaultAuthTypesForMultipleOperation() {
130+
let authMode = AWSMultiAuthModeStrategy()
131+
var authTypesIterator = authMode.authTypesFor(schema: ModelNoProvider.schema, operations: [.read, .create])
132+
XCTAssertEqual(authTypesIterator.count, 2)
133+
XCTAssertEqual(authTypesIterator.next(), .amazonCognitoUserPools)
134+
XCTAssertEqual(authTypesIterator.next(), .apiKey)
135+
}
136+
137+
// Given: multi-auth strategy and a model schema with auth provider
138+
// When: auth types are requested with multiple operation
139+
// Then: auth rule for public access should be returned
140+
func testMultiAuthReturnDefaultAuthTypesForMultipleOperationWithProvider() {
141+
let authMode = AWSMultiAuthModeStrategy()
142+
let delegate = UnauthenticatedUserDelegate()
143+
authMode.authDelegate = delegate
144+
var authTypesIterator = authMode.authTypesFor(schema: ModelNoProvider.schema, operations: [.read, .create])
145+
XCTAssertEqual(authTypesIterator.count, 1)
146+
XCTAssertEqual(authTypesIterator.next(), .apiKey)
147+
}
148+
126149
}
127150

128151
// MARK: - Test models

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/SubscriptionSync/IncomingAsyncSubscriptionEventPublisher.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,11 @@ final class IncomingAsyncSubscriptionEventPublisher: AmplifyCancellable {
7373

7474
// onCreate operation
7575
let onCreateValueListener = onCreateValueListenerHandler(event:)
76-
let onCreateAuthTypeProvider = authModeStrategy.authTypesFor(schema: modelSchema,
77-
operation: .create)
76+
let onCreateAuthTypeProvider = authModeStrategy.authTypesFor(
77+
schema: modelSchema,
78+
operations: [.create, .read]
79+
)
80+
7881
self.onCreateValueListener = onCreateValueListener
7982
self.onCreateOperation = RetryableGraphQLSubscriptionOperation(
8083
requestFactory: IncomingAsyncSubscriptionEventPublisher.apiRequestFactoryFor(
@@ -94,8 +97,10 @@ final class IncomingAsyncSubscriptionEventPublisher: AmplifyCancellable {
9497

9598
// onUpdate operation
9699
let onUpdateValueListener = onUpdateValueListenerHandler(event:)
97-
let onUpdateAuthTypeProvider = authModeStrategy.authTypesFor(schema: modelSchema,
98-
operation: .update)
100+
let onUpdateAuthTypeProvider = authModeStrategy.authTypesFor(
101+
schema: modelSchema,
102+
operations: [.update, .read]
103+
)
99104
self.onUpdateValueListener = onUpdateValueListener
100105
self.onUpdateOperation = RetryableGraphQLSubscriptionOperation(
101106
requestFactory: IncomingAsyncSubscriptionEventPublisher.apiRequestFactoryFor(
@@ -115,8 +120,10 @@ final class IncomingAsyncSubscriptionEventPublisher: AmplifyCancellable {
115120

116121
// onDelete operation
117122
let onDeleteValueListener = onDeleteValueListenerHandler(event:)
118-
let onDeleteAuthTypeProvider = authModeStrategy.authTypesFor(schema: modelSchema,
119-
operation: .delete)
123+
let onDeleteAuthTypeProvider = authModeStrategy.authTypesFor(
124+
schema: modelSchema,
125+
operations: [.delete, .read]
126+
)
120127
self.onDeleteValueListener = onDeleteValueListener
121128
self.onDeleteOperation = RetryableGraphQLSubscriptionOperation(
122129
requestFactory: IncomingAsyncSubscriptionEventPublisher.apiRequestFactoryFor(

AmplifyPlugins/DataStore/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,4 @@ SPEC CHECKSUMS:
128128

129129
PODFILE CHECKSUM: 0bab7193bebdf470839514f327440893b0d26090
130130

131-
COCOAPODS: 1.11.3
131+
COCOAPODS: 1.12.0

Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ SPEC CHECKSUMS:
5151

5252
PODFILE CHECKSUM: 5e20e56b8ef40444b018a3736b7b726ff9772f00
5353

54-
COCOAPODS: 1.11.3
54+
COCOAPODS: 1.12.0

0 commit comments

Comments
 (0)