Class: Mortar::Auth

Inherits:
Object
  • Object
show all
Extended by:
Helpers
Defined in:
lib/mortar/auth.rb

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from Helpers

action, ask, confirm, copy_if_not_present_at_dest, default_host, deprecate, display, display_header, display_object, display_row, display_table, display_with_indent, download_to_file, ensure_dir_exists, error, error_with_failure, error_with_failure=, extended, extended_into, format_bytes, format_date, format_with_bang, get_terminal_environment, home_directory, host, hprint, hputs, included, included_into, installed_with_omnibus?, json_decode, json_encode, line_formatter, longest, output_with_bang, quantify, redisplay, retry_on_exception, running_on_a_mac?, running_on_windows?, set_buffer, shell, spinner, status, string_distance, styled_array, styled_error, styled_hash, styled_header, suggestion, test_name, ticking, time_ago, truncate, warning, with_tty, write_to_file

Class Attribute Details

.credentialsObject

Returns the value of attribute credentials.



30
31
32
# File 'lib/mortar/auth.rb', line 30

def credentials
  @credentials
end

Class Method Details

.apiObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/mortar/auth.rb', line 32

def api
  @api ||= begin
    require("mortar-api-ruby")
    api = Mortar::API.new(default_params.merge(:user => user, :api_key => password))

    def api.request(params, &block)
      response = super
      if response.headers.has_key?('X-Mortar-Warning')
        Mortar::Command.warnings.concat(response.headers['X-Mortar-Warning'].split("\n"))
      end
      response
    end

    api
  end
end

.api_key(user = get_credentials[0], password = get_credentials[1]) ⇒ Object



88
89
90
91
92
# File 'lib/mortar/auth.rb', line 88

def api_key(user = get_credentials[0], password = get_credentials[1])
  require("mortar-api-ruby")
  api = Mortar::API.new(default_params)
  api.(user, password).body["api_key"]
end

.ask_for_and_save_credentialsObject



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/mortar/auth.rb', line 216

def ask_for_and_save_credentials
  require("mortar-api-ruby") # for the errors
  begin
    @credentials = ask_for_credentials
    write_credentials
    check
  rescue Mortar::API::Errors::NotFound, Mortar::API::Errors::Unauthorized => e
    delete_credentials
    display "Authentication failed."
    retry if retry_login?
    exit 1
  rescue Mortar::CLI::Errors::InvalidGithubUsername => e
    #Too many failures at setting github username
    display "Authentication failed."
    delete_credentials
    exit 1
  rescue Exception => e
    delete_credentials
    raise e
  end
  # TODO: ensure that keys exist
  #check_for_associated_ssh_key unless Mortar::Command.current_command == "keys:add"
  @credentials
end

.ask_for_and_save_github_usernameObject



241
242
243
244
245
246
247
# File 'lib/mortar/auth.rb', line 241

def ask_for_and_save_github_username
  require ("mortar-api-ruby")
  begin
    @github_username = ask_for_github_username
    save_github_username
  end
end

.ask_for_credentialsObject



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/mortar/auth.rb', line 168

def ask_for_credentials
  puts
  puts "Enter your Mortar credentials."

  print "Email: "
  user = ask

  print "Password (typing will be hidden): "
  password = running_on_windows? ? ask_for_password_on_windows : ask_for_password

  [user, api_key(user, password)]
end

.ask_for_github_usernameObject



181
182
183
184
185
186
187
188
# File 'lib/mortar/auth.rb', line 181

def ask_for_github_username
  puts
  puts "Please enter your github username (not email address)."

  print "Github Username: "
  github_username = ask
  github_username
end

.ask_for_passwordObject



208
209
210
211
212
213
214
# File 'lib/mortar/auth.rb', line 208

def ask_for_password
  echo_off
  password = ask
  puts
  echo_on
  return password
end

.ask_for_password_on_windowsObject



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/mortar/auth.rb', line 190

def ask_for_password_on_windows
  require "Win32API"
  char = nil
  password = ''

  while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
    break if char == 10 || char == 13 # received carriage return or newline
    if char == 127 || char == 8 # backspace and delete
      password.slice!(-1, 1)
    else
      # windows might throw a -1 at us so make sure to handle RangeError
      (password << char.chr) rescue RangeError
    end
  end
  puts
  return password
end

.checkObject



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/mortar/auth.rb', line 58

def check
  @mortar_user = api.get_user.body
  #Need to ensure user has a github_username
  unless @mortar_user.fetch("user_github_username", nil)
    begin
      ask_for_and_save_github_username
    rescue Mortar::CLI::Errors::InvalidGithubUsername => e
      retry if retry_set_github_username?
      raise e
    end
  end
end

.delete_credentialsObject



102
103
104
105
106
107
108
# File 'lib/mortar/auth.rb', line 102

def delete_credentials
  if netrc
    netrc.delete("api.#{host}")
    netrc.save
  end
  @api, @client, @credentials = nil, nil
end

.echo_offObject



156
157
158
159
160
# File 'lib/mortar/auth.rb', line 156

def echo_off
  with_tty do
    system "stty -echo"
  end
