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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +17 -6
- data/bin/fue +3 -2
- data/lib/fue.rb +7 -0
- data/lib/fue/auth.rb +97 -0
- data/lib/fue/security.rb +46 -0
- data/lib/fue/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdf4e815c9a0ac53a054f3f8253b877910128fc4
|
4
|
+
data.tar.gz: 1d54bdfb1a79ae4709f3762a58599082826c5c8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d5a73a9249125d4fad2f69a0f0b54cc9af5a1ed5be94d635c13245f27d07357cd7b2b4b0b59315aaf1997d35c522c7c4e5f74516160b4a1823cca235ff677eb
|
7
|
+
data.tar.gz: 7f506c0f889ddd23e6817828a10358343895b0d73cd3780304a52cf414449ff2039eb12f7ae433170ea64167fc5e1cb1a0e24f3e3b45b7fe0fb443bdd530a4eb
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
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
|
-
|
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
data/lib/fue/auth.rb
ADDED
@@ -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
|
data/lib/fue/security.rb
ADDED
@@ -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
|
data/lib/fue/version.rb
CHANGED
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.
|
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-
|
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:
|