Skip to content
Snippets Groups Projects
Commit 96eb2aa9 authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Set certificate on report request

parent a6aa22bd
No related branches found
No related tags found
3 merge requests!71Releasing v1.1.5 (214),!69Implemented filtering for banned/blocked users and reporting,!67v1.1.5 b(203)
......@@ -466,6 +466,9 @@ let package = Package(
.product(name: "ChatLayout", package: "ChatLayout"),
.product(name: "DifferenceKit", package: "DifferenceKit"),
.product(name: "ScrollViewController", package: "ScrollViewController"),
],
resources: [
.process("Resources"),
]
),
.testTarget(
......
......@@ -430,8 +430,9 @@ public final class SingleChatController: UIViewController {
drawer.dismiss(animated: true) { [weak self] in
guard let self = self else { return }
self.drawerCancellables.removeAll()
self.viewModel.proceeedWithReport(screenshot: self.takeAppScreenshot())
self.navigationController?.popViewController(animated: true)
self.viewModel.proceeedWithReport(screenshot: self.takeAppScreenshot()) {
self.navigationController?.popViewController(animated: true)
}
}
}.store(in: &drawerCancellables)
......@@ -447,18 +448,11 @@ public final class SingleChatController: UIViewController {
}
func takeAppScreenshot() -> UIImage {
let foregroundWindowScene: UIWindowScene? = UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.compactMap { $0 as? UIWindowScene }
.first
guard let foregroundWindowScene = foregroundWindowScene else {
fatalError("[takeAppScreenshot]: Unable to get foreground window scene")
}
guard let keyWindow = foregroundWindowScene.windows.first(where: \.isKeyWindow) else {
fatalError("[takeAppScreenshot]: Unable to get key window")
}
let keyWindow = getKeyWindow(foregroundWindowScene)
let rendererFormat = UIGraphicsImageRendererFormat()
rendererFormat.scale = foregroundWindowScene.screen.scale
......@@ -602,11 +596,15 @@ extension SingleChatController: KeyboardListenerDelegate {
}
func keyboardWillChangeFrame(info: KeyboardInfo) {
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
guard let scene = foregroundWindowScene else {
fatalError("[keyboardWillChangeFrame]: Couldn't get foregroundWindowScene")
}
let keyWindow = getKeyWindow(scene)
let keyboardFrame = keyWindow.convert(info.frameEnd, to: view)
guard !currentInterfaceActions.options.contains(.changingFrameSize),
collectionView.contentInsetAdjustmentBehavior != .never,
let keyboardFrame = keyWindow?.convert(info.frameEnd, to: view),
collectionView.convert(collectionView.bounds, to: keyWindow).maxY > info.frameEnd.minY else { return }
currentInterfaceActions.options.insert(.changingKeyboardFrame)
......@@ -766,3 +764,16 @@ extension SingleChatController: QLPreviewControllerDelegate {
fileURL = nil
}
}
let foregroundWindowScene: UIWindowScene? = UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.compactMap { $0 as? UIWindowScene }
.first
func getKeyWindow(_ scene: UIWindowScene) -> UIWindow {
guard let keyWindow = scene.windows.first(where: \.isKeyWindow) else {
fatalError("Unable to get key window")
}
return keyWindow
}
-----BEGIN CERTIFICATE-----
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
WuHZNZ2W6k8sb2qp0vBbj6TXfhs=
-----END CERTIFICATE-----
\ No newline at end of file
......@@ -7,6 +7,7 @@ import XXLogger
import XXModels
import Foundation
import Integration
import Defaults
import Permissions
import ToastFeature
import DifferenceKit
......@@ -23,12 +24,14 @@ enum SingleChatNavigationRoutes: Equatable {
case webview(String)
}
final class SingleChatViewModel {
final class SingleChatViewModel: NSObject {
@Dependency private var logger: XXLogger
@Dependency private var session: SessionType
@Dependency private var permissions: PermissionHandling
@Dependency private var toastController: ToastController
@KeyObject(.username, defaultValue: nil) var username: String?
var contact: Contact { contactSubject.value }
private var stagedReply: Reply?
private var cancellables = Set<AnyCancellable>()
......@@ -73,6 +76,7 @@ final class SingleChatViewModel {
init(_ contact: Contact) {
self.contactSubject = .init(contact)
super.init()
updateRecentState(contact)
......@@ -140,11 +144,11 @@ final class SingleChatViewModel {
guard let id = message.id else { return }
session.retryMessage(id)
}
func didNavigateSomewhere() {
navigationRoutes.send(.none)
}
@discardableResult
func didTest(permission: PermissionType) -> Bool {
switch permission {
......@@ -222,18 +226,6 @@ final class SingleChatViewModel {
return (contactTitle, message.text)
}
func proceeedWithReport(screenshot: UIImage) {
var contact = contact
contact.isBlocked = true
_ = try? session.dbManager.saveContact(contact)
let name = (contact.nickname ?? contact.username) ?? ""
toastController.enqueueToast(model: .init(
title: "Your report has been sent and \(name) is now blocked.",
leftImage: Asset.requestSentToaster.image
))
}
func showRoundFrom(_ roundURL: String?) {
if let urlString = roundURL, !urlString.isEmpty {
navigationRoutes.send(.webview(urlString))
......@@ -261,3 +253,117 @@ final class SingleChatViewModel {
sectionsRelay.value.count > 0 ? sectionsRelay.value[index].model : nil
}
}
extension SingleChatViewModel {
struct Report: Encodable {
struct ReportUser: Encodable {
var userId: String
var username: String
}
var sender: ReportUser
var recipient: ReportUser
var type: String
var screenshot: String
}
private func blockContact() {
var contact = contact
contact.isBlocked = true
_ = try? session.dbManager.saveContact(contact)
}
private func makeReportRequest(with screenshot: UIImage) -> URLRequest {
let url = URL(string: "https://3.74.237.181:11420/report")
let report = Report(
sender: .init(
userId: contact.id.base64EncodedString(),
username: contact.username!
),
recipient: .init(
userId: session.myId.base64EncodedString(),
username: username!
), type: "dm",
screenshot: screenshot.jpegData(compressionQuality: 0.1)!.base64EncodedString())
var request = try! URLRequest(url: url!, method: .post)
request.httpBody = try! JSONEncoder().encode(report)
return request
}
private func enqueueBlockedToast() {
let name = (contact.nickname ?? contact.username) ?? ""
toastController.enqueueToast(model: .init(
title: "Your report has been sent and \(name) is now blocked.",
leftImage: Asset.requestSentToaster.image
))
}
private func uploadReport(
_ request: URLRequest,
completion: @escaping (Result<Void, Error>) -> Void
) {
URLSession(configuration: .default, delegate: self, delegateQueue: nil)
.dataTask(with: request) { data, response, error in
if let error = error as? NSError {
completion(.failure(error))
return
}
if let data = data {
completion(.success(()))
}
}.resume()
}
func proceeedWithReport(screenshot: UIImage, completion: @escaping () -> Void) {
hudRelay.send(.on)
uploadReport(makeReportRequest(with: screenshot)) { [weak self] in
guard let self = self else { return }
switch $0 {
case .success:
DispatchQueue.main.async {
self.blockContact()
self.enqueueBlockedToast()
self.hudRelay.send(.none)
completion()
}
case .failure(let error):
DispatchQueue.main.async {
self.hudRelay.send(.error(.init(with: error)))
completion()
}
}
}
}
}
extension SingleChatViewModel: URLSessionDelegate {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
let serverTrust = challenge.protectionSpace.serverTrust
let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)
let policies = NSMutableArray()
policies.add(SecPolicyCreateSSL(true, challenge.protectionSpace.host as CFString))
SecTrustSetPolicies(serverTrust!, policies)
let remoteCertificateData: NSData = SecCertificateCopyData(certificate!)
let pathToCert = Bundle.module.path(forResource: "report_cert", ofType: "crt")
let localCertificate: NSData = NSData(contentsOfFile: pathToCert!)!
if (remoteCertificateData.isEqual(to: localCertificate as Data)) {
let credential: URLCredential = URLCredential(trust: serverTrust!)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment