Skip to content

Commit

Permalink
ability to add multiple accounts
Browse files Browse the repository at this point in the history
v1.3.1 -> v1.4
  • Loading branch information
artginzburg committed Feb 20, 2020
1 parent 3f0e52e commit ecdedbd
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 189 deletions.
10 changes: 6 additions & 4 deletions 2FA to Tray.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = R2294BC6J8;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "2FA to Tray/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.3.1;
MARKETING_VERSION = 1.4;
PRODUCT_BUNDLE_IDENTIFIER = com.dafuqtor.2FAtoTray;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -322,14 +323,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = R2294BC6J8;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "2FA to Tray/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.3.1;
MARKETING_VERSION = 1.4;
PRODUCT_BUNDLE_IDENTIFIER = com.dafuqtor.2FAtoTray;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
161 changes: 52 additions & 109 deletions 2FA to Tray/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,61 +11,59 @@ import JavaScriptCore

let defaults = UserDefaults.standard
extension UserDefaults {
func toggleBool(_ forKey: String) {
func boolToggle(_ forKey: String) {
self.set(!self.bool(forKey: forKey), forKey: forKey)
}
}

extension NSMenuItem {
func toggleState() {
self.state = self.state == .on ? .off : .on
extension NSControl.StateValue {
mutating func toggle() {
self = self == .on ? .off : .on
}
func stateBy(_ bool: Bool) {
self.state = bool ? .on : .off
mutating func by(_ bool: Bool) {
self = bool ? .on : .off
}
}

import KeychainAccess
let keychain = Keychain(service: "com.dafuqtor.2FAtoTray")
let keychain = Keychain(service: Bundle.main.bundleIdentifier!)

extension String {

func condenseWhitespace() -> String {
return self.components(separatedBy: .whitespacesAndNewlines).filter { !$0.isEmpty }.joined(separator: " ")
}

}

final class EditableNSTextField: NSTextField {

private let commandKey = NSEvent.ModifierFlags.command.rawValue
private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue

override func performKeyEquivalent(with event: NSEvent) -> Bool {
if event.type == NSEvent.EventType.keyDown {
if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
switch event.charactersIgnoringModifiers! {
case "x":
if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
case "c":
if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
case "v":
if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
case "z":
if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
case "a":
if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
default:
break
}
} else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
if event.charactersIgnoringModifiers == "Z" {
if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
}
}

private let commandKey = NSEvent.ModifierFlags.command.rawValue
private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue

override func performKeyEquivalent(with event: NSEvent) -> Bool {
if event.type == NSEvent.EventType.keyDown {
if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
switch event.charactersIgnoringModifiers! {
case "x":
if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
case "c":
if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
case "v":
if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
case "z":
if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
case "a":
if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
default:
break
}
} else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
if event.charactersIgnoringModifiers == "Z" {
if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
}
return super.performKeyEquivalent(with: event)
}
}
return super.performKeyEquivalent(with: event)
}
}

import AppKit
Expand All @@ -81,15 +79,18 @@ class Clipboard {
}

func paste() {
if !AXIsProcessTrusted() {
return
}
checkAccessibilityPermissions()

DispatchQueue.main.async {
let vCode = UInt16(kVK_ANSI_V)
let source = CGEventSource(stateID: .combinedSessionState)
// Disable local keyboard events while pasting
source?.setLocalEventsFilterDuringSuppressionState([.permitLocalMouseEvents, .permitSystemDefinedEvents],
state: .eventSuppressionStateSuppressionInterval)

let keyVDown = CGEvent(keyboardEventSource: source, virtualKey: vCode, keyDown: true)
let keyVUp = CGEvent(keyboardEventSource: source, virtualKey: vCode, keyDown: false)
keyVDown?.flags = .maskCommand
Expand All @@ -105,18 +106,20 @@ class Clipboard {
}
}

let otp = OTP()
var otpInstances: [OTP] = []
class OTP {

private var fn:JSValue?
private var timer:Timer?
var token:String
var button:NSStatusBarButton?
var displayItem:NSMenuItem?
var secret:String

init() {
fn = nil
button = nil
displayItem = nil
timer = nil
secret = ""
token = ""
Expand All @@ -141,100 +144,40 @@ class OTP {
let token = result!.toString()!
if self.token != token {
self.token = token
self.button!.toolTip = token
self.button?.toolTip = token
self.button?.appearsDisabled = false
self.displayItem?.title = token
self.displayItem?.isHidden = false
self.displayItem?.isEnabled = true
}
}
}

func initTimer() {
self.timer = Timer.new(every: 2.second) {
self.timer = Timer.new(every: 1.second) {
self.updateTimer()
}
self.timer!.start()
}

func copy() {
if self.token.isEmpty {
self.showAlert()
} else {
clipboard.copy(self.token)
}
}

func showAlert() {
if (NSApplication.shared.modalWindow) != nil {
return
}
let alert = NSAlert()
alert.messageText = "Change secret seed"
alert.informativeText = "Enter a code which should look like this:"

alert.addButton(withTitle: "OK")
alert.addButton(withTitle: "Cancel")
alert.addButton(withTitle: "Delete secret from disk")

let textfield = EditableNSTextField(frame: NSRect(x: 0.0, y: 0.0, width: 150.0, height: 22.0))
textfield.alignment = .center
textfield.placeholderString = "AADEM4YUY5GYZHHP"
alert.accessoryView = textfield

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
textfield.becomeFirstResponder()
}

let theSecret = keychain["secret"] ?? ""
if !theSecret.isEmpty {
textfield.stringValue = theSecret
}

let response = alert.runModal()

if response == .alertFirstButtonReturn {
let value = textfield.stringValue
if !value.isEmpty {
let secret = value.condenseWhitespace()

do {
try keychain
.synchronizable(true)
.accessibility(.afterFirstUnlock)
.set(secret, key: "secret")
} catch let error {
print("error: \(error)")
}

self.button?.appearsDisabled = false
self.secret = secret
} else {
print("Empty value")
}
} else if response == .alertThirdButtonReturn {
print("Delete secret")
do {
try keychain.remove("secret")
} catch let error {
print("error: \(error)")
}
self.secret = ""
self.token = ""
self.button?.toolTip = ""
self.button?.appearsDisabled = true
}
clipboard.copy(self.token)
print("copied the token")
}

}

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationShouldHandleReopen(_ sender: NSApplication,
hasVisibleWindows flag: Bool) -> Bool
{
otp.copy()
otpInstances[currentlySelectedSeed].copy()
if let button = statusItem.button {
button.highlight(true)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
button.highlight(false)
}
print("highlighted statusItem.button")
}
print("handled reopen")
return true
Expand Down
36 changes: 27 additions & 9 deletions 2FA to Tray/Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
Expand All @@ -20,23 +21,37 @@
<outlet property="pasteOnDoubleClickButton" destination="2iy-PT-cH5" id="qMa-Di-2sF"/>
<outlet property="permissionsButton" destination="045-Ih-Tf7" id="7A2-sI-Q01"/>
<outlet property="statusMenu" destination="Xfq-v7-Hh9" id="IVL-Qf-J99"/>
<outlet property="tokenDisplay" destination="zOQ-XV-e7G" id="1d5-EH-Qe4"/>
</connections>
</customObject>
<menu showsStateColumn="NO" id="Xfq-v7-Hh9">
<menu id="Xfq-v7-Hh9">
<items>
<menuItem title="Token" hidden="YES" enabled="NO" keyEquivalent="c" indentationLevel="1" id="zOQ-XV-e7G">
<menuItem title="Copy Token" hidden="YES" keyEquivalent="c" allowsKeyEquivalentWhenHidden="YES" id="pjS-KF-kBg">
<connections>
<action selector="tokenDisplayClicked:" target="dok-4Z-Dc3" id="Ccq-RI-Ctx"/>
<action selector="copyTokenClicked:" target="dok-4Z-Dc3" id="TqR-tB-Gsg"/>
</connections>
</menuItem>
<menuItem title="Paste Token" hidden="YES" keyEquivalent="v" allowsKeyEquivalentWhenHidden="YES" id="zFw-k9-rav">
<connections>
<action selector="pasteTokenClicked:" target="dok-4Z-Dc3" id="C0k-86-o0p"/>
</connections>
</menuItem>
<menuItem title="Add new..." image="NSAddTemplate" id="mOb-6m-Qx6">
<attributedString key="attributedTitle">
<fragment content="Add new...">
<attributes>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" metaFont="label" size="12"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
</attributedString>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="addNewClicked:" target="dok-4Z-Dc3" id="xmQ-FJ-bgq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4gT-no-BVk"/>
<menuItem title="Auto-paste on" indentationLevel="1" id="lYJ-t7-4RJ">
<menuItem title="Auto-paste on" id="lYJ-t7-4RJ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Auto-paste on" autoenablesItems="NO" id="teo-zT-IQW">
<items>
Expand Down Expand Up @@ -69,12 +84,12 @@
</items>
</menu>
</menuItem>
<menuItem title="Change secret..." keyEquivalent="," indentationLevel="1" id="UPw-mj-LC4">
<menuItem title="Change secret..." keyEquivalent="," id="UPw-mj-LC4">
<connections>
<action selector="changeSecret:" target="dok-4Z-Dc3" id="Heu-pl-tvM"/>
</connections>
</menuItem>
<menuItem title="Quit" keyEquivalent="q" indentationLevel="1" id="YdM-ld-HSz" userLabel="Quit">
<menuItem title="Quit" keyEquivalent="q" id="YdM-ld-HSz" userLabel="Quit">
<connections>
<action selector="terminate:" target="-1" id="gjK-Ut-vGN"/>
</connections>
Expand All @@ -83,4 +98,7 @@
<point key="canvasLocation" x="139" y="-98"/>
</menu>
</objects>
<resources>
<image name="NSAddTemplate" width="11" height="11"/>
</resources>
</document>
Loading

0 comments on commit ecdedbd

Please sign in to comment.