noms-command 0.5.0 → 2.1.1

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.
@@ -3,5 +3,5 @@ class NOMS
3
3
  end
4
4
 
5
5
  class NOMS::Command
6
- VERSION = "0.5.0"
6
+ VERSION = "2.1.1"
7
7
  end
@@ -54,11 +54,29 @@ class NOMS::Command::Window::Console < NOMS::Command::Base
54
54
 
55
55
  # Some implementations have a kind of format string. I don't
56
56
  def log(*items)
57
- @log.debug(items.map { |s| _sanitize(s) }.join(', '))
57
+ @log.debug(items.map { |s| _string(s) }.join(', '))
58
58
  end
59
59
 
60
- def _sanitize(s)
61
- s.respond_to?(:to_str) ? s : s.to_json
60
+ def _string(s)
61
+ s = _sanitize(s)
62
+ s.kind_of?(Enumerable) ? s.to_json : s.inspect
63
+ end
64
+
65
+ # Get rid of V8 stuff
66
+ def _sanitize(thing)
67
+ # This really needs to go into a class
68
+ if thing.kind_of? V8::Array or thing.respond_to? :to_ary
69
+ thing.map do |item|
70
+ _sanitize item
71
+ end
72
+ elsif thing.respond_to? :keys
73
+ Hash[
74
+ thing.keys.map do |key|
75
+ [key, _sanitize(thing[key])]
76
+ end]
77
+ else
78
+ thing
79
+ end
62
80
  end
63
81
 
64
82
  end
@@ -4,8 +4,6 @@ require 'noms/command/urinion'
4
4
  require 'noms/command/useragent'
5
5
  require 'noms/command/error'
6
6
 
7
- require 'httpclient'
8
-
9
7
  class NOMS
10
8
 
11
9
  end
@@ -113,7 +111,7 @@ class NOMS::Command::XMLHttpRequest
113
111
  end
114
112
 
115
113
  def HEADERS_RECEIVED
116
- HEADERS_RECEIVED
114
+ HEADERS_RECEIVED
117
115
  end
118
116
 
119
117
  def LOADING
@@ -154,24 +152,26 @@ class NOMS::Command::XMLHttpRequest
154
152
  self.readyState = OPENED
155
153
  self.readyState = HEADERS_RECEIVED
156
154
  self.readyState = LOADING
157
- @responseText = @response.content
155
+ @responseText = @response.body
158
156
  self.readyState = DONE
159
157
  end
160
158
 
161
159
  def status
162
- @response.status.to_i unless @response.nil?
160
+ @response.status unless @response.nil?
163
161
  end
164
162
 
165
163
  def statusText
166
- @response.status + ' ' + @response.reason unless @response.nil?
164
+ @response.statusText unless @response.nil?
167
165
  end
168
166
 
169
167
  def getResponseHeader(header)
170
- @response.header[header.downcase] unless @response.nil?
168
+ @response.header header unless @response.nil?
171
169
  end
172
170
 
173
171
  def getAllResponseHeaders
174
- lambda { || @response.headers.map { |h, v| "#{h}: #{v}" }.join("\n") + "\n" }
172
+ unless @response.nil?
173
+ lambda { || @response.header.map { |h, v| "#{h}: #{v}" }.join("\n") + "\n" }
174
+ end
175
175
  end
176
176
 
177
177
  def abort()
data/noms-command.gemspec CHANGED
@@ -19,12 +19,14 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.add_runtime_dependency "therubyracer"
21
21
  spec.add_runtime_dependency "mime-types"
22
- spec.add_runtime_dependency "httpclient"
22
+ spec.add_runtime_dependency "typhoeus"
23
23
  spec.add_runtime_dependency "json"
24
24
  spec.add_runtime_dependency "trollop"
25
25
  spec.add_runtime_dependency "highline"
26
+ spec.add_runtime_dependency "bcrypt"
26
27
 
27
28
  spec.add_development_dependency "bundler", "~> 1.7"
28
29
  spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "rspec"
29
31
  spec.add_development_dependency "sinatra"
30
32
  end
data/spec/07js_spec.rb CHANGED
@@ -67,7 +67,7 @@ describe NOMS::Command::Application do
67
67
  app = make_script_app("console.log('test debug output')", :logger => log)
68
68
  app.fetch!
69
69
  app.render!
70
- expect(logcatcher.string).to match(/^D,.*test debug output$/)
70
+ expect(logcatcher.string).to match(/^D,.*test debug output/)
71
71
  end
