clockker 0.1.4 → 0.1.5

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: a5917fe8052498f65072fe075093b1af5d725ea0
4
- data.tar.gz: 0c09c0cbb7b630660b8f0326ba799a5c08fea671
3
+ metadata.gz: c7404b361d1f21b145d39ff872ed9901c19f7944
4
+ data.tar.gz: 7af9d8d18fdbfaf1779250f579a24fa8ef7e57c7
5
5
  SHA512:
6
- metadata.gz: 4c674892ffb7178e58fa8430582014ae8d456e92dce3c303aa344f0e8c53cab6897298638b5b0c58a243beb6f4d8aa821ea0a58d639f3a22b9610d77d7574f2d
7
- data.tar.gz: efe5566b8355c97fc08f2015047aae7450231c39b8001e8658c582488a587afe388bfe75bcc33171b4392dac4936f519be0492c950d97a3e12c36924eff155c4
6
+ metadata.gz: 66432b991bcbd96026f1761bd87211afad2b626e47df12b9627367cb767574ea2eb34f255b58fca4e17c369970e4bcbd7b1327d95f8b0eb981283317d68c7bf8
7
+ data.tar.gz: 69bd52efc272a2fa17ed05893e234b81a533d148548c5a1da5bb1afbd215d84b76fac85fb7adda1775cae0eefe5096ff38de45e084bff90cc106ea06b1e5ece6
data/README.md CHANGED
@@ -8,6 +8,18 @@ Install it with:
8
8
 
9
9
  $ gem install clockker
10
10
 
11
+ To access your Safari history when using macOS Mojave (10.14) and higher, you must give the Terminal app "Full Disk Access".
12
+
13
+ 1. Settings
14
+ 2. Security & Privacy
15
+ 3. Privacy
16
+ 4. Full Disk Access
17
+ 5. <unlock>
18
+ 6. + to add
19
+ 7. Browse to find /Applications/Utilities/Terminal
20
+ 8. Quit and restart Terminal
21
+
22
+
11
23
  ## Usage
12
24
 
13
25
  Run it with:
@@ -68,6 +80,8 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al
68
80
 
69
81
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
70
82
 
83
+ To run a development version run `bundle exec exe/clockker <params>`.
84
+
71
85
  ## Contributing
72
86
 
73
87
  Bug reports and pull requests are welcome on GitHub at https://github.com/liquidmedia/clockker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/clockker.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_dependency 'rb-fsevent', '>= 0.10.2'
34
34
  spec.add_dependency 'thor'
35
+ spec.add_dependency 'sqlite3'
35
36
 
36
37
  spec.add_development_dependency "bundler", "~> 1.15"
37
38
  spec.add_development_dependency "rake", "~> 10.0"
@@ -1,5 +1,5 @@
1
1
  module Clockker
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
 
4
4
  def self.macos_version
5
5
  @mov ||= `sw_vers -productVersion`
@@ -1,6 +1,7 @@
1
1
  require 'rb-fsevent'
2
2
  require 'logger'
3
3
  require 'net/http'
4
+ require 'sqlite3'
4
5
 
5
6
  module Clockker
6
7
  class Watcher
@@ -9,21 +10,33 @@ module Clockker
9
10
 
10
11
  trap "INT" do
11
12
  @fsevent.stop
12
- # @watcher.kill # this also works, but the former is a bit more elegant
13
- @queue << :exit # this shuts down the submitter, first letting it submit its changeset
13
+ @timer.kill # the timer can just go away; it doesn't need a graceful shutdown.
14
+ @safari_watcher_queue << :exit
15
+ @submitter_queue << :exit # this shuts down the submitter, first letting it submit its changeset
14
16
  end
15
17
 
16
18
  white_black_list = WhiteBlackList.new(config)
17
19
 
18
- @queue = Queue.new
19
- @watcher = Thread.new { create_watcher('/', white_black_list, logger) }
20
+ @submitter_queue = Queue.new
21
+ @safari_watcher_queue = Queue.new
22
+ @timer = Thread.new { create_timer(@safari_watcher_queue) }
23
+ @file_watcher = Thread.new { create_file_watcher('/', white_black_list, logger) }
24
+ @safari_watcher = Thread.new { create_safari_watcher(logger) }
20
25
  @submitter = Thread.new { create_submitter(config.submit_frequency, config.region, config.token, config.identifier, logger, config.development) }
