mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Merge pull request #105 from loki-project/security
Fix Profile Picture Issues
This commit is contained in:
commit
251a93e529
|
@ -5,7 +5,7 @@
|
||||||
<key>BuildDetails</key>
|
<key>BuildDetails</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CarthageVersion</key>
|
<key>CarthageVersion</key>
|
||||||
<string>0.33.0</string>
|
<string>0.34.0</string>
|
||||||
<key>OSXVersion</key>
|
<key>OSXVersion</key>
|
||||||
<string>10.15.3</string>
|
<string>10.15.3</string>
|
||||||
<key>WebRTCCommit</key>
|
<key>WebRTCCommit</key>
|
||||||
|
|
|
@ -155,7 +155,7 @@ final class DisplayNameVC : UIViewController {
|
||||||
return showError(title: NSLocalizedString("Please pick a shorter display name", comment: ""))
|
return showError(title: NSLocalizedString("Please pick a shorter display name", comment: ""))
|
||||||
}
|
}
|
||||||
TSAccountManager.sharedInstance().didRegister()
|
TSAccountManager.sharedInstance().didRegister()
|
||||||
OWSProfileManager.shared().updateLocalProfileName(displayName, avatarImage: nil, success: { }, failure: { }) // Try to save the user name but ignore the result
|
OWSProfileManager.shared().updateLocalProfileName(displayName, avatarImage: nil, success: { }, failure: { _ in }) // Try to save the user name but ignore the result
|
||||||
let homeVC = HomeVC()
|
let homeVC = HomeVC()
|
||||||
navigationController!.setViewControllers([ homeVC ], animated: true)
|
navigationController!.setViewControllers([ homeVC ], animated: true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,10 +274,16 @@ final class SettingsVC : UIViewController, AvatarViewHelperDelegate {
|
||||||
self.displayNameToBeUploaded = nil
|
self.displayNameToBeUploaded = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, failure: {
|
}, failure: { error in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
modalActivityIndicator.dismiss {
|
modalActivityIndicator.dismiss {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Couldn't Update Profile", comment: ""), message: NSLocalizedString("Please check your internet connection and try again", comment: ""), preferredStyle: .alert)
|
var isMaxFileSizeExceeded = false
|
||||||
|
if let error = error as? LokiDotNetAPI.LokiDotNetAPIError {
|
||||||
|
isMaxFileSizeExceeded = (error == .maxFileSizeExceeded)
|
||||||
|
}
|
||||||
|
let title = isMaxFileSizeExceeded ? "Maximum File Size Exceeded" : NSLocalizedString("Couldn't Update Profile", comment: "")
|
||||||
|
let message = isMaxFileSizeExceeded ? "Please select a smaller photo and try again" : NSLocalizedString("Please check your internet connection and try again", comment: "")
|
||||||
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self?.present(alert, animated: true, completion: nil)
|
self?.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,7 +419,7 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
|
||||||
}];
|
}];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
failure:^{
|
failure:^(NSError *error) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[modalActivityIndicator dismissWithCompletion:^{
|
[modalActivityIndicator dismissWithCompletion:^{
|
||||||
[OWSAlerts showErrorAlertWithMessage:NSLocalizedString(
|
[OWSAlerts showErrorAlertWithMessage:NSLocalizedString(
|
||||||
|
|
|
@ -170,7 +170,7 @@ public class OnboardingProfileViewController: OnboardingBaseViewController {
|
||||||
self.onboardingController.profileDidComplete(fromView: self)
|
self.onboardingController.profileDidComplete(fromView: self)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, failure: {
|
}, failure: { _ in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
modal.dismiss(completion: {
|
modal.dismiss(completion: {
|
||||||
OWSAlerts.showErrorAlert(message: NSLocalizedString("PROFILE_VIEW_ERROR_UPDATE_FAILED",
|
OWSAlerts.showErrorAlert(message: NSLocalizedString("PROFILE_VIEW_ERROR_UPDATE_FAILED",
|
||||||
|
|
|
@ -336,7 +336,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
|
||||||
success:^{
|
success:^{
|
||||||
resolve(@(1));
|
resolve(@(1));
|
||||||
}
|
}
|
||||||
failure:^{
|
failure:^(NSError *error) {
|
||||||
// Ignore errors related to local profile.
|
// Ignore errors related to local profile.
|
||||||
resolve(@(1));
|
resolve(@(1));
|
||||||
}];
|
}];
|
||||||
|
|
|
@ -50,7 +50,7 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter;
|
||||||
- (void)updateLocalProfileName:(nullable NSString *)profileName
|
- (void)updateLocalProfileName:(nullable NSString *)profileName
|
||||||
avatarImage:(nullable UIImage *)avatarImage
|
avatarImage:(nullable UIImage *)avatarImage
|
||||||
success:(void (^)(void))successBlock
|
success:(void (^)(void))successBlock
|
||||||
failure:(void (^)(void))failureBlock;
|
failure:(void (^)(NSError *))failureBlock;
|
||||||
|
|
||||||
- (BOOL)isProfileNameTooLong:(nullable NSString *)profileName;
|
- (BOOL)isProfileNameTooLong:(nullable NSString *)profileName;
|
||||||
|
|
||||||
|
|
|
@ -229,13 +229,13 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||||
- (void)updateLocalProfileName:(nullable NSString *)profileName
|
- (void)updateLocalProfileName:(nullable NSString *)profileName
|
||||||
avatarImage:(nullable UIImage *)avatarImage
|
avatarImage:(nullable UIImage *)avatarImage
|
||||||
success:(void (^)(void))successBlockParameter
|
success:(void (^)(void))successBlockParameter
|
||||||
failure:(void (^)(void))failureBlockParameter
|
failure:(void (^)(NSError *))failureBlockParameter
|
||||||
{
|
{
|
||||||
OWSAssertDebug(successBlockParameter);
|
OWSAssertDebug(successBlockParameter);
|
||||||
OWSAssertDebug(failureBlockParameter);
|
OWSAssertDebug(failureBlockParameter);
|
||||||
|
|
||||||
// Ensure that the success and failure blocks are called on the main thread.
|
// Ensure that the success and failure blocks are called on the main thread.
|
||||||
void (^failureBlock)(void) = ^{
|
void (^failureBlock)(NSError *) = ^(NSError *error) {
|
||||||
OWSLogError(@"Updating service with profile failed.");
|
OWSLogError(@"Updating service with profile failed.");
|
||||||
|
|
||||||
// We use a "self-only" contact sync to indicate to desktop
|
// We use a "self-only" contact sync to indicate to desktop
|
||||||
|
@ -247,7 +247,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||||
[[self.syncManager syncLocalContact] retainUntilComplete];
|
[[self.syncManager syncLocalContact] retainUntilComplete];
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
failureBlockParameter();
|
failureBlockParameter(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
void (^successBlock)(void) = ^{
|
void (^successBlock)(void) = ^{
|
||||||
|
@ -288,7 +288,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
failure:^(NSError *error) {
|
failure:^(NSError *error) {
|
||||||
failureBlock();
|
failureBlock(error);
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -319,11 +319,11 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||||
tryToUpdateService(avatarUrlPath, fileName);
|
tryToUpdateService(avatarUrlPath, fileName);
|
||||||
}
|
}
|
||||||
failure:^(NSError *error) {
|
failure:^(NSError *error) {
|
||||||
failureBlock();
|
failureBlock(error);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
failure:^(NSError *error) {
|
failure:^(NSError *error) {
|
||||||
failureBlock();
|
failureBlock(error);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
} else if (userProfile.avatarUrlPath) {
|
} else if (userProfile.avatarUrlPath) {
|
||||||
|
@ -333,7 +333,7 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
|
||||||
tryToUpdateService(nil, nil);
|
tryToUpdateService(nil, nil);
|
||||||
}
|
}
|
||||||
failure:^(NSError *error) {
|
failure:^(NSError *error) {
|
||||||
failureBlock();
|
failureBlock(error);
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
OWSLogVerbose(@"Updating local profile on service with no avatar.");
|
OWSLogVerbose(@"Updating local profile on service with no avatar.");
|
||||||
|
|
|
@ -100,10 +100,10 @@ public class LokiDotNetAPI : NSObject {
|
||||||
return seal.reject(error)
|
return seal.reject(error)
|
||||||
}
|
}
|
||||||
// Send the request
|
// Send the request
|
||||||
func parseResponse(_ response: Any) {
|
func parseResponse(_ responseObject: Any) {
|
||||||
// Parse the server ID & download URL
|
// Parse the server ID & download URL
|
||||||
guard let json = response as? JSON, let data = json["data"] as? JSON, let serverID = data["id"] as? UInt64, let downloadURL = data["url"] as? String else {
|
guard let json = responseObject as? JSON, let data = json["data"] as? JSON, let serverID = data["id"] as? UInt64, let downloadURL = data["url"] as? String else {
|
||||||
print("[Loki] Couldn't parse attachment from: \(response).")
|
print("[Loki] Couldn't parse attachment from: \(responseObject).")
|
||||||
return seal.reject(LokiDotNetAPIError.parsingFailed)
|
return seal.reject(LokiDotNetAPIError.parsingFailed)
|
||||||
}
|
}
|
||||||
// Update the attachment
|
// Update the attachment
|
||||||
|
|
|
@ -138,6 +138,9 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
|
||||||
// MARK: Profile Pictures (Public API)
|
// MARK: Profile Pictures (Public API)
|
||||||
public static func setProfilePicture(_ profilePicture: Data) -> Promise<String> {
|
public static func setProfilePicture(_ profilePicture: Data) -> Promise<String> {
|
||||||
return Promise<String>() { seal in
|
return Promise<String>() { seal in
|
||||||
|
guard profilePicture.count < maxFileSize else {
|
||||||
|
return seal.reject(LokiDotNetAPIError.maxFileSizeExceeded)
|
||||||
|
}
|
||||||
getAuthToken(for: server).done { token in
|
getAuthToken(for: server).done { token in
|
||||||
let url = "\(server)/users/me/avatar"
|
let url = "\(server)/users/me/avatar"
|
||||||
let parameters: JSON = [ "type" : attachmentType, "Content-Type" : "application/binary" ]
|
let parameters: JSON = [ "type" : attachmentType, "Content-Type" : "application/binary" ]
|
||||||
|
@ -150,24 +153,15 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
|
||||||
print("[Loki] Couldn't upload profile picture due to error: \(error).")
|
print("[Loki] Couldn't upload profile picture due to error: \(error).")
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
let task = AFURLSessionManager(sessionConfiguration: .default).uploadTask(withStreamedRequest: request as URLRequest, progress: nil, completionHandler: { response, responseObject, error in
|
let _ = LokiFileServerProxy(for: server).performLokiFileServerNSURLRequest(request as NSURLRequest).done { responseObject in
|
||||||
if let error = error {
|
|
||||||
print("[Loki] Couldn't upload profile picture due to error: \(error).")
|
|
||||||
return seal.reject(error)
|
|
||||||
}
|
|
||||||
let statusCode = (response as! HTTPURLResponse).statusCode
|
|
||||||
let isSuccessful = (200...299) ~= statusCode
|
|
||||||
guard isSuccessful else {
|
|
||||||
print("[Loki] Couldn't upload profile picture.")
|
|
||||||
return seal.reject(LokiDotNetAPIError.generic)
|
|
||||||
}
|
|
||||||
guard let json = responseObject as? JSON, let data = json["data"] as? JSON, let profilePicture = data["avatar_image"] as? JSON, let downloadURL = profilePicture["url"] as? String else {
|
guard let json = responseObject as? JSON, let data = json["data"] as? JSON, let profilePicture = data["avatar_image"] as? JSON, let downloadURL = profilePicture["url"] as? String else {
|
||||||
print("[Loki] Couldn't parse profile picture from: \(responseObject).")
|
print("[Loki] Couldn't parse profile picture from: \(responseObject).")
|
||||||
return seal.reject(LokiDotNetAPIError.parsingFailed)
|
return seal.reject(LokiDotNetAPIError.parsingFailed)
|
||||||
}
|
}
|
||||||
return seal.fulfill(downloadURL)
|
return seal.fulfill(downloadURL)
|
||||||
})
|
}.catch { error in
|
||||||
task.resume()
|
seal.reject(error)
|
||||||
|
}
|
||||||
}.catch { error in
|
}.catch { error in
|
||||||
print("[Loki] Couldn't upload profile picture due to error: \(error).")
|
print("[Loki] Couldn't upload profile picture due to error: \(error).")
|
||||||
seal.reject(error)
|
seal.reject(error)
|
||||||
|
|
|
@ -106,7 +106,7 @@ internal class LokiFileServerProxy : LokiHTTPClient {
|
||||||
print("[Loki] Received an invalid response.")
|
print("[Loki] Received an invalid response.")
|
||||||
throw Error.proxyResponseParsingFailed
|
throw Error.proxyResponseParsingFailed
|
||||||
}
|
}
|
||||||
let isSuccess = (200..<300).contains(statusCode)
|
let isSuccess = (200...299) ~= statusCode
|
||||||
guard isSuccess else { throw HTTPError.networkError(code: statusCode, response: nil, underlyingError: Error.fileServerHTTPError(code: statusCode, message: nil)) }
|
guard isSuccess else { throw HTTPError.networkError(code: statusCode, response: nil, underlyingError: Error.fileServerHTTPError(code: statusCode, message: nil)) }
|
||||||
let uncheckedJSONAsData = try DiffieHellman.decrypt(cipherText, using: symmetricKey)
|
let uncheckedJSONAsData = try DiffieHellman.decrypt(cipherText, using: symmetricKey)
|
||||||
if uncheckedJSONAsData.isEmpty { return () }
|
if uncheckedJSONAsData.isEmpty { return () }
|
||||||
|
|
Loading…
Reference in a new issue