Module: SecondStep::MacOSNotify
- Defined in:
- lib/second_step/mac_os_notify.rb
Class Method Summary collapse
- ._notify(message, options = {}, verbose = false) ⇒ Object
- ._notify_result(result, options = {}) ⇒ Object
- .hash_to_array_with_only(hash, keys = nil) ⇒ Object
-
.notify_login(from: 'Unknown', actions: %i[approve deny],, action_text: 'Approve or Deny:', timeout: 5, ignore_label: 'Ignore', show_details: nil, **details) ⇒ Object
Returns an action from actions, or
:ignoreAction must be an array of symbols containing only word characters and non-neighboring underscores. - .notify_with_dialog(details) ⇒ Object
Class Method Details
._notify(message, options = {}, verbose = false) ⇒ Object
17 18 19 20 |
# File 'lib/second_step/mac_os_notify.rb', line 17 def self._notify(, = {}, verbose = false) result = TerminalNotifier.execute(verbose, .merge(:message => )) $? && $?.success? && _notify_result(result, ) end |
._notify_result(result, options = {}) ⇒ Object
9 10 11 12 13 14 15 16 |
# File 'lib/second_step/mac_os_notify.rb', line 9 def self._notify_result(result, = {}) reply_option = [:reply] || ['reply'] if reply_option && !result.start_with?('@') result else result.length == 0 || result.downcase.gsub(/\W+/,'_').to_sym end end |
.hash_to_array_with_only(hash, keys = nil) ⇒ Object
21 22 23 |
# File 'lib/second_step/mac_os_notify.rb', line 21 def self.hash_to_array_with_only(hash, keys = nil) keys.zip(hash.values_at(*keys)) end |
.notify_login(from: 'Unknown', actions: %i[approve deny],, action_text: 'Approve or Deny:', timeout: 5, ignore_label: 'Ignore', show_details: nil, **details) ⇒ Object
Returns an action from actions, or :ignore Action must be an array of symbols containing only word characters and non-neighboring underscores.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/second_step/mac_os_notify.rb', line 50 def self.notify_login(from: 'Unknown', actions: i[approve deny], action_text: 'Approve or Deny:', timeout: 5, ignore_label: 'Ignore', show_details: nil, **details) if show_details show_details &= details.keys else show_details = details.keys end body_text = hash_to_array_with_only(details, show_details).map{|(k,v)| "#{k.to_s.capitalize}: #{v}"}.join(', ') subprocess = fork do begin if TerminalNotifier.available? result = _notify(body_text, actions: actions.map{|s| s.to_s.capitalize}.join(','), closeLabel: ignore_label, dropdownLabel: action_text, title: 'SecondStep', subtitle: "Login Request from #{from}", group: Process.pid, sender: 'com.getsecondstep.macos.mac-notify', timeout: timeout) if result result = notify_with_dialog(details.merge(from: from, actions: actions, action_text: action_text, ignore_label: ignore_label, show_details: show_details)) if result == :_contentclicked yield actions.include?(result) ? result : :ignore else raise NotificationError.new(result) end else result = notify_with_dialog(details.merge(from: from, actions: actions, action_text: action_text, ignore_label: ignore_label, show_details: show_details)) yield actions.include?(result) ? result : :ignore end ensure TerminalNotifier.remove Process.pid end end at_exit { begin unless Process.waitpid subprocess, Process::WNOHANG puts "Waiting for notification in process #{subprocess} to finish..." begin Timeout.timeout(180) do Process.wait subprocess end rescue Timeout::Error puts "Process #{subprocess} not finishing... killing" begin Process.kill('HUP', subprocess) Timeout.timeout(20) do Process.wait subprocess end rescue Timeout::Error puts "Process #{subprocess} not killing... terminating" Process.kill(9, subprocess) end end end rescue Errno::ECHILD true end } end |
.notify_with_dialog(details) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/second_step/mac_os_notify.rb', line 24 def self.notify_with_dialog(details) = details[:actions].map{ |action| "\"#{Shellwords.shellescape(action.to_s.capitalize)}\"" } escaped_from = Shellwords.shellescape details[:from] body_text = hash_to_array_with_only(details, details[:show_details]).map do |(k,v)| body_line = k.to_s.capitalize.split(' ') body_line.last << ':' Shellwords.join(body_line + v.to_s.split(' ')) end.join('\n') icon_path = File.('../logo.png.icns', __FILE__) osascript = "try\n set dialogResult to display dialog \"Login Request from \#{escaped_from}\\\\n\\\\n\#{body_text}\" buttons {\"Ignore\",\#{buttons.reverse.join(',')}} cancel button \"Ignore\" default button \#{buttons.first} with title \"SecondStep Login Request\" with icon POSIX file \"\#{icon_path}\"\n return the button returned of dialogResult\non error number -128\n return \"ignore\"\nend try\n osascript\n result = IO.popen('osascript', 'r+') do |f|\n f.puts osascript\n f.close_write\n f.readlines\n end\n _notify_result result.first.chomp\nend\n" |