-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
260: Changes related to the next Meilisearch release (v0.26.0) r=bidoubiwa a=meili-bot Related to this issue: meilisearch/integration-guides#181 This PR: - gathers the changes related to the next Meilisearch release (v0.26.0) so that this package is ready when the official release is out. - should pass the tests against the [latest pre-release of Meilisearch](https://github.com/meilisearch/meilisearch/releases). - might eventually contain test failures until the Meilisearch v0.26.0 is out.⚠️ This PR should NOT be merged until the next release of Meilisearch (v0.26.0) is out. _This PR is auto-generated for the [pre-release week](https://github.com/meilisearch/integration-guides/blob/master/guides/pre-release-week.md) purpose._ Co-authored-by: meili-bot <74670311+meili-bot@users.noreply.github.com> Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com> Co-authored-by: Bruno Casali <brunoocasali@gmail.com> Co-authored-by: meili-bors[bot] <89034592+meili-bors[bot]@users.noreply.github.com>
- Loading branch information
Showing
20 changed files
with
785 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import Foundation | ||
|
||
public struct SearchRules: Codable, Equatable { | ||
var index: String = "*" | ||
var filter: String? | ||
|
||
init(_ index: String, filter: String? = nil) { | ||
self.index = index | ||
self.filter = filter | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
|
||
if let indexes = try? container.decode([String].self), !indexes.isEmpty, let index = indexes.first { | ||
self.index = index | ||
|
||
return | ||
} | ||
|
||
if let dict = try? container.decode([String: [String: String]].self) { | ||
if let key = dict.keys.first { | ||
self.index = key | ||
|
||
if let value = dict[key] { | ||
self.filter = value["filter"] | ||
} | ||
} | ||
|
||
return | ||
} | ||
|
||
throw DecodingError.typeMismatch( | ||
SearchRules.self, | ||
DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SearchRules") | ||
) | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
var dict = [String: [String: String?]]() | ||
|
||
guard let filter = self.filter, !filter.isEmpty else { | ||
try container.encode([index]) | ||
|
||
return | ||
} | ||
|
||
dict[index] = ["filter": self.filter] | ||
|
||
try container.encode(dict) | ||
} | ||
|
||
public func getFilterDict() -> [String: String?]? { | ||
guard let filter = self.filter, !filter.isEmpty else { | ||
return [String: String?]() | ||
} | ||
|
||
return ["filter": self.filter] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import Foundation | ||
|
||
public struct SearchRulesGroup: Codable, Equatable { | ||
var members: [SearchRules] = [] | ||
|
||
init(_ members: [SearchRules]) { | ||
precondition(members.count > 0, "One or more SearchRules() are required") | ||
|
||
self.members = members | ||
} | ||
|
||
init(_ searchRules: SearchRules) { | ||
self.init([searchRules]) | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
|
||
if let list = try? container.decode([String].self) { | ||
for item in list { | ||
self.members.append(SearchRules(item)) | ||
} | ||
|
||
return | ||
} | ||
|
||
if let list = try? container.decode([String: [String: String]].self) { | ||
for (index, value) in list { | ||
self.members.append(SearchRules(index, filter: value["filter"] ?? nil)) | ||
} | ||
|
||
return | ||
} | ||
|
||
throw DecodingError.typeMismatch( | ||
SearchRules.self, | ||
DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SearchRules") | ||
) | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
var dict = [String: [String: String?]]() | ||
|
||
for rule in self.members { | ||
if let filter = rule.getFilterDict() { | ||
dict[rule.index] = filter | ||
} | ||
} | ||
|
||
try container.encode(dict) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Foundation | ||
import JWTKit | ||
|
||
internal struct TokenPayload: JWTPayload, Equatable { | ||
/// The "exp" (expiration time) claim identifies the expiration time on | ||
/// or after which the JWT MUST NOT be accepted for processing. | ||
var exp: ExpirationClaim? | ||
|
||
/// The "searchRules" claim contains the rules to be enforced at | ||
/// search time for all or specific accessible indexes for the signing API Key. | ||
var searchRules: SearchRulesClaim | ||
|
||
/// The "apiKeyPrefix" claim contains the first 8 characters of the | ||
/// Meilisearch API key that generates and signs the Tenant Token. | ||
var apiKeyPrefix: ApiKeyPrefixClaim? | ||
|
||
func verify(using signer: JWTSigner) throws { | ||
try self.exp?.verifyNotExpired() | ||
try self.apiKeyPrefix?.verify() | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
Sources/MeiliSearch/TenantTokenClaims/ApiKeyPrefixClaim.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Foundation | ||
import JWTKit | ||
|
||
internal struct ApiKeyPrefixClaim: JWTClaim, Equatable { | ||
/// See `JWTClaim`. | ||
public var value: String | ||
|
||
/// See `JWTClaim`. | ||
public init(value: String) { | ||
self.value = value | ||
} | ||
|
||
// Checks if the apiKey sent as value is valid to sign the JWT. | ||
public func verify() throws { | ||
if self.value.isEmpty || self.value.count < 8 { | ||
throw JWTError.claimVerificationFailure(name: "apiKeyPrefix", reason: "invalid key sent") | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
Sources/MeiliSearch/TenantTokenClaims/SearchRulesClaim.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Foundation | ||
import JWTKit | ||
|
||
internal struct SearchRulesClaim: JWTClaim, Equatable { | ||
public var value: SearchRulesGroup | ||
|
||
public init(value: SearchRulesGroup) { | ||
self.value = value | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import Foundation | ||
import JWTKit | ||
|
||
/// Struct used to generate tenant tokens | ||
internal struct TenantTokens { | ||
/** | ||
Generate tenant tokens with a particular set of options, and use this token to authorize search requests. | ||
- [docs.meilisearch.com](https://docs.meilisearch.com/learn/security/tenant_tokens.html) | ||
*/ | ||
static func generateTenantToken( | ||
_ searchRules: SearchRulesGroup, | ||
apiKey: String = "", | ||
expiresAt: Date? = nil, | ||
_ completion: @escaping (Result<String, Swift.Error>) -> Void | ||
) { | ||
let signers = JWTSigners() | ||
signers.use(.hs256(key: apiKey)) | ||
|
||
do { | ||
let payload = try createTokenPayload( | ||
searchRules: searchRules, | ||
apiKey: apiKey, | ||
expiresAt: expiresAt | ||
) | ||
|
||
let jwt = try signers.sign(payload) | ||
|
||
completion(.success(jwt)) | ||
} catch let error { | ||
completion(.failure(error)) | ||
} | ||
} | ||
|
||
private static func createTokenPayload( | ||
searchRules: SearchRulesGroup, | ||
apiKey: String, | ||
expiresAt: Date? | ||
) throws -> TokenPayload { | ||
guard !apiKey.isEmpty else { throw JWTError.signatureVerifictionFailed } | ||
|
||
var payload = TokenPayload( | ||
searchRules: SearchRulesClaim(value: searchRules), | ||
apiKeyPrefix: ApiKeyPrefixClaim(value: String(apiKey.prefix(8))) | ||
) | ||
|
||
if let exp = expiresAt { | ||
payload.exp = ExpirationClaim(value: exp) | ||
} | ||
|
||
try payload.verify(using: .hs256(key: apiKey)) | ||
|
||
return payload | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.