Skip to content

Commit 76aaab8

Browse files
authored
chore: kickoff release
2 parents 39edc73 + 70a49c1 commit 76aaab8

File tree

19 files changed

+514
-120
lines changed

19 files changed

+514
-120
lines changed

Amplify/Categories/DataStore/Query/ModelKey.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ extension CodingKey where Self: ModelKey {
5656
return key.contains(value)
5757
}
5858

59+
// MARK: - not contains
60+
public func notContains(_ value: String) -> QueryPredicateOperation {
61+
return field(stringValue).notContains(value)
62+
}
63+
5964
// MARK: - eq
6065

6166
public func eq(_ value: Persistable?) -> QueryPredicateOperation {

Amplify/Categories/DataStore/Query/QueryField.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public protocol QueryFieldOperation {
3434
func beginsWith(_ value: String) -> QueryPredicateOperation
3535
func between(start: Persistable, end: Persistable) -> QueryPredicateOperation
3636
func contains(_ value: String) -> QueryPredicateOperation
37+
func notContains(_ value: String) -> QueryPredicateOperation
3738
func eq(_ value: Persistable?) -> QueryPredicateOperation
3839
func eq(_ value: EnumPersistable) -> QueryPredicateOperation
3940
func ge(_ value: Persistable) -> QueryPredicateOperation
@@ -84,6 +85,11 @@ public struct QueryField: QueryFieldOperation {
8485
return key.contains(value)
8586
}
8687

88+
// MARK: - not contains
89+
public func notContains(_ value: String) -> QueryPredicateOperation {
90+
return QueryPredicateOperation(field: name, operator: .notContains(value))
91+
}
92+
8793
// MARK: - eq
8894

8995
public func eq(_ value: Persistable?) -> QueryPredicateOperation {

Amplify/Categories/DataStore/Query/QueryOperator.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public enum QueryOperator {
1515
case greaterOrEqual(_ value: Persistable)
1616
case greaterThan(_ value: Persistable)
1717
case contains(_ value: String)
18+
case notContains(_ value: String)
1819
case between(start: Persistable, end: Persistable)
1920
case beginsWith(_ value: String)
2021

@@ -37,6 +38,10 @@ public enum QueryOperator {
3738
return targetString.contains(predicateString)
3839
}
3940
return false
41+
case .notContains(let predicateString):
42+
if let targetString = target as? String {
43+
return !targetString.contains(predicateString)
44+
}
4045
case .between(let start, let end):
4146
return PersistableHelper.isBetween(start, end, target)
4247
case .beginsWith(let predicateValue):

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Helpers/ConfigurationHelper.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ struct ConfigurationHelper {
9494
scopes: scopesArray,
9595
signInRedirectURI: signInRedirectURI,
9696
signOutRedirectURI: signOutRedirectURI)
97-
return HostedUIConfigurationData(clientId: appClientId, oauth: oauth, clientSecret: nil)
97+
var clientSecret: String?
98+
if case .string(let appClientSecret) = configuration?.value(at: "AppClientSecret") {
99+
clientSecret = appClientSecret
100+
}
101+
return HostedUIConfigurationData(clientId: appClientId, oauth: oauth, clientSecret: clientSecret)
98102
}
99103

100104
static func parseIdentityPoolData(_ config: JSONValue) -> IdentityPoolConfigurationData? {

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIRequestHelper.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct HostedUIRequestHelper {
116116
var urlRequest = URLRequest(url: url)
117117
urlRequest.httpMethod = "POST"
118118
urlRequest.httpBody = body.data(using: .utf8)
119+
urlRequest.addHeaders(using: configuration)
119120
return urlRequest
120121
}
121122

@@ -145,6 +146,7 @@ struct HostedUIRequestHelper {
145146
var urlRequest = URLRequest(url: url)
146147
urlRequest.httpMethod = "POST"
147148
urlRequest.httpBody = body.data(using: .utf8)
149+
urlRequest.addHeaders(using: configuration)
148150
return urlRequest
149151
}
150152

@@ -154,3 +156,14 @@ struct HostedUIRequestHelper {
154156
.replacingOccurrences(of: "=", with: "")
155157
}
156158
}
159+
160+
private extension URLRequest {
161+
mutating func addHeaders(using configuration: HostedUIConfigurationData) {
162+
guard let clientSecret = configuration.clientSecret,
163+
let value = "\(configuration.clientId):\(clientSecret)".data(using: .utf8) else {
164+
return
165+
}
166+
167+
setValue("Basic \(value.base64EncodedString())", forHTTPHeaderField: "Authorization")
168+
}
169+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Foundation
9+
10+
@testable import AWSCognitoAuthPlugin
11+
import Amplify
12+
import XCTest
13+
14+
class HostedUIRequestHelperTests: XCTestCase {
15+
private var configuration: HostedUIConfigurationData!
16+
private let result = HostedUIResult(
17+
code: "code",
18+
state: "state",
19+
codeVerifier: "codeVerifier",
20+
options: .init(
21+
scopes: [],
22+
providerInfo: .init(
23+
authProvider: nil,
24+
idpIdentifier: nil
25+
),
26+
presentationAnchor: nil,
27+
preferPrivateSession: false)
28+
)
29+
30+
override func setUp() {
31+
createConfiguration()
32+
}
33+
34+
override func tearDown() {
35+
configuration = nil
36+
}
37+
38+
private var encodedSecret: String? {
39+
guard let clientSecret = configuration.clientSecret,
40+
let value = "\(configuration.clientId):\(clientSecret)".data(using: .utf8) else {
41+
return nil
42+
}
43+
44+
return value.base64EncodedString()
45+
}
46+
47+
private func createConfiguration(clientSecret: String? = nil) {
48+
configuration = .init(
49+
clientId: "clientId",
50+
oauth: .init(
51+
domain: "domain",
52+
scopes: [],
53+
signInRedirectURI: "app://",
54+
signOutRedirectURI: "app://"
55+
),
56+
clientSecret: clientSecret
57+
)
58+
}
59+
60+
/// Given: A HostedUI configuration without a client secret
61+
/// When: HostedUIRequestHelper.createTokenRequest is invoked with said configuration
62+
/// Then: A request is generated that does not include an Authorization header
63+
func testCreateTokenRequest_withoutClientSecret_shouldNotAddAuthorizationHeader() throws {
64+
let request = try HostedUIRequestHelper.createTokenRequest(
65+
configuration: configuration,
66+
result: result
67+
)
68+
69+
XCTAssertNil(request.value(forHTTPHeaderField: "Authorization"))
70+
}
71+
72+
/// Given: A HostedUI configuration that defines a client secret
73+
/// When: HostedUIRequestHelper.createTokenRequest is invoked with said configuration
74+
/// Then: A request is generated that includes an Authorization header and its value has an encoded version of the secret
75+
func testCreateTokenRequest_withClientSecret_shouldEncodeSecretAndAddAuthorizationHeader() throws {
76+
createConfiguration(clientSecret: "clientSecret")
77+
let request = try HostedUIRequestHelper.createTokenRequest(
78+
configuration: configuration,
79+
result: result
80+
)
81+
82+
let header = try XCTUnwrap(request.value(forHTTPHeaderField: "Authorization"))
83+
let encodedSecret = try XCTUnwrap(encodedSecret)
84+
XCTAssertEqual("Basic \(encodedSecret)", header)
85+
}
86+
87+
/// Given: A HostedUI configuration without a client secret
88+
/// When: HostedUIRequestHelper.createRefreshTokenRequest is invoked with said configuration
89+
/// Then: A request is generated that does not include an Authorization header
90+
func testCreateRefreshTokenRequest_withoutClientSecret_shouldNotAddAuthorizationHeader() throws {
91+
let request = try HostedUIRequestHelper.createRefreshTokenRequest(
92+
refreshToken: "refreshToken",
93+
configuration: configuration
94+
)
95+
96+
XCTAssertNil(request.value(forHTTPHeaderField: "Authorization"))
97+
}
98+
99+
/// Given: A HostedUI configuration that defines a client secret
100+
/// When: HostedUIRequestHelper.createRefreshTokenRequest is invoked with said configuration
101+
/// Then: A request is generated that includes an Authorization header and its value has an encoded version of the secret
102+
func testCreateRefreshTokenRequest_withClientSecret_shouldEncodeSecretAndAddAuthorizationHeader() throws {
103+
createConfiguration(clientSecret: "clientSecret")
104+
let request = try HostedUIRequestHelper.createRefreshTokenRequest(
105+
refreshToken: "refreshToken",
106+
configuration: configuration
107+
)
108+
109+
let header = try XCTUnwrap(request.value(forHTTPHeaderField: "Authorization"))
110+
let encodedSecret = try XCTUnwrap(encodedSecret)
111+
XCTAssertEqual("Basic \(encodedSecret)", header)
112+
}
113+
}

AmplifyPlugins/Core/AWSPluginsCore/Model/Support/QueryPredicate+GraphQL.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ extension QueryOperator {
185185
return "between"
186186
case .beginsWith:
187187
return "beginsWith"
188+
case .notContains:
189+
return "notContains"
188190
}
189191
}
190192

@@ -208,6 +210,8 @@ extension QueryOperator {
208210
return [start.graphQLValue(), end.graphQLValue()]
209211
case .beginsWith(let value):
210212
return value
213+
case .notContains(let value):
214+
return value
211215
}
212216
}
213217
}

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/AWSDataStorePlugin+DataStoreBaseBehavior.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extension AWSDataStorePlugin: DataStoreBaseBehavior {
6868
storageEngine.save(model,
6969
modelSchema: modelSchema,
7070
condition: condition,
71-
eagerLoad: isEagerLoad,
71+
eagerLoad: configuration.isEagerLoad,
7272
completion: publishingCompletion)
7373
}
7474

@@ -218,7 +218,7 @@ extension AWSDataStorePlugin: DataStoreBaseBehavior {
218218
predicate: predicate,
219219
sort: sortInput,
220220
paginationInput: paginationInput,
221-
eagerLoad: isEagerLoad,
221+
eagerLoad: configuration.isEagerLoad,
222222
completion: completion)
223223
}
224224

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/AWSDataStorePlugin+DataStoreSubscribeBehavior.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ extension AWSDataStorePlugin: DataStoreSubscribeBehavior {
4646
sortInput: sortInput?.asSortDescriptors(),
4747
storageEngine: storageEngine,
4848
dataStorePublisher: dataStorePublisher,
49-
dataStoreConfiguration: dataStoreConfiguration,
49+
dataStoreConfiguration: configuration.pluginConfiguration,
5050
dispatchedModelSyncedEvent: dispatchedModelSyncedEvent,
5151
dataStoreStatePublisher: dataStoreStateSubject.eraseToAnyPublisher())
5252
return taskRunner.sequence

0 commit comments

Comments
 (0)