end

.echo_onObject



162
163
164
165
166
# File 'lib/mortar/auth.rb', line 162

def echo_on
  with_tty do
    system "stty echo"
  end
end

.get_credentialsObject

:nodoc:



98
99
100
# File 'lib/mortar/auth.rb', line 98

def get_credentials    # :nodoc:
  @credentials ||= (read_credentials || ask_for_and_save_credentials)
end

.has_credentialsObject



94
95
96
# File 'lib/mortar/auth.rb', line 94

def has_credentials
  (nil != read_credentials)
end

.loginObject



49
50
51
52
# File 'lib/mortar/auth.rb', line 49

def 
  delete_credentials
  get_credentials
end

.logoutObject



54
55
56
# File 'lib/mortar/auth.rb', line 54

def logout
  delete_credentials
end

.netrcObject

:nodoc:



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/mortar/auth.rb', line 123

def netrc   # :nodoc:
  @netrc ||= begin
    File.exists?(netrc_path) && Netrc.read(netrc_path)
  rescue => error
    if error.message =~ /^Permission bits for/
      perm = File.stat(netrc_path).mode & 0777
      abort("Permissions #{perm} for '#{netrc_path}' are too open. You should run `chmod 0600 #{netrc_path}` so that your credentials are NOT accessible by others.")
    else
      raise error
    end
  end
end

.netrc_pathObject



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/mortar/auth.rb', line 110

def netrc_path
  default = Netrc.default_path
  encrypted = default + ".gpg"
  from_env = ENV['MORTAR_LOGIN_FILE']
  if from_env
    from_env
  elsif File.exists?(encrypted)
    encrypted
  else
    default
  end
end

.passwordObject

:nodoc:



79
80
81
# File 'lib/mortar/auth.rb', line 79

def password    # :nodoc:
  get_credentials[1]
end

.polling_intervalObject



294
295
296
# File 'lib/mortar/auth.rb', line 294

def polling_interval
  (2.0).to_f
end

.read_credentialsObject



136
137
138
139
140
141
142
143
144
# File 'lib/mortar/auth.rb', line 136

def read_credentials
  if ENV['MORTAR_API_KEY']
    ['', ENV['MORTAR_API_KEY']]
  else
    if netrc
      netrc["api.#{host}"]
    end
  end
end

.reauthorizeObject



71
72
73
# File 'lib/mortar/auth.rb', line 71

def reauthorize
  @credentials = ask_for_and_save_credentials
end

.retry_login?Boolean

Returns:

  • (Boolean)


282
283
284
285
286
# File 'lib/mortar/auth.rb', line 282

def retry_login?
  @login_attempts ||= 0
  @login_attempts += 1
  @login_attempts < 3
end

.retry_set_github_username?Boolean

Returns:

  • (Boolean)


288
289
290
291
292
# File 'lib/mortar/auth.rb', line 288

def retry_set_github_username?
  @set_github_username_attempts ||= 0
  @set_github_username_attempts += 1
  @set_github_username_attempts < 3
end

.save_github_usernameObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/mortar/auth.rb', line 249

def save_github_username
  task_id = api.update_user(@mortar_user['user_id'], {'user_github_username' => @github_username}).body['task_id']

  task_result = nil
  ticking(polling_interval) do |ticks|
    task_result = api.get_task(task_id).body
    is_finished =
      Mortar::API::Task::STATUSES_COMPLETE.include?(task_result["status_code"])
    
    redisplay("Setting github username: %s" % 
      [is_finished ? " Done!" : spinner(ticks)],
      is_finished) # only display newline on last message
    if is_finished
      display
      break
    end
  end

  case task_result['status_code']
  when Mortar::API::Task::STATUS_FAILURE
    error_message = "Setting github username failed with #{task_result['error_type'] || 'error'}"
    error_message += ":\n\n#{task_result['error_message']}\n\n"
    output_with_bang error_message
    raise Mortar::CLI::Errors::InvalidGithubUsername.new
  when Mortar::API::Task::STATUS_SUCCESS
    display "Successfully set github username." 
  else
    #Raise error so .netrc file is wiped out.
    raise RuntimeError, "Unknown task status: #{task_result['status_code']}"
  end
end

.userObject

:nodoc:



75
76
77
# File 'lib/mortar/auth.rb', line 75

def user    # :nodoc:
  get_credentials[0]
end

.user_s3_safe(local = false) ⇒ Object



83
84
85
86
# File 'lib/mortar/auth.rb', line 83

def user_s3_safe(local = false)
  user_email = (local && !has_credentials) ? "[email protected]" : user
  return user_email.gsub(/[^0-9a-zA-Z]/i, '-')
end

.write_credentialsObject



146
147
148
149
150
151
152
153
154
# File 'lib/mortar/auth.rb', line 146

def write_credentials
  FileUtils.mkdir_p(File.dirname(netrc_path))
  FileUtils.touch(netrc_path)
  unless running_on_windows?
    FileUtils.chmod(0600, netrc_path)
  end
  netrc["api.#{host}"] = self.credentials
  netrc.save
end