gas 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/gas.rb +27 -28
- data/lib/gas/config.rb +5 -5
- data/lib/gas/github_speaker.rb +219 -0
- data/lib/gas/prompter.rb +169 -0
- data/lib/gas/settings.rb +28 -0
- data/lib/gas/ssh.rb +86 -411
- data/lib/gas/version.rb +1 -1
- data/spec/integration/ssh_spec.rb +338 -0
- data/spec/spec_helper.rb +110 -34
- data/spec/{gas → unit}/config_spec.rb +15 -15
- data/spec/{gas → unit}/gitconfig_spec.rb +10 -10
- data/spec/unit/github_speaker_spec.rb +107 -0
- data/spec/unit/settings_spec.rb +56 -0
- data/spec/{gas → unit}/user_spec.rb +0 -0
- metadata +116 -27
- data/spec/gas/ssh_spec.rb +0 -328
data/lib/gas/settings.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Gas
|
2
|
+
|
3
|
+
# Class that contains settings for the app
|
4
|
+
class Settings
|
5
|
+
attr_accessor :base_dir, :github_server
|
6
|
+
attr_reader :gas_dir, :ssh_dir
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@base_dir = '~'
|
10
|
+
@gas_dir = "#{@base_dir}/.gas"
|
11
|
+
@ssh_dir = "#{@base_dir}/.ssh"
|
12
|
+
@github_server = 'api.github.com'
|
13
|
+
end
|
14
|
+
|
15
|
+
def configure
|
16
|
+
yield self if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
def gas_dir=(value)
|
20
|
+
@gas_dir = "#{@base_dir}/#{value}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def ssh_dir=(value)
|
24
|
+
@ssh_dir = "#{@base_dir}/#{value}"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/gas/ssh.rb
CHANGED
@@ -1,42 +1,10 @@
|
|
1
1
|
module Gas
|
2
|
-
|
3
2
|
class Ssh
|
4
3
|
require 'highline/import'
|
5
4
|
require 'net/https'
|
6
5
|
require 'json'
|
7
|
-
|
8
|
-
|
9
|
-
# If the user says 'f', the system will
|
10
|
-
# report that there isn't an id_rsa already in gas. This causes a new key to overwrite automatically down the road.
|
11
|
-
# This is for checking if a .gas/rsa file already exists for a nickname which is being registered
|
12
|
-
# If the rsa exists, then we're goona need to ask if we should use it, or if we should delete it
|
13
|
-
#
|
14
|
-
# Returns true to indicate that the user would like to use the rsa file already in .gas ()
|
15
|
-
# Returns false when there is no naming conflicts.
|
16
|
-
def self.user_wants_to_use_key_already_in_gas?
|
17
|
-
if corresponding_rsa_files_exist?
|
18
|
-
puts "Gas has detected a key in its archive directory ~/.gas/#{@uid}_id_rsa. Should gas use this key or overwrite this key with a brand new one?"
|
19
|
-
puts "Keep current key? [y/n]"
|
20
|
-
|
21
|
-
while true
|
22
|
-
keep_current_file = STDIN.gets.strip
|
23
|
-
|
24
|
-
case keep_current_file
|
25
|
-
|
26
|
-
when "y"
|
27
|
-
return true # keep the files already in .gas, skip making key.
|
28
|
-
when "n"
|
29
|
-
return false
|
30
|
-
else
|
31
|
-
puts "please respond 'y' or 'n'"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
else # no need to do anything if files don't exist
|
36
|
-
return false
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
6
|
+
require 'digest/md5'
|
7
|
+
extend Prompter
|
40
8
|
|
41
9
|
def self.corresponding_rsa_files_exist?(nickname = '')
|
42
10
|
nickname = @uid if nickname == ''
|
@@ -44,60 +12,27 @@ module Gas
|
|
44
12
|
false
|
45
13
|
end
|
46
14
|
|
47
|
-
|
48
15
|
# Copies a key pair from ~/.ssh to .gas/Nickname*
|
49
16
|
def self.use_current_rsa_files_for_this_user(test = nil)
|
50
17
|
@uid = test unless test.nil?
|
51
|
-
|
52
|
-
|
18
|
+
FileUtils.cp("#{SSH_DIRECTORY}/id_rsa", "#{GAS_DIRECTORY}/#{@uid}_id_rsa")
|
19
|
+
FileUtils.cp("#{SSH_DIRECTORY}/id_rsa.pub", "#{GAS_DIRECTORY}/#{@uid}_id_rsa.pub")
|
20
|
+
FileUtils.chmod 0700, "#{GAS_DIRECTORY}/#{@uid}_id_rsa"
|
21
|
+
FileUtils.chmod 0700, "#{GAS_DIRECTORY}/#{@uid}_id_rsa.pub"
|
53
22
|
return true
|
54
23
|
end
|
55
24
|
|
56
|
-
|
57
25
|
def self.ssh_dir_contains_rsa?
|
58
26
|
return true if File.exists?(SSH_DIRECTORY + "/id_rsa") or File.exists?(SSH_DIRECTORY + "/id_rsa.pub")
|
59
27
|
return false
|
60
28
|
end
|
61
29
|
|
62
|
-
|
63
|
-
|
64
|
-
# Checks if the ~/.ssh directroy contains id_rsa and id_rsa.pub
|
65
|
-
# if it does, it asks the user if they would like to use that as their ssh key, instead of generating a new key pair.
|
66
|
-
#
|
67
|
-
def self.user_wants_to_use_key_already_in_ssh?
|
68
|
-
return false unless ssh_dir_contains_rsa?
|
69
|
-
|
70
|
-
#puts "Gas has detected that an ~/.ssh/id_rsa file already exists. Would you like to use this as your ssh key to connect with github? Otherwise a new key will be generated and stored in ~/.gas (no overwrite concerns until you 'gas use nickname')"
|
71
|
-
puts "Generate a brand new ssh key pair? (Choose 'n' to use key in ~/.ssh/id_rsa)"
|
72
|
-
puts "Default: 'y'"
|
73
|
-
puts "[Y/n]"
|
74
|
-
|
75
|
-
while true
|
76
|
-
generate_new_rsa = STDIN.gets.strip.downcase
|
77
|
-
case generate_new_rsa
|
78
|
-
when "y", ""
|
79
|
-
return false
|
80
|
-
when "n"
|
81
|
-
return true # return true if we aren't generating a new key
|
82
|
-
else
|
83
|
-
puts "plz answer 'y' or 'n'"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
30
|
# Generates a new sshkey putting it in ~/.gas/nickname_id_rsa
|
91
31
|
# This function can get a little tricky. It's best to strip off the comment here,
|
92
32
|
# because github API doesn't retain the comment...
|
93
33
|
def self.generate_new_rsa_keys_in_gas_dir
|
94
34
|
puts "Generating new ssh key..."
|
95
|
-
# TODO: Prompt user if they'd like to use a more secure password if physical security to their computer is not possible (dumb imo)... Unless we do that thing where we store keys on github!
|
96
35
|
|
97
|
-
# Old ssh key method (relies on unix environment)
|
98
|
-
# puts `ssh-keygen -f ~/.gas/#{@uid}_id_rsa -t rsa -C "#{@email}" -N ""` # ssh-keygen style key creation
|
99
|
-
|
100
|
-
# new sshkey gem method...
|
101
36
|
begin
|
102
37
|
k = SSHKey.generate() # (:comment => "#{@email}")
|
103
38
|
|
@@ -120,124 +55,61 @@ module Gas
|
|
120
55
|
end
|
121
56
|
end
|
122
57
|
|
123
|
-
|
124
|
-
|
125
|
-
def self.user_wants_gas_to_handle_rsa_keys?
|
126
|
-
puts "Do you want gas to handle switching rsa keys for this user?"
|
127
|
-
puts "[Y/n]"
|
128
|
-
|
129
|
-
while true
|
130
|
-
handle_rsa = STDIN.gets.strip
|
131
|
-
|
132
|
-
case handle_rsa
|
133
|
-
when "y", ""
|
134
|
-
return true
|
135
|
-
when "n"
|
136
|
-
puts
|
137
|
-
# check if ~/.gas/rsa exists, if it does, promt the user
|
138
|
-
if corresponding_rsa_files_exist? #in ~/.gas/
|
139
|
-
|
140
|
-
puts "Well... there's already a ~/.gas/#{@uid}_id_rsa configured and ready to go. Are you sure you don't want gas to handle rsa switching? (Clicking no will delete the key from the gas directory)"
|
141
|
-
puts "Just let gas handle ssh key for this user? [y/n]"
|
142
|
-
|
143
|
-
while true
|
144
|
-
keep_file = STDIN.gets.strip
|
145
|
-
|
146
|
-
case keep_file
|
147
|
-
when "n"
|
148
|
-
delete "~/.gas/#{@uid}_id_rsa", "~/.gas/#{@uid}_id_rsa.pub"
|
149
|
-
return false
|
150
|
-
when "y"
|
151
|
-
puts "Excelent! Gas will handle rsa keys for this user."
|
152
|
-
return nil
|
153
|
-
else
|
154
|
-
puts "Please use 'y' or 'n' or enter to choose default."
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
return false
|
159
|
-
|
160
|
-
else
|
161
|
-
puts "Please use 'y' or 'n'"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
58
|
# This function creates the ssh keys if needed and puts them in ~/.gas/NICKNAME_id_rsa and ...rsa.pub
|
169
|
-
#
|
170
|
-
#
|
171
59
|
def self.setup_ssh_keys(user)
|
172
60
|
@uid = user.nickname
|
173
61
|
@email = user.email
|
174
62
|
|
175
|
-
|
176
|
-
|
177
|
-
if wants_gas_handling_keys
|
178
|
-
puts
|
179
|
-
|
180
|
-
if user_wants_to_use_key_already_in_gas?
|
63
|
+
if Gas::Prompter.user_wants_gas_to_handle_rsa_keys?
|
64
|
+
if corresponding_rsa_files_exist?(@uid) and Gas::Prompter.user_wants_to_use_key_already_in_gas?(@uid)
|
181
65
|
return true # We don't need to do anything because the .gas directory is already setup
|
182
|
-
elsif user_wants_to_use_key_already_in_ssh? # Check ~/.ssh for a current id_rsa file, if yes, "Do you want to use the current id_rsa file to be used as your key?"
|
66
|
+
elsif !corresponding_rsa_files_exist?(@uid) and ssh_dir_contains_rsa? and Gas::Prompter.user_wants_to_use_key_already_in_ssh? # Check ~/.ssh for a current id_rsa file, if yes, "Do you want to use the current id_rsa file to be used as your key?"
|
183
67
|
use_current_rsa_files_for_this_user # copies the keys from ~/.ssh instead of generating new keys if desired/possible
|
184
68
|
return true
|
185
69
|
else
|
186
70
|
return generate_new_rsa_keys_in_gas_dir
|
187
71
|
end
|
188
72
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
73
|
+
else # !Gas::Prompter.user_wants_gas_to_handle_rsa_keys?
|
74
|
+
# check if ~/.gas/rsa exists, if it does, promt the user
|
75
|
+
# because that key must be destroyed (if the user really doesn't want gas handling keys for this user)
|
76
|
+
if corresponding_rsa_files_exist?(@uid) #in ~/.gas/
|
77
|
+
delete_associated_local_keys!(@uid) if Gas::Prompter.user_wants_to_remove_the_keys_that_already_exist_for_this_user?(@uid)
|
78
|
+
end
|
193
79
|
end
|
194
80
|
|
195
81
|
end
|
196
82
|
|
197
|
-
|
198
83
|
# This huge method handles the swapping of id_rsa files on the hdd
|
199
|
-
#
|
200
84
|
def self.swap_in_rsa(nickname)
|
201
85
|
@uid = nickname # woah, this is extremely sloppy I think... in order to use any other class methods,
|
202
86
|
# I need to write to @uid or it will
|
203
87
|
# Have the dumb information from the last time it registered a new git author?
|
204
88
|
|
205
|
-
if
|
206
|
-
|
89
|
+
if corresponding_rsa_files_exist?
|
207
90
|
if ssh_dir_contains_rsa?
|
208
91
|
if current_key_already_backed_up?
|
209
92
|
write_to_ssh_dir!
|
210
93
|
else
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
overwrite = STDIN.gets.strip
|
216
|
-
case overwrite
|
217
|
-
when "y"
|
218
|
-
write_to_ssh_dir!
|
219
|
-
break
|
220
|
-
when "n"
|
221
|
-
puts "Proceeding without swapping rsa keys."
|
222
|
-
break
|
223
|
-
else
|
224
|
-
puts "please respond 'y' or 'n'"
|
225
|
-
end
|
94
|
+
if Gas::Prompter.user_wants_to_overwrite_existing_rsa_key?
|
95
|
+
write_to_ssh_dir!
|
96
|
+
else
|
97
|
+
puts "Proceeding without swapping rsa keys (aborting)."
|
226
98
|
end
|
227
|
-
|
228
99
|
end
|
229
|
-
|
230
|
-
else # if no ~/.ssh/id_rsa exists... no overwrite potential
|
100
|
+
else # if no ~/.ssh/id_rsa exists... no overwrite potential... so just write away
|
231
101
|
write_to_ssh_dir!
|
232
102
|
end
|
233
|
-
|
234
103
|
end
|
235
104
|
end
|
236
105
|
|
237
|
-
|
106
|
+
|
238
107
|
def self.write_to_ssh_dir!
|
108
|
+
supress_process_output = "> /dev/null 2>&1"
|
109
|
+
supress_process_output = "> NUL" if IS_WINDOWS
|
110
|
+
|
239
111
|
# remove the current key from the ssh-agent session (key will no longer be used with github)
|
240
|
-
system(
|
112
|
+
system("ssh-add -d #{SSH_DIRECTORY}/id_rsa #{supress_process_output}") if is_ssh_agent_there?
|
241
113
|
|
242
114
|
FileUtils.cp(GAS_DIRECTORY + "/#{@uid}_id_rsa", SSH_DIRECTORY + "/id_rsa")
|
243
115
|
FileUtils.cp(GAS_DIRECTORY + "/#{@uid}_id_rsa.pub", SSH_DIRECTORY + "/id_rsa.pub")
|
@@ -246,23 +118,24 @@ module Gas
|
|
246
118
|
FileUtils.chmod(0700, SSH_DIRECTORY + "/id_rsa.pub")
|
247
119
|
|
248
120
|
if is_ssh_agent_there?
|
249
|
-
`ssh-add
|
250
|
-
|
251
|
-
|
252
|
-
puts "Looks like there may have been a fatal error in registering the rsa key with ssh-agent. Might be worth looking into"
|
121
|
+
`ssh-add #{SSH_DIRECTORY}/id_rsa #{supress_process_output}` # you need to run this command to get the private key to be set to active on unix based machines. Not sure what to do for windows yet...
|
122
|
+
|
123
|
+
if $?.exitstatus == 1 # exit status 1 means failed
|
124
|
+
puts "Looks like there may have been a fatal error in registering the rsa key with ssh-agent. Might be worth looking into"
|
125
|
+
raise "Exit code on ssh-add command line was one meaning: Error!"
|
253
126
|
end
|
127
|
+
|
254
128
|
else
|
255
129
|
puts "Slight Error: The key should now be in ~/.ssh so that's good, BUT ssh-add could not be found. If you're using windows, you'll need to use git bash or cygwin to emulate this unix command and actually do uploads."
|
256
130
|
end
|
131
|
+
|
257
132
|
end
|
258
133
|
|
259
|
-
|
260
|
-
#
|
134
|
+
# This function scans each file in a directory to check
|
135
|
+
# to see if it is the same file which it's being compared against
|
261
136
|
# dir_to_scan The target directory you'd like to scan
|
262
137
|
# file_to_compare The file's path that you're expecting to find
|
263
138
|
def self.scan_for_file_match(file_to_compare, dir_to_scan)
|
264
|
-
require 'digest/md5'
|
265
|
-
|
266
139
|
pattern = get_md5_hash(file_to_compare)
|
267
140
|
|
268
141
|
@files = Dir.glob(dir_to_scan + "/*" + file_to_compare.split(//).last(1).to_s)
|
@@ -274,7 +147,6 @@ module Gas
|
|
274
147
|
return false
|
275
148
|
end
|
276
149
|
|
277
|
-
|
278
150
|
def self.current_key_already_backed_up?
|
279
151
|
if scan_for_file_match(SSH_DIRECTORY + "/id_rsa", GAS_DIRECTORY) and scan_for_file_match(SSH_DIRECTORY + "/id_rsa.pub", GAS_DIRECTORY)
|
280
152
|
return true
|
@@ -285,243 +157,74 @@ module Gas
|
|
285
157
|
|
286
158
|
def self.get_md5_hash(file_path)
|
287
159
|
if File.exists? file_path
|
288
|
-
|
160
|
+
file = File.open(file_path, "rb")
|
161
|
+
hash = Digest::MD5.hexdigest(file.read)
|
162
|
+
file.close
|
163
|
+
return hash
|
289
164
|
end
|
290
165
|
return nil
|
291
166
|
end
|
292
167
|
|
293
168
|
|
294
|
-
def self.
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
while true
|
299
|
-
upload_key = STDIN.gets.strip.downcase
|
300
|
-
case upload_key
|
301
|
-
when "y", ""
|
302
|
-
return true
|
303
|
-
when "n"
|
304
|
-
return false
|
305
|
-
else
|
306
|
-
puts "Plz respond 'y' or 'n'"
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
|
312
|
-
def self.upload_public_key_to_github(user)
|
313
|
-
@uid = user.nickname
|
314
|
-
|
315
|
-
if user_wants_to_install_key_to_github?
|
316
|
-
key_installation_routine!
|
169
|
+
def self.upload_public_key_to_github(user, github_speaker = nil)
|
170
|
+
if Gas::Prompter.user_wants_to_install_key_to_github?
|
171
|
+
key_installation_routine!(user, nil, github_speaker)
|
317
172
|
end
|
318
173
|
end
|
319
174
|
|
320
|
-
|
321
|
-
def self.key_installation_routine!(user = nil, rsa_test = nil)
|
175
|
+
|
176
|
+
def self.key_installation_routine!(user = nil, rsa_test = nil, github_speaker = nil)
|
322
177
|
@uid = user.nickname unless user.nil? # allows for easy testing
|
323
178
|
|
324
|
-
rsa_key = get_associated_rsa_key(@uid)
|
179
|
+
rsa_key = get_associated_rsa_key(@uid).first
|
325
180
|
rsa_key = rsa_test unless rsa_test.nil?
|
326
181
|
return false if rsa_key.nil?
|
327
182
|
|
328
183
|
# TODO: Impliment a key ring system where you store your key on your github in a repository, only it's encrypted. And to decrypt it, there is
|
329
184
|
# A file in your .gas folder!!! That sounds SO fun!
|
330
|
-
|
185
|
+
github_speaker = GithubSpeaker.new(user) if github_speaker.nil?
|
186
|
+
|
187
|
+
puts github_speaker.status
|
331
188
|
|
332
|
-
if
|
189
|
+
if github_speaker.status == :bad_credentials
|
333
190
|
puts "Invalid credentials. Skipping upload of keys to github. "
|
334
191
|
puts "To try again, type $ gas ssh #{@uid}"
|
335
192
|
return false
|
336
193
|
end
|
337
|
-
|
338
|
-
result = post_key!(
|
194
|
+
|
195
|
+
result = github_speaker.post_key!(rsa_key)
|
196
|
+
|
339
197
|
if result
|
340
198
|
puts "Key uploaded successfully!"
|
341
199
|
return true
|
342
200
|
end
|
343
201
|
end
|
344
202
|
|
345
|
-
|
346
|
-
#
|
203
|
+
# Get's the ~/.gas/user_id_rsa and ~/.gas/user_id_rsa.pub strings associated with
|
204
|
+
# the specified user and returns it as an array. Returns array with two nils if there's no keys
|
205
|
+
# [pub_rsa, priv_rsa]
|
347
206
|
def self.get_associated_rsa_key(nickname)
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
end
|
359
|
-
return nil
|
360
|
-
end
|
361
|
-
|
362
|
-
|
363
|
-
def self.get_username_and_password_and_authenticate
|
364
|
-
puts "Type your github.com user name:"
|
365
|
-
print "User: "
|
366
|
-
username = STDIN.gets.strip
|
367
|
-
|
368
|
-
puts "Type your github password:"
|
369
|
-
password = ask("Password: ") { |q| q.echo = false }
|
370
|
-
puts
|
371
|
-
|
372
|
-
credentials = {:username => username, :password => password}
|
373
|
-
|
374
|
-
if valid_github_username_and_pass?(credentials[:username], credentials[:password])
|
375
|
-
return credentials
|
376
|
-
else
|
377
|
-
return false
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
# Get's the username and password from the user, then authenticates. If it fails, it asks them if they'd like to try again.
|
382
|
-
# Returns false if aborted
|
383
|
-
def self.get_username_and_password_diligently
|
384
|
-
while true
|
385
|
-
credentials = get_username_and_password_and_authenticate
|
386
|
-
if !credentials
|
387
|
-
puts "Could not authenticate, try again?"
|
388
|
-
puts "y/n"
|
389
|
-
|
390
|
-
again = STDIN.gets.strip
|
391
|
-
case again.downcase
|
392
|
-
when "y"
|
393
|
-
when "n"
|
394
|
-
return false
|
395
|
-
end
|
396
|
-
else
|
397
|
-
return credentials
|
207
|
+
pub_path = "#{GAS_DIRECTORY}/#{nickname}_id_rsa.pub"
|
208
|
+
priv_path = "#{GAS_DIRECTORY}/#{nickname}_id_rsa"
|
209
|
+
|
210
|
+
if File.exists? pub_path and File.exists? priv_path
|
211
|
+
pub_file = File.open(pub_path, "rb")
|
212
|
+
pub_rsa = pub_file.read.strip
|
213
|
+
pub_file.close
|
214
|
+
if pub_rsa.count(' ') == 2 # special trick to split off the trailing comment text because github API won't store it.
|
215
|
+
pub_rsa = pub_rsa.split(" ")
|
216
|
+
pub_rsa = "#{rsa[0]} #{rsa[1]}"
|
398
217
|
end
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
def self.valid_github_username_and_pass?(username, password)
|
404
|
-
path = '/user'
|
405
|
-
|
406
|
-
http = Net::HTTP.new(GITHUB_SERVER,443)
|
407
|
-
http.use_ssl = true
|
408
|
-
|
409
|
-
req = Net::HTTP::Get.new(path)
|
410
|
-
req.basic_auth username, password
|
411
|
-
response = http.request(req)
|
412
|
-
|
413
|
-
result = JSON.parse(response.body)["message"]
|
414
|
-
|
415
|
-
return false if result == "Bad credentials"
|
416
|
-
return true
|
417
|
-
end
|
418
|
-
|
419
|
-
|
420
|
-
def self.post_key!(credentials, nickname, rsa)
|
421
|
-
puts "Posting key to GitHub.com..."
|
422
|
-
rsa_key = rsa
|
423
|
-
username = credentials[:username]
|
424
|
-
password = credentials[:password]
|
425
|
-
|
426
|
-
|
427
|
-
# find key...
|
428
|
-
if has_key(username, password, rsa_key)
|
429
|
-
puts "Key already installed."
|
430
|
-
return false
|
431
|
-
end
|
432
|
-
title = "GAS: #{nickname}"
|
433
|
-
install_key(username, password, title, rsa_key)
|
434
|
-
end
|
435
|
-
|
436
|
-
|
437
|
-
def self.remove_key_by_id!(username, password, id)
|
438
|
-
server = 'api.github.com'
|
439
|
-
path = "/user/keys/#{id}"
|
440
|
-
|
441
|
-
|
442
|
-
http = Net::HTTP.new(server,443)
|
443
|
-
http.use_ssl = true
|
444
|
-
req = Net::HTTP::Delete.new(path)
|
445
|
-
req.basic_auth username, password
|
446
|
-
|
447
|
-
response = http.request(req)
|
448
|
-
|
449
|
-
return true if response.body.nil?
|
450
|
-
end
|
451
|
-
|
452
|
-
# Cycles through github, looking to see if rsa exists as a public key, then deletes it if it does
|
453
|
-
def self.has_key(username, password, rsa)
|
454
|
-
# get all keys
|
455
|
-
keys = get_keys(username, password)
|
456
|
-
# loop through arrays checking against 'key'
|
457
|
-
keys.each do |key|
|
458
|
-
if key["key"] == rsa
|
459
|
-
return true
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
return false # key not found
|
464
|
-
end
|
465
|
-
|
218
|
+
|
219
|
+
priv_file = File.open(priv_path, "rb")
|
220
|
+
priv_rsa = priv_file.read.strip
|
221
|
+
priv_file.close
|
466
222
|
|
467
|
-
|
468
|
-
def self.remove_key!(username, password, rsa)
|
469
|
-
# get all keys
|
470
|
-
keys = get_keys(username, password)
|
471
|
-
# loop through arrays checking against 'key'
|
472
|
-
keys.each do |key|
|
473
|
-
if key["key"] == rsa
|
474
|
-
return remove_key_by_id!(username, password, key["id"])
|
475
|
-
end
|
223
|
+
return [pub_rsa, priv_rsa]
|
476
224
|
end
|
477
|
-
|
478
|
-
return false # key not found
|
479
|
-
end
|
480
|
-
|
481
|
-
def self.get_keys(username, password)
|
482
|
-
server = 'api.github.com'
|
483
|
-
path = '/user/keys'
|
484
|
-
|
485
|
-
|
486
|
-
http = Net::HTTP.new(server,443)
|
487
|
-
req = Net::HTTP::Get.new(path)
|
488
|
-
http.use_ssl = true
|
489
|
-
req.basic_auth username, password
|
490
|
-
response = http.request(req)
|
491
|
-
|
492
|
-
return JSON.parse(response.body)
|
493
|
-
end
|
494
|
-
|
495
|
-
|
496
|
-
def self.install_key(username, password, title, rsa_key)
|
497
|
-
server = 'api.github.com'
|
498
|
-
path = '/user/keys'
|
499
|
-
|
500
|
-
http = Net::HTTP.new(server, 443) # 443 for ssl
|
501
|
-
http.use_ssl = true
|
502
|
-
|
503
|
-
req = Net::HTTP::Post.new(path)
|
504
|
-
req.basic_auth username, password
|
505
|
-
req.body = "{\"title\":\"#{title}\", \"key\":\"#{rsa_key}\"}"
|
506
|
-
|
507
|
-
response = http.start {|http| http.request(req) }
|
508
|
-
the_code = response.code
|
509
|
-
|
510
|
-
keys_end = get_keys(username, password).length
|
511
|
-
|
512
|
-
return true if the_code == "201"
|
513
|
-
|
514
|
-
puts "The key you are trying to use already exists in another github user's account. You need to use another key." if the_code == "already_exists"
|
515
|
-
|
516
|
-
# currently.. I think it always returns "already_exists" even if successful. API bug.
|
517
|
-
puts "Something may have gone wrong. Either github fixed their API, or your key couldn't be installed." if the_code != "already_exists"
|
518
|
-
|
519
|
-
#return true if my_hash.key?("errors") # this doesn't work due to it being a buggy API atm # false change me to false when they fix their API
|
520
|
-
puts "Server Response: #{response.body}"
|
521
|
-
return false
|
225
|
+
return [nil, nil]
|
522
226
|
end
|
523
227
|
|
524
|
-
|
525
228
|
# Cross-platform way of finding an executable in the $PATH.
|
526
229
|
# returns nil if command not present
|
527
230
|
#
|
@@ -546,7 +249,7 @@ module Gas
|
|
546
249
|
def self.delete(nickname)
|
547
250
|
return false unless user_has_ssh_keys?(nickname) # return if no keys
|
548
251
|
|
549
|
-
case user_wants_to_delete_all_ssh_data?
|
252
|
+
case Gas::Prompter.user_wants_to_delete_all_ssh_data?
|
550
253
|
when "a"
|
551
254
|
delete_associated_github_keys!(nickname)
|
552
255
|
delete_associated_local_keys!(nickname)
|
@@ -561,21 +264,24 @@ module Gas
|
|
561
264
|
end
|
562
265
|
|
563
266
|
def self.user_has_ssh_keys?(nickname)
|
564
|
-
return false if get_associated_rsa_key(nickname).nil?
|
267
|
+
return false if get_associated_rsa_key(nickname).first.nil?
|
565
268
|
return true
|
566
269
|
end
|
567
270
|
|
568
|
-
|
569
271
|
def self.delete_associated_github_keys!(nickname)
|
570
|
-
rsa = get_associated_rsa_key(nickname)
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
272
|
+
rsa = get_associated_rsa_key(nickname).first
|
273
|
+
|
274
|
+
credentials = get_nils
|
275
|
+
|
276
|
+
github_speaker = GithubSpeaker.new(nickname, credentials[:username], credentials[:password])
|
277
|
+
|
278
|
+
result = github_speaker.remove_key! rsa
|
576
279
|
puts "The key for this user was not in the specified github account's public keys section." if !result
|
577
280
|
end
|
578
|
-
|
281
|
+
|
282
|
+
# this is just for testing... it gets stubbed... otherwise, the nils are normal and allow for
|
283
|
+
# normal prompting for username and password from within the GithubSpeaker class
|
284
|
+
def self.get_nils; { :username => nil, :password => nil };end
|
579
285
|
|
580
286
|
def self.delete_associated_local_keys!(nickname)
|
581
287
|
puts "Removing associated keys from local machine..."
|
@@ -594,37 +300,6 @@ module Gas
|
|
594
300
|
File.delete("#{GAS_DIRECTORY}/#{nickname}_id_rsa")
|
595
301
|
File.delete("#{GAS_DIRECTORY}/#{nickname}_id_rsa.pub")
|
596
302
|
end
|
597
|
-
|
598
|
-
# This is another prompt function, but it returns a more complicated lexicon
|
599
|
-
#
|
600
|
-
# returns "a", "l", "g", or "n"
|
601
|
-
def self.user_wants_to_delete_all_ssh_data?
|
602
|
-
puts "Would you like to remove all ssh keys too!?! (github account keys can be removed as well!)"
|
603
|
-
puts "a: All, the local copy, and checks github too."
|
604
|
-
puts "l: Remove local keys only."
|
605
|
-
puts "g: Removes keys from github.com only."
|
606
|
-
puts "n: Don't remove this users keys."
|
607
|
-
puts "Default: l"
|
608
|
-
|
609
|
-
while true
|
610
|
-
delete_all_keys = STDIN.gets.strip
|
611
|
-
|
612
|
-
case delete_all_keys.downcase
|
613
|
-
when "a"
|
614
|
-
return "a"
|
615
|
-
when "l", ""
|
616
|
-
return "l"
|
617
|
-
when "g"
|
618
|
-
return "g"
|
619
|
-
when "n"
|
620
|
-
return "n"
|
621
|
-
else
|
622
|
-
puts "please use 'a', 'l', 'g' or 'n' for NONE."
|
623
|
-
end
|
624
|
-
end
|
625
|
-
end
|
626
|
-
|
303
|
+
|
627
304
|
end
|
628
|
-
end
|
629
|
-
|
630
|
-
|
305
|
+
end
|