onetime 0.3.1 → 0.4.0
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/CHANGES.txt +8 -0
- data/README.md +53 -5
- data/VERSION.yml +2 -2
- data/bin/onetime +91 -25
- data/lib/onetime/api.rb +9 -3
- data/onetime.gemspec +8 -3
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
ONETIME, CHANGES
|
2
2
|
|
3
|
+
#### 0.4.0 (2012-01-07) ###############################
|
4
|
+
|
5
|
+
* ADDED: Support for ttl, passphrase, and email recipient
|
6
|
+
* ADDED: Better error handling
|
7
|
+
* CHANGED: env variable ONETIME_ACCOUNT -> ONETIME_CUSTID
|
8
|
+
* CHANGED: global option -u is now -H
|
9
|
+
|
10
|
+
|
3
11
|
#### 0.3.1 (2012-01-06) ###############################
|
4
12
|
|
5
13
|
* FIXED: Added httparty to gemspec dependencies
|
data/README.md
CHANGED
@@ -2,27 +2,75 @@
|
|
2
2
|
|
3
3
|
**Keep sensitive info out of your chat logs & email.**
|
4
4
|
|
5
|
-
|
5
|
+
## Basic Usage ##
|
6
6
|
|
7
|
+
Use `onetime` to share something you know (a secret phrase, a special link, etc) or to generate a secret (e.g. a temporary password).
|
8
|
+
|
9
|
+
### onetime share ###
|
10
|
+
|
11
|
+
You can pipe it:
|
12
|
+
|
7
13
|
$ echo "I STILL WATCH NIGHT COURT." | onetime
|
8
|
-
|
14
|
+
https://onetimesecret.com/secret/mc5o2649tva6885wvyspm0flobsasin
|
15
|
+
|
16
|
+
You can type it:
|
17
|
+
|
9
18
|
$ onetime
|
10
19
|
Paste secret here (hit control-D to continue):
|
11
20
|
I STILL WATCH NIGHT COURT.
|
12
21
|
https://onetimesecret.com/secret/3djys3b7tridrcvbiprqjejz0c2g07x
|
22
|
+
|
23
|
+
And you can read from a file:
|
13
24
|
|
25
|
+
$ <path/2/file onetime
|
26
|
+
https://onetimesecret.com/secret/8f8k3ajhax87ctln3h6y11nsb4vf0wq
|
14
27
|
|
28
|
+
*Note that we don't use `cat` in that example! We don't want to provoke the [ire of Randal L. Schwartz](http://partmaps.org/era/unix/award.html).*
|
29
|
+
|
30
|
+
|
31
|
+
### onetime generate ###
|
15
32
|
|
16
|
-
|
33
|
+
$ onetime generate
|
34
|
+
Your secret: CttenFwzVpjs
|
35
|
+
https://onetimesecret.com/secret/er5djg1wodsp5m32oyym489bnuhsfp6
|
36
|
+
|
37
|
+
|
38
|
+
## Output Format ##
|
39
|
+
|
40
|
+
`onetime` also supports YAML, JSON, and to a limited extent CSV outputs. Specify the format using the `-f ` global option:
|
41
|
+
|
42
|
+
$ onetime -f yaml generate
|
43
|
+
---
|
44
|
+
value: MhYcuge9VxtX
|
45
|
+
metadata_key: 4j1122kpd6clemp80gpobu9xfxsp7zu
|
46
|
+
secret_key: 8f8k3ajhax87ctln3h6y11nsb4vf0wq
|
47
|
+
ttl: 172800
|
48
|
+
passphrase_required: false
|
49
|
+
|
50
|
+
## Installation ###
|
17
51
|
|
18
52
|
$ [sudo] gem install onetime
|
19
53
|
|
20
|
-
|
54
|
+
## More Info ##
|
21
55
|
|
22
56
|
* [API docs](https://onetimesecret.com/docs/api)
|
23
57
|
* [Codes](https://github.com/onetimesecret/onetime-ruby)
|
24
58
|
* [Rubgems](https://rubygems.org/gems/onetime)
|
59
|
+
* [One-Time Secret](https://onetimesecret.com/)
|
60
|
+
|
61
|
+
See also:
|
62
|
+
|
63
|
+
$ onetime -h
|
64
|
+
$ onetime show-commands
|
65
|
+
$ onetime share -h
|
66
|
+
$ onetime generate -h
|
67
|
+
|
68
|
+
## Thanks ##
|
69
|
+
|
70
|
+
* Kyle Dawkins for the [perl lib](https://github.com/quile/onetime-perl)
|
71
|
+
* Drew Carey for [tweeting about us](https://twitter.com/DrewFromTV/status/142730130689761280)
|
72
|
+
|
25
73
|
|
26
|
-
|
74
|
+
## License ##
|
27
75
|
|
28
76
|
See LICENSE.txt
|
data/VERSION.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
:MAJOR: 0
|
2
|
-
:MINOR:
|
3
|
-
:PATCH:
|
2
|
+
:MINOR: 4
|
3
|
+
:PATCH: 0
|
data/bin/onetime
CHANGED
@@ -12,9 +12,9 @@ class Onetime::CLI
|
|
12
12
|
|
13
13
|
default :share
|
14
14
|
|
15
|
+
global :H, String, "Base URI (e.g. https://onetimesecret.com/api)"
|
15
16
|
global :c, :custid, String, "Customer ID (e.g. you@yourcompany.com)"
|
16
17
|
global :k, :apikey, String, "API key (e.g. 4eb33c6340006d6607c813fc7e707a32f8bf5342)"
|
17
|
-
global :u, :uri, String, "Base URI (e.g. https://onetimesecret.com/api)"
|
18
18
|
|
19
19
|
global :f, :format, String, "Output format (json or yaml)"
|
20
20
|
global :j, :json, "Shorthand for -f json"
|
@@ -30,6 +30,7 @@ class Onetime::CLI
|
|
30
30
|
end
|
31
31
|
|
32
32
|
before do |obj|
|
33
|
+
OT::API.base_uri obj.global.H if obj.global.H
|
33
34
|
@api = OT::API.new obj.global.custid, obj.global.apikey
|
34
35
|
obj.global.format = 'yaml' if obj.global.yaml
|
35
36
|
obj.global.format = 'json' if obj.global.json
|
@@ -45,39 +46,71 @@ class Onetime::CLI
|
|
45
46
|
after do |obj|
|
46
47
|
case obj.global.format
|
47
48
|
when 'json'
|
48
|
-
puts @
|
49
|
+
puts @res.to_json
|
49
50
|
when 'yaml'
|
50
|
-
puts @
|
51
|
+
puts @res.to_yaml
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
55
|
+
usage "onetime status"
|
54
56
|
command :status do |obj|
|
55
|
-
@
|
57
|
+
@res = @api.get '/status'
|
58
|
+
if @res.nil?
|
59
|
+
raise RuntimeError, 'Could not complete request'
|
60
|
+
elsif @api.response.code != 200
|
61
|
+
raise RuntimeError, @res['message']
|
62
|
+
end
|
56
63
|
unless obj.global.format
|
57
|
-
|
64
|
+
msg = @api.anonymous ? 'Anonymous' : @api.custid
|
65
|
+
STDERR.puts '# Host: %s' % OT::API.base_uri
|
66
|
+
STDERR.puts '# Account: %s' % msg
|
67
|
+
puts 'Service Status: %s' % @res[:status]
|
58
68
|
end
|
59
69
|
end
|
60
70
|
|
61
71
|
argv :key
|
72
|
+
usage "onetime metadata <KEY>"
|
62
73
|
command :metadata do |obj|
|
63
74
|
raise RuntimeError, "csv not supported" if obj.global.format == 'csv'
|
64
75
|
raise RuntimeError, "Usage: #{$0} metadata <KEY>" unless obj.argv.key
|
65
|
-
@
|
76
|
+
@res = @api.post '/metadata/%s' % obj.argv.key
|
77
|
+
if @res.nil?
|
78
|
+
raise RuntimeError, 'Could not complete request'
|
79
|
+
elsif @api.response.code != 200
|
80
|
+
raise RuntimeError, @res['message']
|
81
|
+
end
|
66
82
|
unless obj.global.format
|
67
|
-
puts @
|
83
|
+
puts @res.to_yaml
|
68
84
|
end
|
69
85
|
end
|
70
86
|
|
87
|
+
option :p, :passphrase, String, "Passphrase to decrypt the secret (only required if one was provided to you)"
|
71
88
|
argv :key
|
89
|
+
usage "onetime secret <KEY>"
|
90
|
+
usage "onetime secret [-p PASSPHRASE] <KEY>"
|
72
91
|
command :secret do |obj|
|
73
92
|
raise RuntimeError, "csv not supported" if obj.global.format == 'csv'
|
74
93
|
raise RuntimeError, "Usage: #{$0} secret <KEY>" unless obj.argv.key
|
75
|
-
|
94
|
+
opts = {}
|
95
|
+
opts[:passphrase] = obj.option.passphrase if obj.option.passphrase
|
96
|
+
@res = @api.post '/secret/%s' % [obj.argv.key], opts
|
97
|
+
if @res.nil?
|
98
|
+
raise RuntimeError, 'Could not complete request'
|
99
|
+
elsif @api.response.code != 200
|
100
|
+
raise RuntimeError, @res['message']
|
101
|
+
end
|
76
102
|
unless obj.global.format
|
77
|
-
puts @
|
103
|
+
puts @res.to_yaml
|
78
104
|
end
|
79
105
|
end
|
80
106
|
|
107
|
+
usage "onetime share"
|
108
|
+
usage "onetime share [-t 3600] [-p PASSPHRASE]"
|
109
|
+
usage "echo 'your secret' | onetime share"
|
110
|
+
usage "<path/2/file onetime share"
|
111
|
+
option :t, :ttl, Integer, "Time-to-live in seconds"
|
112
|
+
option :p, :passphrase, String, "Passphrase to encrypt the secret (something only you and recipient know)"
|
113
|
+
option :r, :recipient, Array, "Email address to deliver the secret link"
|
81
114
|
command :share do |obj|
|
82
115
|
begin
|
83
116
|
if Kernel.select [$stdin], nil, nil, 0
|
@@ -85,39 +118,72 @@ class Onetime::CLI
|
|
85
118
|
else
|
86
119
|
STDERR.puts "Paste secret here (hit control-D to continue):"
|
87
120
|
secret_value = ARGF.read
|
88
|
-
STDERR.puts
|
121
|
+
STDERR.puts # new line to let the person know we got it.
|
89
122
|
end
|
90
123
|
rescue Interrupt => ex
|
91
124
|
puts "Exiting..."
|
92
125
|
exit 0
|
93
126
|
end
|
94
127
|
raise RuntimeError, "No secret provided" if secret_value.chomp.empty?
|
95
|
-
|
96
|
-
|
128
|
+
opts = { :secret => secret_value, :ttl => obj.option.ttl, :recipient => obj.option.recipient }
|
129
|
+
opts[:passphrase] = obj.option.passphrase if obj.option.passphrase
|
130
|
+
@res = @api.post '/share', opts
|
131
|
+
if @res.nil?
|
132
|
+
raise RuntimeError, 'Could not complete request'
|
133
|
+
elsif @api.response.code != 200
|
134
|
+
raise RuntimeError, @res['message']
|
135
|
+
end
|
136
|
+
uri = OT::API.web_uri('secret', @res[:secret_key])
|
97
137
|
if obj.global.format == 'csv' || obj.global.format.nil?
|
98
|
-
|
138
|
+
if @res[:recipient] && !@res[:recipient].compact.empty?
|
139
|
+
STDERR.puts '# Secret link sent to: %s' % @res[:recipient].join(',')
|
140
|
+
else
|
141
|
+
puts uri
|
142
|
+
end
|
99
143
|
end
|
100
144
|
end
|
101
145
|
|
146
|
+
usage "onetime generate"
|
147
|
+
usage "onetime generate [-t 3600] [-p PASSPHRASE]"
|
148
|
+
option :t, :ttl, Integer, "Time-to-live in seconds"
|
149
|
+
option :p, :passphrase, String, "Passphrase to encrypt the secret (something only you and recipient know)"
|
150
|
+
option :r, :recipient, Array, "Email address to deliver the secret link"
|
102
151
|
command :generate do |obj|
|
103
|
-
|
104
|
-
|
105
|
-
|
152
|
+
opts = { :ttl => obj.option.ttl, :recipient => obj.option.recipient }
|
153
|
+
opts[:passphrase] = obj.option.passphrase if obj.option.passphrase
|
154
|
+
@res = @api.post '/generate', opts
|
155
|
+
if @res.nil?
|
156
|
+
raise RuntimeError, 'Could not complete request'
|
157
|
+
elsif @api.response.code != 200
|
158
|
+
raise RuntimeError, @res['message']
|
159
|
+
end
|
160
|
+
uri, secret_value = OT::API.web_uri('secret', @res[:secret_key]), @res[:value]
|
161
|
+
STDERR.puts @res.inspect if obj.global.debug
|
106
162
|
if obj.global.format == 'csv'
|
107
163
|
puts [secret_value,uri].join ','
|
108
164
|
elsif obj.global.format.nil?
|
109
165
|
msg = 'Your secret (hit return to continue): %s' % secret_value
|
166
|
+
if @res[:recipient] && !@res[:recipient].compact.empty?
|
167
|
+
uri = "\e[K\r# Secret link sent to: %s" % [@res[:recipient].join(',').ljust(40, ' ')]
|
168
|
+
end
|
110
169
|
eraser = "\e[K\r%s" % [uri] # \e[K\r
|
111
170
|
print msg
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
171
|
+
# Check for tty b/c if we're receiving data via STDIN, even if
|
172
|
+
# we're ignoring it, the stty commands return "stdin isn't a terminal"
|
173
|
+
if STDIN.tty?
|
174
|
+
begin
|
175
|
+
old_stty = `stty -g` # store tty settings
|
176
|
+
system "stty -echo"
|
177
|
+
STDIN.getc
|
178
|
+
rescue Interrupt
|
179
|
+
ensure
|
180
|
+
system "stty echo"
|
181
|
+
system "stty #{old_stty}" # restore stty settings
|
182
|
+
print eraser
|
183
|
+
end
|
184
|
+
else
|
185
|
+
puts
|
186
|
+
print uri
|
121
187
|
end
|
122
188
|
puts
|
123
189
|
end
|
data/lib/onetime/api.rb
CHANGED
@@ -51,7 +51,7 @@ module Onetime
|
|
51
51
|
base_uri 'https://onetimesecret.com/api'
|
52
52
|
format :json
|
53
53
|
headers 'X-Onetime-Client' => Onetime::API::VERSION.to_s
|
54
|
-
attr_reader :opts, :response, :custid, :key, :default_params
|
54
|
+
attr_reader :opts, :response, :custid, :key, :default_params, :anonymous
|
55
55
|
attr_accessor :apiversion
|
56
56
|
def initialize custid=nil, key=nil, opts={}
|
57
57
|
unless ENV['ONETIME_HOST'].to_s.empty?
|
@@ -60,9 +60,15 @@ module Onetime
|
|
60
60
|
@apiversion = opts.delete(:apiversion) || opts.delete('apiversion') || 1
|
61
61
|
@opts = opts
|
62
62
|
@default_params = {}
|
63
|
-
@custid = custid || ENV['
|
63
|
+
@custid = custid || ENV['ONETIME_CUSTID']
|
64
64
|
@key = key || ENV['ONETIME_APIKEY']
|
65
|
-
|
65
|
+
if @custid.to_s.empty? && @key.to_s.empty?
|
66
|
+
@anonymous = true
|
67
|
+
elsif @custid.to_s.empty? || @key.to_s.empty?
|
68
|
+
raise RuntimeError, "You provided a custid without an apikey" if @key.to_s.empty?
|
69
|
+
raise RuntimeError, "You provided an apikey without a custid" if @custid.to_s.empty?
|
70
|
+
else
|
71
|
+
@anonymous = false
|
66
72
|
opts[:basic_auth] ||= { :username => @custid, :password => @key }
|
67
73
|
end
|
68
74
|
end
|
data/onetime.gemspec
CHANGED
@@ -5,20 +5,22 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "onetime"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Delano Mandelbaum"]
|
12
|
-
s.date = "2012-01-
|
12
|
+
s.date = "2012-01-07"
|
13
13
|
s.description = "CLI tool and Ruby library for onetimesecret.com"
|
14
14
|
s.email = "delano@onetimesecret.com"
|
15
15
|
s.executables = ["onetime"]
|
16
16
|
s.extra_rdoc_files = [
|
17
|
-
"LICENSE.txt"
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.md"
|
18
19
|
]
|
19
20
|
s.files = [
|
20
21
|
"CHANGES.txt",
|
21
22
|
"LICENSE.txt",
|
23
|
+
"README.md",
|
22
24
|
"Rakefile",
|
23
25
|
"VERSION.yml",
|
24
26
|
"bin/onetime",
|
@@ -36,13 +38,16 @@ Gem::Specification.new do |s|
|
|
36
38
|
|
37
39
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
38
40
|
s.add_runtime_dependency(%q<drydock>, [">= 0.6.9"])
|
41
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0.7.7"])
|
39
42
|
s.add_runtime_dependency(%q<json>, [">= 1.6.4"])
|
40
43
|
else
|
41
44
|
s.add_dependency(%q<drydock>, [">= 0.6.9"])
|
45
|
+
s.add_dependency(%q<httparty>, [">= 0.7.7"])
|
42
46
|
s.add_dependency(%q<json>, [">= 1.6.4"])
|
43
47
|
end
|
44
48
|
else
|
45
49
|
s.add_dependency(%q<drydock>, [">= 0.6.9"])
|
50
|
+
s.add_dependency(%q<httparty>, [">= 0.7.7"])
|
46
51
|
s.add_dependency(%q<json>, [">= 1.6.4"])
|
47
52
|
end
|
48
53
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: onetime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Delano Mandelbaum
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-07 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: drydock
|