module SecondStep::MacOSNotify
Public Class Methods
_notify(message, options = {}, verbose = false)
click to toggle source
# File lib/second_step/mac_os_notify.rb, line 17 def self._notify(message, options = {}, verbose = false) result = TerminalNotifier.execute(verbose, options.merge(:message => message)) $? && $?.success? && _notify_result(result, options) end
_notify_result(result, options = {})
click to toggle source
# File lib/second_step/mac_os_notify.rb, line 9 def self._notify_result(result, options = {}) reply_option = options[:reply] || options['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)
click to toggle source
# 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) { |include?(result) ? result : :ignore| ... }
click to toggle source
Returns an action from actions, or `:ignore` Action must be an array of symbols containing only word characters and non-neighboring underscores.
# 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 if result == :_contentclicked result = notify_with_dialog(details.merge(from: from, actions: actions, action_text: action_text, ignore_label: ignore_label, show_details: show_details)) end 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 end
notify_with_dialog(details)
click to toggle source
# File lib/second_step/mac_os_notify.rb, line 24 def self.notify_with_dialog(details) buttons = 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.expand_path('../logo.png.icns', __FILE__) osascript = <<-osascript try 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}" return the button returned of dialogResult on error number -128 return "ignore" end try osascript result = IO.popen('osascript', 'r+') do |f| f.puts osascript f.close_write f.readlines end _notify_result result.first.chomp end