// // DatabaseAnswer.swift // Privado // // Created by Juraldinio on 11/13/19. // Copyright © 2019 Omicronmedia. All rights reserved. // import Foundation import CoreData final class DatabaseAnswer { private enum Constants { static let maxLogRecords = 1000 static let encryptionKey = "DatabaseEncryptionKey" } // MARK: - Methods private static var encryptionKey: Data { let bytesCount = 64 let keychain = KeychainSwift() if let data = keychain.getData(Constants.encryptionKey) { return data } if let data = Data(randomOfLength: bytesCount) { keychain.set(data, forKey: Constants.encryptionKey) return data } if let data = UUID().uuidString.data(using: .utf8) { keychain.set(data, forKey: Constants.encryptionKey) return data } return Data(repeating: 8, count: bytesCount) } private static var commonUrl: URL? { #if os(iOS) let domainPath: FileManager.SearchPathDirectory = .documentDirectory #else let domainPath: FileManager.SearchPathDirectory = .applicationSupportDirectory #endif let urls = FileManager.default.urls(for: domainPath, in: .userDomainMask) guard let url = urls.first else { return nil } let directory = url.appendingPathComponent(Environment.bundleName) try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: false, attributes: nil) let file = directory.appendingPathComponent("psett.sql") if !FileManager.default.fileExists(atPath: file.path) { FileManager.default.createFile(atPath: file.path, contents: nil, attributes: nil) } return file } private static func createCommon(allowDelete: Bool = false) -> CoreDataCoordinator? { guard let url = self.commonUrl else { return nil } let coordintor = CoreDataCoordinator.create(name: "Privado", storageUrl: url, async: false, completion: nil) guard let context = coordintor?.createContext() else { return coordintor } let request: NSFetchRequest = LogRecord.fetchRequest() request.sortDescriptors = [NSSortDescriptor(keyPath: \LogRecord.date, ascending: false)] var logs = context.fetch(request) if logs.count > Constants.maxLogRecords { var diff = logs.count - Constants.maxLogRecords while diff > 0 { guard let log = logs.popLast() else { break } context.delete(log) diff -= 1 } context.save(sync: false, forced: true) coordintor?.save() } return coordintor } private static func remove(at url: URL?) -> Bool { guard let pathUrl = url else { return false } guard FileManager.default.fileExists(atPath: pathUrl.path) , FileManager.default.isDeletableFile(atPath: pathUrl.path) else { return false } try? FileManager.default.removeItem(atPath: pathUrl.path) return true } static var commonDB: CoreDataCoordinator? = { return DatabaseAnswer.createCommon(allowDelete: true) }() // TEMPORARY! Next we need migration! static func clearCommon() { return /*guard let url = self.commonUrl else { return } try? FileManager.default.removeItem(at: url) guard let loggerUrl = self.loggerUrl else { return } try? FileManager.default.removeItem(at: loggerUrl)*/ } }