Skip to content

Commit

Permalink
Merge branch 'release/0.27.12/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Jul 23, 2024
2 parents 8a7f6b3 + 4f9bdfc commit f2b4e6e
Show file tree
Hide file tree
Showing 23 changed files with 379 additions and 39 deletions.
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## Changes in 0.27.12 (2024-07-23)

🙌 Improvements

- Expose MXRroomPowerLevels Swift wrappers to Element ([#1869](https://github.com/matrix-org/matrix-ios-sdk/pull/1869))

🐛 Bugfixes

- Fix CallKit audio session late init in VoIP call. ([#1866](https://github.com/matrix-org/matrix-ios-sdk/pull/1866))


## Changes in 0.27.11 (2024-06-18)

No significant changes.
Expand Down
2 changes: 1 addition & 1 deletion MatrixSDK.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "MatrixSDK"
s.version = "0.27.11"
s.version = "0.27.12"
s.summary = "The iOS SDK to build apps compatible with Matrix (https://www.matrix.org)"

s.description = <<-DESC
Expand Down
24 changes: 24 additions & 0 deletions MatrixSDK/Categories/MXKeysQueryResponse+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,27 @@ extension MXKeysQueryResponse : MXSummable {
return keysQueryResponse as! Self
}
}


extension MXKeysQueryResponseRaw : MXSummable {

public static func +(lhs: MXKeysQueryResponseRaw, rhs: MXKeysQueryResponseRaw) -> Self {
let keysQueryResponse = MXKeysQueryResponseRaw()

// Casts to original objc NSDictionary are annoying
// but we want to reuse our implementation of NSDictionary.+
let deviceKeysMap = (lhs.deviceKeys as NSDictionary? ?? NSDictionary())
+ (rhs.deviceKeys as NSDictionary? ?? NSDictionary())
keysQueryResponse.deviceKeys = deviceKeysMap as? [String : Any]

let crossSigningKeys = (lhs.crossSigningKeys as NSDictionary? ?? NSDictionary())
+ (rhs.crossSigningKeys as NSDictionary? ?? NSDictionary())
keysQueryResponse.crossSigningKeys = crossSigningKeys as? [String: MXCrossSigningInfo]

let failures = (lhs.failures as NSDictionary? ?? NSDictionary())
+ (rhs.failures as NSDictionary? ?? NSDictionary())
keysQueryResponse.failures = failures as? [AnyHashable : Any]

return keysQueryResponse as! Self
}
}
71 changes: 71 additions & 0 deletions MatrixSDK/Categories/MXRestClient+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,75 @@ public extension MXRestClient {

return operation
}

/// Download users keys by chunks.
///
/// - Parameters:
/// - users: list of users to get keys for.
/// - token: sync token to pass in the query request, to help.
/// - chunkSize: max number of users to ask for in one CS API request.
/// - success: A block object called when the operation succeeds.
/// - failure: A block object called when the operation fails.
/// - Returns: a MXHTTPOperation instance.
func downloadKeysByChunkRaw(forUsers users: [String],
token: String?,
chunkSize: Int = 250,
success: @escaping (_ keysQueryResponse: MXKeysQueryResponseRaw) -> Void,
failure: @escaping (_ error: NSError?) -> Void) -> MXHTTPOperation {

// Do not chunk if not needed
if users.count <= chunkSize {
return self.downloadKeysRaw(forUsers: users, token: token) { response in
switch response {
case .success(let keysQueryResponse):
success(keysQueryResponse)
case .failure(let error):
failure(error as NSError)
}
}
}

MXLog.debug("[MXRestClient+Extensions] downloadKeysByChunk: \(users.count) users with chunkSize:\(chunkSize)")

// An arbitrary MXHTTPOperation. It will not cancel requests
// but it will avoid to call callbacks in case of a cancellation is requested
let operation = MXHTTPOperation()

let group = DispatchGroup()
var responses = [MXResponse<MXKeysQueryResponseRaw>]()
users.chunked(into: chunkSize).forEach { chunkedUsers in
group.enter()
self.downloadKeysRaw(forUsers: chunkedUsers, token: token) { response in
switch response {
case .success(let keysQueryResponse):
MXLog.debug("[MXRestClient+Extensions] downloadKeysByChunk: Got intermediate response. Got device keys for %@ users. Got cross-signing keys for %@ users \(String(describing: keysQueryResponse.deviceKeys.keys.count)) \(String(describing: keysQueryResponse.crossSigningKeys.count))")
case .failure(let error):
MXLog.debug("[MXRestClient+Extensions] downloadKeysByChunk: Got intermediate error. Error: \(error)")
}

responses.append(response)
group.leave()
}
}

group.notify(queue: self.completionQueue) {
MXLog.debug("[MXRestClient+Extensions] downloadKeysByChunk: Got all responses")

guard operation.isCancelled == false else {
MXLog.debug("[MXRestClient+Extensions] downloadKeysByChunk: Request was cancelled")
return
}

// Gather all responses in one
let response = responses.reduce(.success(MXKeysQueryResponseRaw()), +)
switch response {
case .success(let keysQueryResponse):
success(keysQueryResponse)
case .failure(let error):
failure(error as NSError)
}
}

return operation
}
}
4 changes: 2 additions & 2 deletions MatrixSDK/Contrib/Swift/JSONModels/MXRoomPowerLevels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extension MXRoomPowerLevels {
- parameter eventType: the type of event.
- returns: the required minimum power level.
*/
@nonobjc func minimumPowerLevelForSendingMessageEvent(_ eventType: MXEventType) -> Int {
@nonobjc public func minimumPowerLevelForSendingMessageEvent(_ eventType: MXEventType) -> Int {
return __minimumPowerLevelForSendingEvent(asMessage: eventType.identifier)
}

Expand All @@ -36,7 +36,7 @@ extension MXRoomPowerLevels {
- parameter eventType: the type of event.
- returns: the required minimum power level.
*/
@nonobjc func minimumPowerLevelForSendingStateEvent(_ eventType: MXEventType) -> Int {
@nonobjc public func minimumPowerLevelForSendingStateEvent(_ eventType: MXEventType) -> Int {
return __minimumPowerLevelForSendingEvent(asStateEvent: eventType.identifier)
}

Expand Down
4 changes: 4 additions & 0 deletions MatrixSDK/Contrib/Swift/MXRestClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1848,6 +1848,10 @@ public extension MXRestClient {
return __downloadKeys(forUsers: userIds, token: token, success: currySuccess(completion), failure: curryFailure(completion))
}

@nonobjc @discardableResult func downloadKeysRaw(forUsers userIds: [String], token: String? = nil, completion: @escaping (_ response: MXResponse<MXKeysQueryResponseRaw>) -> Void) -> MXHTTPOperation {
return __downloadKeysRaw(forUsers: userIds, token: token, success: currySuccess(completion), failure: curryFailure(completion))
}


/**
Claim one-time keys.
Expand Down
6 changes: 3 additions & 3 deletions MatrixSDK/Crypto/CryptoMachine/MXCryptoRequests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import MatrixSDKCrypto
/// to the native REST API client
struct MXCryptoRequests {
private let restClient: MXRestClient
private let queryScheduler: MXKeysQueryScheduler<MXKeysQueryResponse>
private let queryScheduler: MXKeysQueryScheduler<MXKeysQueryResponseRaw>

init(restClient: MXRestClient) {
self.restClient = restClient
self.queryScheduler = .init { users in
try await performCallbackRequest { completion in
_ = restClient.downloadKeysByChunk(
_ = restClient.downloadKeysByChunkRaw(
forUsers: users,
token: nil,
success: {
Expand Down Expand Up @@ -96,7 +96,7 @@ struct MXCryptoRequests {
}
}

func queryKeys(users: [String]) async throws -> MXKeysQueryResponse {
func queryKeys(users: [String]) async throws -> MXKeysQueryResponseRaw {
try await queryScheduler.query(users: Set(users))
}

Expand Down
19 changes: 19 additions & 0 deletions MatrixSDK/JSONModels/MXJSONModels.h
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,25 @@ FOUNDATION_EXPORT NSString *const kMXPushRuleScopeStringGlobal;

@end

@interface MXKeysQueryResponseRaw : MXJSONModel

/**
The device keys per devices per users.
*/
@property (nonatomic) NSDictionary<NSString *, id> *deviceKeys;

/**
Cross-signing keys per users.
*/
@property (nonatomic) NSDictionary<NSString*, MXCrossSigningInfo*> *crossSigningKeys;

/**
The failures sorted by homeservers.
*/
@property (nonatomic) NSDictionary *failures;

@end

/**
`MXKeysClaimResponse` represents the response to /keys/claim request made by
[MXRestClient claimOneTimeKeysForUsersDevices].
Expand Down
95 changes: 95 additions & 0 deletions MatrixSDK/JSONModels/MXJSONModels.m
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,101 @@ - (NSDictionary *)JSONDictionary

@end

@interface MXKeysQueryResponseRaw ()
@end

@implementation MXKeysQueryResponseRaw

+ (id)modelFromJSON:(NSDictionary *)JSONDictionary
{
MXKeysQueryResponseRaw *keysQueryResponse = [[MXKeysQueryResponseRaw alloc] init];
if (keysQueryResponse)
{

if ([JSONDictionary[@"device_keys"] isKindOfClass:NSDictionary.class])
{
keysQueryResponse.deviceKeys = JSONDictionary[@"device_keys"];
}

MXJSONModelSetDictionary(keysQueryResponse.failures, JSONDictionary[@"failures"]);

// Extract cross-signing keys
NSMutableDictionary *crossSigningKeys = [NSMutableDictionary dictionary];

// Gather all of them by type by user
NSDictionary<NSString*, NSDictionary<NSString*, MXCrossSigningKey*>*> *allKeys =
@{
MXCrossSigningKeyType.master: [self extractUserKeysFromJSON:JSONDictionary[@"master_keys"]] ?: @{},
MXCrossSigningKeyType.selfSigning: [self extractUserKeysFromJSON:JSONDictionary[@"self_signing_keys"]] ?: @{},
MXCrossSigningKeyType.userSigning: [self extractUserKeysFromJSON:JSONDictionary[@"user_signing_keys"]] ?: @{},
};

// Package them into a `userId -> MXCrossSigningInfo` dictionary
for (NSString *keyType in allKeys)
{
NSDictionary<NSString*, MXCrossSigningKey*> *keys = allKeys[keyType];
for (NSString *userId in keys)
{
MXCrossSigningInfo *crossSigningInfo = crossSigningKeys[userId];
if (!crossSigningInfo)
{
crossSigningInfo = [[MXCrossSigningInfo alloc] initWithUserId:userId];
crossSigningKeys[userId] = crossSigningInfo;
}

[crossSigningInfo addCrossSigningKey:keys[userId] type:keyType];
}
}

keysQueryResponse.crossSigningKeys = crossSigningKeys;
}

return keysQueryResponse;
}

+ (NSDictionary<NSString*, MXCrossSigningKey*>*)extractUserKeysFromJSON:(NSDictionary *)keysJSONDictionary
{
NSMutableDictionary<NSString*, MXCrossSigningKey*> *keys = [NSMutableDictionary dictionary];
for (NSString *userId in keysJSONDictionary)
{
MXCrossSigningKey *key;
MXJSONModelSetMXJSONModel(key, MXCrossSigningKey, keysJSONDictionary[userId]);
if (key)
{
keys[userId] = key;
}
}

if (!keys.count)
{
keys = nil;
}

return keys;
}

- (NSDictionary *)JSONDictionary
{

NSMutableDictionary *master = [[NSMutableDictionary alloc] init];
NSMutableDictionary *selfSigning = [[NSMutableDictionary alloc] init];
NSMutableDictionary *userSigning = [[NSMutableDictionary alloc] init];
for (NSString *userId in self.crossSigningKeys) {
master[userId] = self.crossSigningKeys[userId].masterKeys.JSONDictionary.copy;
selfSigning[userId] = self.crossSigningKeys[userId].selfSignedKeys.JSONDictionary.copy;
userSigning[userId] = self.crossSigningKeys[userId].userSignedKeys.JSONDictionary.copy;
}

return @{
@"device_keys": self.deviceKeys.copy ?: @{},
@"failures": self.failures.copy ?: @{},
@"master_keys": master.copy ?: @{},
@"self_signing_keys": selfSigning.copy ?: @{},
@"user_signing_keys": userSigning.copy ?: @{}
};
}

@end
@interface MXKeysClaimResponse ()

/**
Expand Down
6 changes: 6 additions & 0 deletions MatrixSDK/JSONModels/MXMatrixVersions.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct MXMatrixClientServerAPIVersionStruct
__unsafe_unretained NSString * const v1_1;
__unsafe_unretained NSString * const v1_2;
__unsafe_unretained NSString * const v1_3;
__unsafe_unretained NSString * const v1_11;
};
extern const struct MXMatrixClientServerAPIVersionStruct MXMatrixClientServerAPIVersion;

Expand Down Expand Up @@ -123,6 +124,11 @@ extern const struct MXMatrixVersionsFeatureStruct MXMatrixVersionsFeature;
*/
@property (nonatomic, readonly) BOOL supportsRedactionWithRelationsUnstable;

/**
Indicate if the server supports MSC3916
*/
@property (nonatomic, readonly) BOOL supportsAuthenticatedMedia;

@end

NS_ASSUME_NONNULL_END
9 changes: 8 additions & 1 deletion MatrixSDK/JSONModels/MXMatrixVersions.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
.r0_6_1 = @"r0.6.1",
.v1_1 = @"v1.1",
.v1_2 = @"v1.2",
.v1_3 = @"v1.3"
.v1_3 = @"v1.3",
// missing versions not considered
.v1_11 = @"v1.11"
};

const struct MXMatrixVersionsFeatureStruct MXMatrixVersionsFeature = {
Expand Down Expand Up @@ -145,6 +147,11 @@ - (BOOL)supportsRedactionWithRelationsUnstable
return [self serverSupportsFeature:kJSONKeyMSC3912Unstable];
}

- (BOOL)supportsAuthenticatedMedia
{
return [self serverSupportsVersion:MXMatrixClientServerAPIVersion.v1_11];
}

#pragma mark - Private

- (BOOL)serverSupportsVersion:(NSString *)version
Expand Down
5 changes: 5 additions & 0 deletions MatrixSDK/MXEnumConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ FOUNDATION_EXPORT NSString *const kMXContentUriScheme;
*/
FOUNDATION_EXPORT NSString *const kMXContentPrefixPath;

/**
A constant representing the default prefix of the Matrix authenticated content repository path.
*/
FOUNDATION_EXPORT NSString *const kMXAuthenticatedContentPrefixPath;

/**
A constant representing the URI path for as-yet unspecified of the AntiVirus Client-Server HTTP API.
*/
Expand Down
1 change: 1 addition & 0 deletions MatrixSDK/MXEnumConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
NSString *const kMXContentUriScheme = @"mxc://";
NSString *const kMXContentPrefixPath = @"_matrix/media/r0";
NSString *const kMXAuthenticatedContentPrefixPath = @"_matrix/client/v1/media";

/**
Prefix used in path of antivirus server API requests.
Expand Down
Loading

0 comments on commit f2b4e6e

Please sign in to comment.