Skip to content

Commit

Permalink
Updated export functions (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeldavidw authored Jul 6, 2024
1 parent e90b640 commit 45c1e74
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 45 deletions.
6 changes: 3 additions & 3 deletions Chronos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0;
MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.joeldavidw.ChronosDevDebug;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -709,7 +709,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0;
MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.joeldavidw.ChronosDevRelease;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -812,7 +812,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0;
MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.joeldavidw.Chronos;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct EncryptedExportConfirmPasswordView: View {
.presentationDragIndicator(Visibility.hidden)
.onDisappear {
exportNav.showSheet = false
exportService.cleanupTemporaryDirectory()
}
} else {
VStack {
Expand Down
3 changes: 3 additions & 0 deletions Chronos/App/Tabs/Settings/Export/ExportSelectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ struct ExportSelectionView: View {
if let fileurl = exportService.exportToUnencryptedJson() {
ActivityView(fileUrl: fileurl)
.presentationDetents([.medium, .large])
.onDisappear {
exportService.cleanupTemporaryDirectory()
}
} else {
VStack {
Image(systemName: "xmark.circle")
Expand Down
100 changes: 58 additions & 42 deletions Chronos/Services/ExportService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,87 +16,91 @@ public class ExportService {
calendar: Calendar(identifier: .gregorian)
)

func exportToUnencryptedJson() -> URL? {
private func getExportVault() -> ExportVault? {
let context = ModelContext(swiftDataService.getModelContainer())
let vault = vaultService.getVault(context: context)

let exportVault = ExportVault()
guard let vault = vaultService.getVault(context: context) else {
logger.error("Vault missing")
return nil
}

var tokens: [Token] = []

for encToken in vault!.encryptedTokens! {
for encToken in vault.encryptedTokens ?? [] {
guard let token = cryptoService.decryptToken(encryptedToken: encToken) else {
logger.error("Unable to decode token")
continue
}
tokens.append(token)
}

let exportVault = ExportVault()
exportVault.tokens = tokens
return exportVault
}

let url = FileManager.default.temporaryDirectory
.appendingPathComponent("Chronos_" + Date().formatted(verbatimStyle))
.appendingPathExtension("json")
private func createUniqueDir() -> URL? {
let uniqueDir = FileManager.default.temporaryDirectory
.appendingPathComponent("export", isDirectory: true)
.appendingPathComponent(UUID().uuidString, isDirectory: true)

do {
try FileManager.default.createDirectory(at: uniqueDir, withIntermediateDirectories: true)
} catch {
logger.error("Unable to create temporary directory: \(error.localizedDescription)")
return nil
}
return uniqueDir
}

private func writeJSON(to url: URL, from exportVault: ExportVault) -> Bool {
guard let jsonData = try? JSONEncoder().encode(exportVault) else {
logger.error("Unable to encode exportVault")
return nil
return false
}

do {
try jsonData.write(to: url)
return true
} catch {
logger.error("Unable to write json file: \(error.localizedDescription)")
return nil
return false
}

return url
}

func exportToEncryptedZip(password: String) -> URL? {
let context = ModelContext(swiftDataService.getModelContainer())
let vault = vaultService.getVault(context: context)

let exportVault = ExportVault()

var tokens: [Token] = []

for encToken in vault!.encryptedTokens! {
guard let token = cryptoService.decryptToken(encryptedToken: encToken) else {
logger.error("Unable to decode token")
continue
}
tokens.append(token)
func exportToUnencryptedJson() -> URL? {
guard let exportVault = getExportVault(), let uniqueDir = createUniqueDir() else {
return nil
}

exportVault.tokens = tokens

let randomDir = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
let url = uniqueDir.appendingPathComponent("Chronos_" + Date().formatted(verbatimStyle))
.appendingPathExtension("json")

try? FileManager.default.createDirectory(at: randomDir, withIntermediateDirectories: true)
if writeJSON(to: url, from: exportVault) {
return url
}

let jsonUrl = randomDir.appendingPathComponent("Chronos_" + Date().formatted(verbatimStyle))
.appendingPathExtension("json")
return nil
}

guard let jsonData = try? JSONEncoder().encode(exportVault) else {
logger.error("Unable to encode exportVault")
func exportToEncryptedZip(password: String) -> URL? {
guard let exportVault = getExportVault(), let uniqueDir = createUniqueDir() else {
return nil
}

do {
try jsonData.write(to: jsonUrl)
} catch {
logger.error("Unable to write json file: \(error.localizedDescription)")
let jsonUrl = uniqueDir.appendingPathComponent("Chronos_" + Date().formatted(verbatimStyle))
.appendingPathExtension("json")

if !writeJSON(to: jsonUrl, from: exportVault) {
return nil
}

let zipUrl = FileManager.default.temporaryDirectory
.appendingPathComponent("Chronos_Encrypted_" + Date().formatted(verbatimStyle))
.appendingPathComponent("export", isDirectory: true)
.appendingPathComponent("Chronos_" + Date().formatted(verbatimStyle))
.appendingPathExtension("zip")

let success = SSZipArchive.createZipFile(
atPath: zipUrl.path(),
withContentsOfDirectory: randomDir.path(),
atPath: zipUrl.path,
withContentsOfDirectory: uniqueDir.path,
keepParentDirectory: false,
compressionLevel: 0,
password: password,
Expand All @@ -107,6 +111,18 @@ public class ExportService {
return zipUrl
}

logger.error("Failed to create zip file")
return nil
}

func cleanupTemporaryDirectory() {
do {
let tempExportDirUrl = FileManager.default.temporaryDirectory
.appendingPathComponent("export", isDirectory: true)

try FileManager.default.removeItem(at: tempExportDirUrl)
} catch {
logger.error("Unable to delete temporary directory: \(error.localizedDescription)")
}
}
}

0 comments on commit 45c1e74

Please sign in to comment.