onetime 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- ### Usage ###
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
- ### Installation ###
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
- ### More Info ###
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
- ### License ###
74
+ ## License ##
27
75
 
28
76
  See LICENSE.txt
@@ -1,3 +1,3 @@
1
1
  :MAJOR: 0
2
- :MINOR: 3
3
- :PATCH: 1
2
+ :MINOR: 4
3
+ :PATCH: 0
@@ -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 @ret.to_json
49
+ puts @res.to_json
49
50
  when 'yaml'
50
- puts @ret.to_yaml
51
+ puts @res.to_yaml
51
52
  end
52
53
  end
53
54
 
55
+ usage "onetime status"
54
56
  command :status do |obj|
55
- @ret = @api.get '/status'
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
- puts @ret[:status]
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
- @ret = @api.post '/metadata/%s' % obj.argv.key
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 @ret.to_yaml
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
- @ret = @api.post '/secret/%s' % obj.argv.key
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 @ret.to_yaml
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 "Generating link..."
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
- @ret = @api.post '/share', :secret => secret_value
96
- uri = OT::API.web_uri('secret', @ret[:secret_key])
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
- puts uri
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
- @ret = @api.post '/generate'
104
- uri, secret_value = OT::API.web_uri('secret', @ret[:secret_key]), @ret[:value]
105
- STDERR.puts @ret.inspect if obj.global.debug
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
- begin
113
- old_stty = `stty -g` # store tty settings
114
- system "stty -echo"
115
- STDIN.getc
116
- rescue Interrupt
117
- ensure
118
- system "stty echo"
119
- system "stty #{old_stty}" # restore stty settings
120
- print eraser
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
@@ -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['ONETIME_ACCOUNT']
63
+ @custid = custid || ENV['ONETIME_CUSTID']
64
64
  @key = key || ENV['ONETIME_APIKEY']
65
- unless @custid.to_s.empty? || @key.to_s.empty?
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
@@ -5,20 +5,22 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "onetime"
8
- s.version = "0.3.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-06"
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.3.1
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-06 00:00:00 Z
13
+ date: 2012-01-07 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: drydock