21
26
 
22
- @watcher.join
27
+ @file_watcher.join
28
+ @safari_watcher.join
23
29
  @submitter.join
24
30
  end
25
31
 
26
- def create_watcher(dir, white_black_list, logger)
32
+ def create_timer(*queues)
33
+ loop do
34
+ sleep 5
35
+ queues.each {|q| q << :run}
36
+ end
37
+ end
38
+
39
+ def create_file_watcher(dir, white_black_list, logger)
27
40
  @fsevent = FSEvent.new
28
41
  @fsevent.watch dir, {file_events: true} do |directories, event_meta|
29
42
  t = Time.now.utc
@@ -31,9 +44,9 @@ module Clockker
31
44
  event_meta['events'].each do |event|
32
45
  next if white_black_list.ignore?(event['path'])
33
46
  count += 1
34
- @queue << {created_at: t, event_id: event['id'], filepath: event['path'], flags: event['flags']}
47
+ @submitter_queue << {touched_at: t, contents: event['path'], type: "file", metadata: {flags: event['flags'], id: event['id']}}
35
48
  end
36
- logger.debug "#{Time.now} checked #{event_meta['numEvents']} events and added #{count} to the queue"
49
+ logger.debug "#{Time.now} checked #{event_meta['numEvents']} events and added #{count} to the submitter_queue"
37
50
  end
38
51
  logger.info "#{Time.now} now watching /"
39
52
  logger.info "#{Time.now} whitelist paths: #{white_black_list.whitelist}"
@@ -42,8 +55,50 @@ module Clockker
42
55
  logger.info "#{Time.now} fswatcher done"
43
56
  end
44
57
 
45
- def create_submitter(submit_frequency, region, token, identifier, logger, development)
46
- logger.info "#{Time.now} submitting to clockk.com #{"and localhost:4000 " if development}every #{submit_frequency} seconds with token #{token} from identifier #{identifier} with version #{Clockker.version}"
58
+ def create_safari_watcher(logger)
59
+ safari_db = SQLite3::Database.new(File.expand_path("~/Library/Safari/History.db"))
60
+ logger.info "#{Time.now} now watching Safari"
61
+ last_time = Time.now.to_i - 978307200 # convert to macOS Core Data time
62
+ loop do
63
+ submit_now = false
64
+ exit_now = false
65
+
66
+ value = @safari_watcher_queue.pop
67
+ case value
68
+ when :exit
69
+ submit_now = true
70
+ exit_now = true
71
+ when :run
72
+ # we just move forward
73
+ else
74
+ # On the off chance the message isn't :run
75
+ end
76
+
77
+ safari_db.execute("
78
+ SELECT hv.id, datetime(hv.visit_time+978307200, \"unixepoch\") as visited_at, hv.visit_time, hv.title, hi.url
79
+ FROM history_visits hv, history_items hi
80
+ WHERE hv.history_item=hi.id
81
+ AND hv.visit_time > #{last_time}
82
+ ORDER BY hv.visit_time ASC
83
+ ") do |row|
84
+ id, visited_at, visit_time, title, url = row
85
+ visited_at = Time.parse(visited_at+"Z") # the time is already UTC; let's make doubly sure!
86
+ # TODO check the whitelisted domain regexes to see if we can submit this one.
87
+ logger.info " - #{visited_at} - #{url} - #{title}"
88
+ @submitter_queue << {touched_at: visited_at, contents: url, type: "url", metadata: {title: title}}
89
+ last_time = visit_time
90
+ end
91
+
92
+ if exit_now
93
+ logger.info "#{Time.now} Safari watcher preparing to exit"
94
+ break
95
+ end
96
+ end
97
+ logger.info "#{Time.now} Safari watcher done"
98
+ end
99
+
100
+ def create_submitter(submit_frequency, region, token, identifier, logger, dev_mode)
101
+ logger.info "#{Time.now} submitting to clockk.com #{"and localhost:4000 " if dev_mode}every #{submit_frequency} seconds with token #{token} from identifier #{identifier} with version #{Clockker.version}"
47
102
  t_start = Time.now
48
103
  clockk_agent_uri = URI("https://#{region}.clockk.io/api/v1/agent/artifacts")
49
104
  clockk_local_uri = URI("http://localhost:4000/api/v1/agent/artifacts")
@@ -52,7 +107,7 @@ module Clockker
52
107
  submit_now = false
53
108
  exit_now = false
54
109
 
55
- value = @queue.pop
110
+ value = @submitter_queue.pop
56
111
  case value
57
112
  when :submit
58
113
  submit_now = true
@@ -68,29 +123,38 @@ module Clockker
68
123
  end
69
124
 
70
125
  if exit_now
71
- logger.info "#{Time.now} preparing to exit"
126
+ logger.info "#{Time.now} Submitter preparing to exit"
72
127
  end
73
128
 
74
- if submit_now
129
+ if submit_now && @changeset.length > 0
75
130
  logger.info "#{Time.now} submitting #{@changeset.length} items"
76
131
  @changeset.each_with_index do |cs, idx|
77
- logger.info " - #{idx} - #{cs[:created_at].strftime("%H:%M:%S")} #{cs[:filepath]}"
132
+ logger.info " - #{idx} - #{cs[:touched_at].strftime("%H:%M:%S")} #{cs[:contents]}"
78
133
  end
79
134
 
80
135
  begin
81
- data = {artifacts: @changeset.map{|c| {file_path: c[:filepath], touched_at: c[:created_at].strftime("%Y-%m-%d %H:%M:%S"), identifier: identifier, agent: Clockker.version}}}.to_json
136
+ dev_data = {artifacts: @changeset.map{|c| {contents: c[:contents], touched_at: c[:touched_at].strftime("%Y-%m-%d %H:%M:%S"), type: c[:type], metadata: c[:metadata], identifier: identifier, agent: Clockker.version}}}.to_json
137
+
138
+ # temporarily we're keeping the old data structure, until all of our APIs are up to date.
139
+ prod_data = @changeset.find_all{|c| c[:type] == "file"}
140
+ prod_data = {artifacts: prod_data.map{|c| {file_path: c[:contents], touched_at: c[:touched_at].strftime("%Y-%m-%d %H:%M:%S"), identifier: identifier, agent: Clockker.version}}}.to_json
141
+
82
142
  header = {"Authorization" => "Bearer #{token}", "Content-Type" => "application/json"}
83
143
 
144
+ # logger.info "PROD submission: #{prod_data.inspect}"
84
145
  Net::HTTP.start(clockk_agent_uri.hostname, clockk_agent_uri.port, use_ssl: clockk_agent_uri.scheme == 'https') do |http|
85
- http.post(clockk_agent_uri.path, data, header)
146
+ http.post(clockk_agent_uri.path, prod_data, header)
86
147
  end
87
148
 
88
- begin
89
- Net::HTTP.start(clockk_local_uri.hostname, clockk_local_uri.port, use_ssl: clockk_local_uri.scheme == 'https') do |http|
90
- http.post(clockk_local_uri.path, data, header)
149
+ if dev_mode
150
+ begin
151
+ # logger.info "DEV submission: #{dev_data.inspect}"
152
+ Net::HTTP.start(clockk_local_uri.hostname, clockk_local_uri.port, use_ssl: clockk_local_uri.scheme == 'https') do |http|
153
+ http.post(clockk_local_uri.path, dev_data, header)
154
+ end
155
+ rescue Exception => q
156
+ logger.info "#{Time.now} Failed to reach localhost:4000; ignoring"
91
157
  end
92
- rescue Exception => q
93
- logger.info "#{Time.now} Failed to reach localhost:4000; ignoring"
94
158
  end
95
159
 
96
160
  @changeset = []
@@ -102,7 +166,7 @@ module Clockker
102
166
  end
103
167
 
104
168
  if exit_now
105
- logger.info "#{Time.now} exiting"
169
+ logger.info "#{Time.now} Submitter done"
106
170
  break
107
171
  end
108
172
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clockker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Doerwald
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-02 00:00:00.000000000 Z
11
+ date: 2018-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb-fsevent
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement