Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.27.12 #1873

Merged
merged 17 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGES.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worthwhile mentioning in here that support for the Authenticated Media endpoint has been added?

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
Loading