72
72
 
73
73
  end
data/spec/10auth_spec.rb CHANGED
@@ -2,6 +2,138 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
+ require 'digest/sha1'
6
+
7
+ require 'noms/command/application'
8
+ require 'noms/command/auth'
9
+
10
+ describe NOMS::Command::Auth::Identity do
11
+
12
+ before(:all) do
13
+ setup_fixture
14
+ NOMS::Command::Auth::Identity.identity_dir = 'test/identities'
15
+ File.chmod 0600, 'test/identity'
16
+ FileUtils.rm_r 'test/identities' if File.directory? 'test/identities'
17
+ File.unlink 'test/identities/.noms-vault-key' if File.exist? 'test/identities/.noms-vault-key'
18
+ end
19
+
20
+ after(:all) do
21
+ teardown_fixture
22
+ end
23
+
24
+ before(:each) do
25
+ @identity = NOMS::Command::Auth::Identity.new({ 'id' => 'Authorization+Required=http://localhost:8787/',
26
+ 'data' => 'testdata' })
27
+ identity_file = File.join(NOMS::Command::Auth::Identity.identity_dir, @identity.id_number)
28
+ @vault_keyfile = File.join(NOMS::Command::Auth::Identity.identity_dir, '.noms-vault-key')
29
+ File.unlink "#{identity_file}.json" if File.exist? "#{identity_file}.json"
30
+ File.unlink "#{identity_file}.enc" if File.exist? "#{identity_file}.json"
31
+ File.unlink @vault_keyfile if File.exist? @vault_keyfile
32
+ end
33
+
34
+ describe '.new' do
35
+
36
+ it "should create an identity" do
37
+ identity = NOMS::Command::Auth::Identity.new({'id' => 'Authorization+Required=http://localhost:8787/',
38
+ 'data' => 'testdata' })
39
+ expect(identity).to be_a NOMS::Command::Auth::Identity
40
+ end
41
+
42
+ end
43
+
44
+ describe "#id_number" do
45
+
46
+ it "should return the hash of the identity id" do
47
+ comp_id = Digest::SHA1.new.update(@identity['id']).hexdigest
48
+ expect(@identity.id_number).to eq comp_id
49
+ end
50
+
51
+ end
52
+
53
+ describe "#save" do
54
+
55
+ it "should save the identity in an encrypted file" do
56
+ file = @identity.save
57
+ expect(File.basename(file)).to eq @identity.id_number + '.enc'
58
+ expect(File.exist? file).to be_truthy
59
+ expect(File.read file).to_not match(/Authorization/)
60
+ expect(File.exist? File.join(NOMS::Command::Auth::Identity.identity_dir, '.noms-vault-key')).to be_truthy
61
+ end
62
+
63
+ it "should save unencrypted when directed" do
64
+ file = @identity.save :encrypt => false
65
+ expect(File.basename(file)).to eq @identity.id_number + '.json'
66
+ expect(File.read file).to match(/Authorization/)
67
+ end
68
+
69
+ it "should save in specific file when asked" do
70
+ file = @identity.save :file => 'test/identities/test-identity.json', :encrypt => false
71
+ expect(File.basename(file)).to eq 'test-identity.json'
72
+ expect(File.read file).to match(/Authorization/)
73
+ end
74
+
75
+ it "should not save when from specified file" do
76
+ this_identity = NOMS::Command::Auth::Identity.from 'test/identity'
77
+ file = this_identity.save :file => 'test/identities/test-identity.enc'
78
+ expect(file).to eq 'test/identity'
79
+ end
80
+
81
+ end
82
+
83
+ describe '.saved' do
84
+
85
+ it 'should be false when not saved' do
86
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_falsey
87
+ end
88
+
89
+ it 'should be true when saved' do
90
+ file = @identity.save
91
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_truthy
92
+ end
93
+
94
+ it 'should be false when not decryptable' do
95
+ file = @identity.save
96
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_truthy
97
+
98
+ File.unlink NOMS::Command::Auth::Identity.vault_keyfile
99
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_falsey
100
+ end
101
+
102
+ it 'should be false when too old' do
103
+ file = @identity.save
104
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_truthy
105
+ old_hash = Digest::SHA1.new.update(File.read @vault_keyfile).hexdigest
106
+
107
+ old_ts = Time.now - 24 * 3600
108
+ File.utime(old_ts, old_ts, @vault_keyfile)
109
+ expect(NOMS::Command::Auth::Identity.saved @identity['id']).to be_falsey
110
+ new_hash = Digest::SHA1.new.update(File.read @vault_keyfile).hexdigest
111
+ expect(new_hash).to_not eq old_hash
112
+ end
113
+
114
+ it 'should load an identity' do
115
+ file = @identity.save
116
+
117
+ id_data = NOMS::Command::Auth::Identity.saved @identity['id']
118
+ expect(id_data['id']).to eq @identity['id']
119
+ end
120
+
121
+ it 'should update vault key mtime' do
122
+ file = @identity.save
123
+
124
+ old_ts = Time.now - (5 * 60)
125
+ File.utime(old_ts, old_ts, @vault_keyfile)
126
+
127
+ id_data = NOMS::Command::Auth::Identity.saved @identity['id']
128
+ new_identity = NOMS::Command::Auth::Identity.new(id_data)
129
+ new_ts = File.stat(@vault_keyfile).mtime
130
+ expect(Time.now - new_ts).to be < 5
131
+ end
132
+
133
+ end
134
+
135
+ end
136
+
5
137
  describe "NOMS::Command::Application" do
6
138
 
7
139
  before(:all) do
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'noms/command/useragent'
6
+
7
+ describe 'NOMS::Command::UserAgent' do
8
+ before(:all) do
9
+ setup_fixture
10
+ start_server
11
+ end
12
+
13
+ after(:all) do
14
+ stop_server
15
+ teardown_fixture
16
+ end
17
+
18
+ context 'when caching' do
19
+
20
+ describe '.request' do
21
+
22
+ before(:each) do
23
+ @ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :max_age => 10, :cache => true
24
+ @ua.clear_cache!
25
+ end
26
+
27
+ it 'loads fresh content' do
28
+ response, = @ua.request('GET', 'http://localhost:8787/static/expires-4')
29
+ expect(response.from_cache?).to be_falsey
30
+ generated = get_generated(response)
31
+ expect(Time.now - generated).to be <= 1
32
+ end
33
+
34
+ it 'loads cached content' do
35
+ response0, = @ua.request('GET', 'http://localhost:8787/static/expires-4')
36
+ expect(response0.from_cache?).to be_falsey
37
+ generated0 = get_generated response0
38
+
39
+ sleep 2
40
+ response1, = @ua.request('GET', 'http://localhost:8787/static/expires-4')
41
+ expect(response1.from_cache?).to be_truthy
42
+ generated1 = get_generated response1
43
+
44
+ expect(generated1).to eq generated0
45
+ end
46
+
47
+ it 'refetches cached content' do
48
+ response0, = @ua.request('GET', 'http://localhost:8787/static/expires-4')
49
+ expect(response0.from_cache?).to be_falsey
50
+ generated0 = get_generated response0
51
+
52
+ sleep 5
53
+ response1, = @ua.request('GET', 'http://localhost:8787/static/expires-4')
54
+ expect(response1.from_cache?).to be_falsey
55
+ generated1 = get_generated response1
56
+
57
+ expect(Time.now - generated1).to be <= 1
58
+ end
59
+
60
+ it 'revalidates cached content with last-modified' do
61
+ response0, = @ua.request('GET', 'http://localhost:8787/static/last-modified')
62
+ expect(response0.from_cache?).to be_falsey
63
+ generated0 = get_generated response0
64
+
65
+ sleep 5
66
+ response1, = @ua.request('GET', 'http://localhost:8787/static/last-modified')
67
+ expect(response1.from_cache?).to be_truthy
68
+ generated1 = get_generated response1
69
+
70
+ expect(generated1).to eq generated0
71
+ end
72
+
73
+ it 'revalidates cached content' do
74
+ response0, = @ua.request('GET', 'http://localhost:8787/static/expires-2-constant')
75
+ expect(response0.from_cache?).to be_falsey
76
+ generated0 = get_generated response0
77
+
78
+ sleep 3
79
+ response1, = @ua.request('GET', 'http://localhost:8787/static/expires-2-constant')
80
+ expect(response1.from_cache?).to be_truthy
81
+ generated1 = get_generated response1
82
+
83
+ expect(generated1).to eq generated0
84
+ end
85
+
86
+ it 'refuses to cache longer than :max_age' do
87
+ response0, = @ua.request('GET', 'http://localhost:8787/static/long-cache')
88
+ expect(response0.from_cache?).to be_falsey
89
+ generated0 = get_generated response0
90
+
91
+ sleep 5
92
+ response1, = @ua.request('GET', 'http://localhost:8787/static/long-cache')
93
+ expect(response1.from_cache?).to be_truthy
94
+ generated1 = get_generated response1
95
+
96
+ expect(generated1).to eq generated0
97
+
98
+ sleep 6
99
+ response2, = @ua.request('GET', 'http://localhost:8787/static/long-cache')
100
+ expect(response2.from_cache?).to be_falsey
101
+ generated2 = get_generated response2
102
+
103
+ expect(generated2 - Time.now).to be <= 1
104
+ end
105
+
106
+ it 'refuses to cache when directed' do
107
+ ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :cache => false
108
+ response0, = ua.request('GET', 'http://localhost:8787/static/expires-4')
109
+ expect(response0.from_cache?).to be_falsey
110
+ generated0 = get_generated response0
111
+
112
+ sleep 2
113
+ response1, = ua.request('GET', 'http://localhost:8787/static/expires-4')
114
+ expect(response1.from_cache?).to be_falsey
115
+ generated1 = get_generated response1
116
+
117
+ expect(generated1).to_not eq generated0
118
+ expect(generated0 - Time.now).to be <= 1
119
+ end
120
+
121
+ it 'does not serve cached reply for authenticated pages, when unauthenticated' do
122
+ File.chmod 0600, 'test/identity'
123
+ File.open('test/fail-identity', 'w') do |outfh|
124
+ outfh.write JSON.pretty_generate(File.open('test/identity') { |fh| JSON.load(fh) }.merge({ 'password' => 'FAIL' }))
125
+ end
126
+ File.chmod 0600, 'test/fail-identity'
127
+
128
+ ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :cache => true,
129
+ :specified_identities => ['test/identity']
130
+
131
+ response0, = ua.request('GET', 'http://localhost:8787/auth/cacheable')
132
+ expect(response0.from_cache?).to be_falsey
133
+ generated0 = get_generated response0
134
+
135
+ ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :cache => true,
136
+ :specified_identities => ['test/fail-identity']
137
+ response1, = ua.request('GET', 'http://localhost:8787/auth/cacheable')
138
+ expect(response1.from_cache?).to be_falsey
139
+ expect(response1.status).to eq 401
140
+ end
141
+
142
+ it 'does serve cached reply for authenticated pages, when authenticated' do
143
+ File.chmod 0600, 'test/identity'
144
+ ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :cache => true,
145
+ :specified_identities => ['test/identity']
146
+ response0, = ua.request('GET', 'http://localhost:8787/auth/cacheable')
147
+ expect(response0.from_cache?).to be_falsey
148
+ generated0 = get_generated response0
149
+
150
+ sleep 3
151
+ response1, = ua.request('GET', 'http://localhost:8787/auth/cacheable')
152
+ expect(response1.from_cache?).to be_falsey
153
+ generated1 = get_generated response1
154
+ expect(Time.now - generated1).to be < 1
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'noms/command/useragent'
6
+
7
+ describe NOMS::Command::UserAgent do
8
+
9
+ before(:all) do
10
+ setup_fixture
11
+ start_server
12
+ end
13
+
14
+ after(:all) do
15
+ teardown_fixture
16
+ stop_server
17
+ end
18
+
19
+ context 'when using cookies' do
20
+
21
+ describe '#request' do
22
+
23
+ before(:each) do
24
+ @cookie_jar = File.join(NOMS::Command.home, 'cookies.txt')
25
+ File.unlink @cookie_jar if File.exist? @cookie_jar
26
+ @ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :specified_identities => ['test/identity'],
27
+ :cache => false
28
+ end
29
+
30
+ it 'gets cookie-authorized document' do
31
+ response, = @ua.get 'http://localhost:8787/cookie/home'
32
+ result = JSON.parse(response.body)
33
+ expect(result['cookie_user']).to eq 'testuser'
34
+ end
35
+
36
+ it 'persists cookies between invocations' do
37
+ response0, = @ua.get 'http://localhost:8787/cookie/home'
38
+ result0 = JSON.parse(response0.body)
39
+
40
+ expect(File.exist? @cookie_jar).to be_truthy
41
+
42
+ ua = NOMS::Command::UserAgent.new 'http://localhost:8787/', :cache => false
43
+ response1, = ua.get 'http://localhost:8787/cookie/home'
44
+ result1 = JSON.parse(response1.body)
45
+
46
+ expect(result1).to have_key 'cookie_user'
47
+ expect(result1['cookie_user']).to eq 'testuser'
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ end