111 lines
4.3 KiB
Swift
111 lines
4.3 KiB
Swift
import Foundation
|
|
import UserNotifications
|
|
import AppKit
|
|
import SecretKit
|
|
import SecretAgentKit
|
|
import Brief
|
|
|
|
class Notifier {
|
|
|
|
fileprivate let notificationDelegate = NotificationDelegate()
|
|
|
|
init() {
|
|
let action = UNNotificationAction(identifier: Constants.updateIdentitifier, title: "Update", options: [])
|
|
let categories = UNNotificationCategory(identifier: Constants.updateIdentitifier, actions: [action], intentIdentifiers: [], options: [])
|
|
UNUserNotificationCenter.current().setNotificationCategories([categories])
|
|
UNUserNotificationCenter.current().delegate = notificationDelegate
|
|
}
|
|
|
|
func prompt() {
|
|
let notificationCenter = UNUserNotificationCenter.current()
|
|
notificationCenter.requestAuthorization(options: .alert) { _, _ in
|
|
}
|
|
}
|
|
|
|
func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) {
|
|
let notificationCenter = UNUserNotificationCenter.current()
|
|
let notificationContent = UNMutableNotificationContent()
|
|
notificationContent.title = "Signed Request from \(provenance.origin.name)"
|
|
notificationContent.subtitle = "Using secret \"\(secret.name)\""
|
|
if let iconURL = iconURL(for: provenance), let attachment = try? UNNotificationAttachment(identifier: "icon", url: iconURL, options: nil) {
|
|
notificationContent.attachments = [attachment]
|
|
}
|
|
let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil)
|
|
notificationCenter.add(request, withCompletionHandler: nil)
|
|
}
|
|
|
|
func notify(update: Release) {
|
|
notificationDelegate.release = update
|
|
let notificationCenter = UNUserNotificationCenter.current()
|
|
let notificationContent = UNMutableNotificationContent()
|
|
if update.critical {
|
|
notificationContent.title = "Critical Security Update - \(update.name)"
|
|
} else {
|
|
notificationContent.title = "Update Available - \(update.name)"
|
|
}
|
|
notificationContent.subtitle = "Click to Update"
|
|
notificationContent.body = update.body
|
|
notificationContent.categoryIdentifier = Constants.updateIdentitifier
|
|
let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil)
|
|
notificationCenter.add(request, withCompletionHandler: nil)
|
|
}
|
|
|
|
}
|
|
|
|
extension Notifier {
|
|
|
|
func iconURL(for provenance: SigningRequestProvenance) -> URL? {
|
|
do {
|
|
if let app = NSRunningApplication(processIdentifier: provenance.origin.pid), let icon = app.icon?.tiffRepresentation {
|
|
let temporaryURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("\(UUID().uuidString).png"))
|
|
let bitmap = NSBitmapImageRep(data: icon)
|
|
try bitmap?.representation(using: .png, properties: [:])?.write(to: temporaryURL)
|
|
return temporaryURL
|
|
}
|
|
} catch {
|
|
}
|
|
return nil
|
|
}
|
|
|
|
}
|
|
|
|
extension Notifier: SigningWitness {
|
|
|
|
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws {
|
|
}
|
|
|
|
func witness(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws {
|
|
notify(accessTo: secret, by: provenance)
|
|
}
|
|
|
|
}
|
|
|
|
extension Notifier {
|
|
|
|
enum Constants {
|
|
static let updateIdentitifier = "com.maxgoedjen.Secretive.SecretAgent.update"
|
|
}
|
|
|
|
}
|
|
|
|
class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
|
|
|
|
fileprivate var release: Release?
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
|
|
|
|
}
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
|
guard response.notification.request.content.categoryIdentifier == Notifier.Constants.updateIdentitifier else { return }
|
|
guard let update = release else { return }
|
|
NSWorkspace.shared.open(update.html_url)
|
|
completionHandler()
|
|
}
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
|
completionHandler(.alert)
|
|
}
|
|
|
|
}
|