fue 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61e751b27876661073781594e4e2453f29775ece
4
- data.tar.gz: 2072ed4777de7041e92388e47b370a562743c10c
3
+ metadata.gz: bdf4e815c9a0ac53a054f3f8253b877910128fc4
4
+ data.tar.gz: 1d54bdfb1a79ae4709f3762a58599082826c5c8a
5
5
  SHA512:
6
- metadata.gz: 7bb5e6dbe47b597282085d695d4b1da2a434f200425661ada1088d1dfac7e79899c04f02360931e1df08b14617e3ee98deb78626942bf6f315dcf2870966df95
7
- data.tar.gz: 2e9a9fc434871489eb5d2ae86dfe9f2b8e42c91d52e1e9c278568001ab5ae9150289ca6927f301d656670b413ead461a35ac331168cb14e9a2088ded9aee520c
6
+ metadata.gz: 9d5a73a9249125d4fad2f69a0f0b54cc9af5a1ed5be94d635c13245f27d07357cd7b2b4b0b59315aaf1997d35c522c7c4e5f74516160b4a1823cca235ff677eb
7
+ data.tar.gz: 7f506c0f889ddd23e6817828a10358343895b0d73cd3780304a52cf414449ff2039eb12f7ae433170ea64167fc5e1cb1a0e24f3e3b45b7fe0fb443bdd530a4eb
@@ -1,3 +1,8 @@
1
+ ### 0.2.1 (2018/8/23)
2
+
3
+ * [#2](https://github.com/dblock/fue/issues/2): Prompt to authenticate with Github - [@dblock](https://github.com/dblock).
4
+ * [#7](https://github.com/dblock/fue/issues/7): Display version - [@dblock](https://github.com/dblock).
5
+
1
6
  ### 0.2.0 (2018/8/22)
2
7
 
3
8
  * [#6](https://github.com/dblock/fue/issues/6): Configure max depth and breadth separately - [@dblock](https://github.com/dblock).
data/README.md CHANGED
@@ -16,16 +16,12 @@ Fue is short for "Finding Unicorn Engineers".
16
16
  gem install fue
17
17
  ```
18
18
 
19
- #### Get a Github Access Token
20
-
21
- Obtain a Github access token from [here](https://github.com/settings/tokens) with `public_repo` permissions. See [help](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) for more information. Set the token as `GITHUB_ACCESS_TOKEN`.
22
-
23
19
  #### Find Someone's Email
24
20
 
25
21
  The `find` command looks through user's initial repo commits.
26
22
 
27
23
  ```
28
- GITHUB_ACCESS_TOKEN=token fue find defunkt
24
+ $ fue find defunkt
29
25
 
30
26
  Chris Wanstrath <chris@ozmm.org>
31
27
  Chris Wanstrath <chris@github.com>
@@ -36,7 +32,7 @@ Chris Wanstrath <chris@github.com>
36
32
  By default the code looks at 1 commit from the last 10 repos. You can look at more repositories (breadth) and more commits (depth). The maximum value for depth is 100, enforced by Github. Fue will iterate over a number of repositories larger than 100.
37
33
 
38
34
  ```
39
- GITHUB_ACCESS_TOKEN=token fue find --breadth=100 --depth=5 defunkt
35
+ $ fue find --breadth=100 --depth=5 defunkt
40
36
 
41
37
  Chris Wanstrath <chris@ozmm.org>
42
38
  Chris Wanstrath <chris@github.com>
@@ -51,6 +47,21 @@ fue help
51
47
 
52
48
  Displays additional options.
53
49
 
50
+ #### Access Tokens
51
+
52
+ Fue will prompt you for Github credentials and 2FA, if enabled.
53
+
54
+ ```
55
+ $ fue find defunkt
56
+ Enter dblock's GitHub password (never stored): ******************
57
+ Enter GitHub 2FA code: ******
58
+ Token saved to keychain.
59
+ ```
60
+
61
+ The access token will be generated with `public_repo` scope and stored in the keychain. It can be later deleted from [here](https://github.com/settings/tokens). You can also skip the prompts and use a previously obtained token with `-t` or by setting the `GITHUB_ACCESS_TOKEN` environment variable.
62
+
63
+ See [Creating a Personal Access Token for the Command Line](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) for more information about personal tokens.
64
+
54
65
  ## Contributing
55
66
 
56
67
  There're [a few feature requests and known issues](https://github.com/dblock/fue/issues). Please contribute! See [CONTRIBUTING](CONTRIBUTING.md).
data/bin/fue CHANGED
@@ -1,22 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'gli'
3
3
  require 'fue'
4
- require 'graphlient'
5
4
 
6
5
  class App
7
6
  extend GLI::App
8
7
 
9
8
  program_desc "Find a Github user's e-mail address."
9
+ version Fue::VERSION
10
10
 
11
11
  switch %i[v verbose], desc: 'Produce verbose output.', default_value: false
12
12
  flag %i[t token], desc: 'Github access token.', default_value: ENV['GITHUB_ACCESS_TOKEN']
13
+ flag %i[u username], desc: 'Guthub username.', default_value: Fue::Auth.username
13
14
 
14
15
  arguments :strict
15
16
  subcommand_option_handling :normal
16
17
 
17
18
  pre do |global_options, _command, options, _args|
18
19
  options = global_options.dup
19
- token = options.delete(:token)
20
+ token = options.delete(:token) || Fue::Auth.token
20
21
  $fue = Fue::Finder.new(token, options)
21
22
  end
22
23
 
data/lib/fue.rb CHANGED
@@ -1,2 +1,9 @@
1
+ require 'graphlient'
2
+ require 'github_api'
3
+ require 'open3'
4
+ require 'English'
5
+
1
6
  require 'fue/version'
2
7
  require 'fue/finder'
8
+ require 'fue/security'
9
+ require 'fue/auth'
@@ -0,0 +1,97 @@
1
+ module Fue
2
+ module Auth
3
+ class << self
4
+ def token
5
+ stored_options = { username: username, server: 'github.com', label: 'fue' }
6
+ stored_token = Fue::Security.get(stored_options)
7
+ unless stored_token
8
+ stored_token = github_token
9
+ Fue::Security.store!(stored_options.merge(password: stored_token))
10
+ puts 'Token saved to keychain.'
11
+ end
12
+ stored_token
13
+ end
14
+
15
+ def username
16
+ @username ||= begin
17
+ username = `git config github.user`.chomp
18
+ username = get_username if username.empty?
19
+ username
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def github_token(code = nil)
26
+ github(code).auth.create(scopes: ['public_repo'], note: note).token
27
+ rescue Github::Error::Unauthorized => e
28
+ case e.response_headers['X-GitHub-OTP']
29
+ when /required/ then
30
+ github_token(get_code)
31
+ else
32
+ raise e
33
+ end
34
+ rescue Github::Error::UnprocessableEntity => e
35
+ raise e, 'A fue token already exists! Please revoke all previously-generated fue personal access tokens at https://github.com/settings/tokens.'
36
+ end
37
+
38
+ def password
39
+ @password ||= get_password
40
+ end
41
+
42
+ def note
43
+ "Fui (https://github.com/dblock/fue) on #{Socket.gethostname}"
44
+ end
45
+
46
+ def github(code = nil)
47
+ Github.new do |config|
48
+ config.basic_auth = [username, password].join(':')
49
+ if code
50
+ config.connection_options = {
51
+ headers: {
52
+ 'X-GitHub-OTP' => code
53
+ }
54
+ }
55
+ end
56
+ end
57
+ end
58
+
59
+ def get_username
60
+ print 'Enter GithHub username: '
61
+ $stdin.gets.chomp
62
+ rescue Interrupt => e
63
+ raise e, 'ctrl + c'
64
+ end
65
+
66
+ def get_password
67
+ print "Enter #{username}'s GitHub password (never stored): "
68
+ get_secure
69
+ end
70
+
71
+ def get_code
72
+ print 'Enter GitHub 2FA code: '
73
+ get_secure
74
+ end
75
+
76
+ def get_secure
77
+ current_tty = `stty -g`
78
+ system 'stty raw -echo -icanon isig' if $CHILD_STATUS.success?
79
+ input = ''
80
+ while (char = $stdin.getbyte) && !((char == 13) || (char == 10))
81
+ if (char == 127) || (char == 8)
82
+ input[-1, 1] = '' unless input.empty?
83
+ else
84
+ $stdout.write '*'
85
+ input << char.chr
86
+ end
87
+ end
88
+ print "\r\n"
89
+ input
90
+ rescue Interrupt => e
91
+ raise e, 'ctrl + c'
92
+ ensure
93
+ system "stty #{current_tty}" unless current_tty.empty?
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,46 @@
1
+ module Fue
2
+ module Security
3
+ class << self
4
+ def store!(options)
5
+ system!(security('add', options))
6
+ end
7
+
8
+ def get(options)
9
+ system!(security('find', options))
10
+ rescue RuntimeError
11
+ nil
12
+ end
13
+
14
+ private
15
+
16
+ def security(command = nil, options = nil)
17
+ run = [security_path]
18
+ run << "#{command}-internet-password"
19
+ run << "-a #{options[:username]}"
20
+ run << "-s #{options[:server]}"
21
+ if command == 'add'
22
+ run << "-l #{options[:label]}"
23
+ run << '-U'
24
+ run << "-w #{options[:password]}" if options.key?(:password)
25
+ else
26
+ run << '-w'
27
+ end
28
+ run.join ' '
29
+ end
30
+
31
+ def security_path
32
+ @security_path ||= begin
33
+ `which security`.chomp
34
+ rescue StandardError
35
+ 'security'
36
+ end
37
+ end
38
+
39
+ def system!(*cmd)
40
+ stdout, _, status = Open3.capture3(*cmd)
41
+ raise "failed with exit code #{status}" unless status.success?
42
+ stdout.slice!(0..-(1 + $INPUT_RECORD_SEPARATOR.size))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module Fue
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Doubrovkine
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-22 00:00:00.000000000 Z
11
+ date: 2018-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: github_api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: gli
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -51,7 +65,9 @@ files:
51
65
  - README.md
52
66
  - bin/fue
53
67
  - lib/fue.rb
68
+ - lib/fue/auth.rb
54
69
  - lib/fue/finder.rb
70
+ - lib/fue/security.rb
55
71
  - lib/fue/version.rb
56
72
  homepage: http://github.com/dblock/fue
57
73
  licenses: