icfs 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/icfs.rb CHANGED
@@ -11,12 +11,12 @@
11
11
 
12
12
  require 'digest/sha2'
13
13
 
14
+ require_relative 'icfs/validate'
15
+
14
16
  ##########################################################################
15
17
  # Investigative Case File System
16
18
  #
17
19
  # @todo Delete Items and move into this module
18
- # @todo Verification tool written
19
- # @todo Archive/move case tool written
20
20
  #
21
21
  module ICFS
22
22
 
@@ -101,7 +101,6 @@ end # module ICFS::Error
101
101
 
102
102
  end # module ICFS
103
103
 
104
- require_relative 'icfs/validate'
105
104
  require_relative 'icfs/cache'
106
105
  require_relative 'icfs/store'
107
106
  require_relative 'icfs/items'
data/lib/icfs/api.rb CHANGED
@@ -265,12 +265,12 @@ class Api
265
265
  def case_read(cid, lnum=0)
266
266
  if lnum != 0
267
267
  json = @store.case_read(cid, lnum)
268
- return Validate.parse(json, 'case'.freeze, Items::ItemCase)
268
+ return Items.parse(json, 'case'.freeze, Items::ItemCase)
269
269
  end
270
270
 
271
271
  if !@cases.key?(cid)
272
272
  json = @cache.case_read(cid)
273
- cur = Validate.parse(json, 'case'.freeze, Items::ItemCase)
273
+ cur = Items.parse(json, 'case'.freeze, Items::ItemCase)
274
274
  @cases[cid] = cur
275
275
  end
276
276
  return @cases[cid]
@@ -295,7 +295,7 @@ class Api
295
295
 
296
296
  # read
297
297
  json = @cache.log_read(cid, lnum)
298
- return Validate.parse(json, 'log'.freeze, Items::ItemLog)
298
+ return Items.parse(json, 'log'.freeze, Items::ItemLog)
299
299
  end # def log_read()
300
300
 
301
301
 
@@ -313,7 +313,7 @@ class Api
313
313
  # get access list and current entry
314
314
  al = access_list(cid)
315
315
  json = @cache.entry_read(cid, enum)
316
- ec = Validate.parse(json, 'entry'.freeze, Items::ItemEntry)
316
+ ec = Items.parse(json, 'entry'.freeze, Items::ItemEntry)
317
317
 
318
318
  # see if we can read the entry
319
319
  need = Set.new
@@ -330,7 +330,7 @@ class Api
330
330
  return ec
331
331
  else
332
332
  json = @store.entry_read(cid, enum, lnum)
333
- return Validate.parse(json, 'entry'.freeze, Items::ItemEntry)
333
+ return Items.parse(json, 'entry'.freeze, Items::ItemEntry)
334
334
  end
335
335
  end # def entry_read()
336
336
 
@@ -362,7 +362,7 @@ class Api
362
362
  id = '%s.%d'.freeze % [cid, anum]
363
363
  unless @actions.key?(id)
364
364
  json = @cache.action_read(cid, anum)
365
- act = Validate.parse(json, 'action'.freeze, Items::ItemAction)
365
+ act = Items.parse(json, 'action'.freeze, Items::ItemAction)
366
366
  @actions[id] = act
367
367
  end
368
368
  return @actions[id]
@@ -395,7 +395,7 @@ class Api
395
395
  return ac
396
396
  else
397
397
  json = @store.action_read( cid, anum, lnum)
398
- return Validate.parse(json, 'action'.freeze, Items::ItemAction)
398
+ return Items.parse(json, 'action'.freeze, Items::ItemAction)
399
399
  end
400
400
  end # def action_read()
401
401
 
@@ -419,14 +419,14 @@ class Api
419
419
 
420
420
  # read curent index
421
421
  json = @cache.index_read(cid, xnum)
422
- xc = Validate.parse(json, 'index'.freeze, Items::ItemIndex)
422
+ xc = Items.parse(json, 'index'.freeze, Items::ItemIndex)
423
423
 
424
424
  # return the requested version
425
425
  if( lnum == 0 || xc['log'] == lnum )
426
426
  return xc
427
427
  else
428
428
  json = @store.index_read(cid, xnum, lnum)
429
- return Validate.parse(json, 'index'.freeze, Items::ItemIndex)
429
+ return Items.parse(json, 'index'.freeze, Items::ItemIndex)
430
430
  end
431
431
  end # def index_read()
432
432
 
@@ -444,7 +444,7 @@ class Api
444
444
  end
445
445
 
446
446
  json = @cache.current_read(cid)
447
- return Validate.parse(json, 'current'.current, Items::ItemCurrent)
447
+ return Items.parse(json, 'current'.current, Items::ItemCurrent)
448
448
  end # end def current_read()
449
449
 
450
450
 
@@ -476,7 +476,7 @@ class Api
476
476
  # @param query [Hash] a query
477
477
  #
478
478
  def case_search(query)
479
- Validate.validate(query, 'Case Search'.freeze, ValCaseSearch)
479
+ Items.validate(query, 'Case Search'.freeze, ValCaseSearch)
480
480
  @cache.case_search(query)
481
481
  end
482
482
 
@@ -513,7 +513,7 @@ class Api
513
513
  # @param query [Hash] a query
514
514
  #
515
515
  def log_search(query)
516
- Validate.validate(query, 'Log Search'.freeze, ValLogSearch)
516
+ Items.validate(query, 'Log Search'.freeze, ValLogSearch)
517
517
  @cache.log_search(query)
518
518
  end
519
519
 
@@ -552,7 +552,7 @@ class Api
552
552
  # Search for entries
553
553
  #
554
554
  def entry_search(query)
555
- Validate.validate(query, 'Entry Search'.freeze, ValEntrySearch)
555
+ Items.validate(query, 'Entry Search'.freeze, ValEntrySearch)
556
556
 
557
557
  # check permissions
558
558
  # - have global search permissions / read access to the case
@@ -640,7 +640,7 @@ class Api
640
640
  # Search for actions
641
641
  #
642
642
  def action_search(query)
643
- Validate.validate(query, 'Action Search'.freeze, ValActionSearch)
643
+ Items.validate(query, 'Action Search'.freeze, ValActionSearch)
644
644
 
645
645
  # permissions check
646
646
  # - have global search permissions / read access to the case
@@ -686,7 +686,7 @@ class Api
686
686
  # Search for indexes
687
687
  #
688
688
  def index_search(query)
689
- Validate.validate(query, 'Index Search'.freeze, ValIndexSearch)
689
+ Items.validate(query, 'Index Search'.freeze, ValIndexSearch)
690
690
 
691
691
  # permissions check
692
692
  # - have global search permissions / read access to the case
@@ -701,7 +701,7 @@ class Api
701
701
  res[:list].each do |se|
702
702
  idx = se[:object]
703
703
 
704
- unless access_list(idx[:caseid].include?(ICFS::PermRead))
704
+ unless access_list(idx[:caseid]).include?(ICFS::PermRead)
705
705
  idx[:title] = nil
706
706
  idx[:tags] = nil
707
707
  end
@@ -728,7 +728,7 @@ class Api
728
728
  # Analyze stats
729
729
  #
730
730
  def stats(query)
731
- Validate.validate(query, 'Stats Search'.freeze, ValStatsSearch)
731
+ Items.validate(query, 'Stats Search'.freeze, ValStatsSearch)
732
732
 
733
733
  # permissions check
734
734
  # - have global search permissions / read access to the case
@@ -757,7 +757,7 @@ class Api
757
757
  # Get case tags
758
758
  #
759
759
  def case_tags(query)
760
- Validate.validate(query, 'Case Tags Search'.freeze, ValCaseTags)
760
+ Items.validate(query, 'Case Tags Search'.freeze, ValCaseTags)
761
761
  return @cache.case_tags(query)
762
762
  end # def case_tags()
763
763
 
@@ -778,7 +778,7 @@ class Api
778
778
  # Get entry tags
779
779
  #
780
780
  def entry_tags(query)
781
- Validate.validate(query, 'Entry Tags Search'.freeze, ValEntryTags)
781
+ Items.validate(query, 'Entry Tags Search'.freeze, ValEntryTags)
782
782
 
783
783
  # permissions
784
784
  # - read access to case
@@ -819,7 +819,7 @@ class Api
819
819
  # Get action tags
820
820
  #
821
821
  def action_tags(query)
822
- Validate.validate(query, 'Task Tags Search'.freeze, ValActionTags)
822
+ Items.validate(query, 'Task Tags Search'.freeze, ValActionTags)
823
823
 
824
824
  # only allow searches for user/roles you have
825
825
  unless @ur.include?(query[:assigned]) ||
@@ -849,7 +849,7 @@ class Api
849
849
  # Get index tags
850
850
  #
851
851
  def index_tags(query)
852
- Validate.validate(query, 'Index Tags'.freeze, ValIndexTags)
852
+ Items.validate(query, 'Index Tags'.freeze, ValIndexTags)
853
853
  unless access_list(query[:caseid]).include?(ICFS::PermRead)
854
854
  raise(Error::Perms, 'missing perms: %s'.freeze % ICFS::PermRead)
855
855
  end
@@ -875,8 +875,8 @@ class Api
875
875
  # Sanity checks
876
876
 
877
877
  # form & values
878
- Validate.validate(ent, 'entry'.freeze, Items::ItemEntryNew)
879
- Validate.validate(cse, 'case'.freeze, Items::ItemCaseEdit)
878
+ Items.validate(ent, 'entry'.freeze, Items::ItemEntryNew)
879
+ Items.validate(cse, 'case'.freeze, Items::ItemCaseEdit)
880
880
 
881
881
  # access users/roles/groups are valid
882
882
  cse["access"].each do |acc|
@@ -923,7 +923,7 @@ class Api
923
923
  cse['caseid'] = cid
924
924
  cse['log'] = 1
925
925
  cse['tags'] ||= [ ICFS::TagNone ]
926
- citem = Validate.generate(cse, 'case'.freeze, Items::ItemCase)
926
+ citem = Items.generate(cse, 'case'.freeze, Items::ItemCase)
927
927
 
928
928
  # entry
929
929
  ent['icfs'] = 1
@@ -973,12 +973,12 @@ class Api
973
973
  # finish items
974
974
  ent['time'] ||= now
975
975
  ent['files'].each{|fi| fi['log'] ||= 1 } if ent['files']
976
- eitem = Validate.generate(ent, 'entry'.freeze, Items::ItemEntry)
976
+ eitem = Items.generate(ent, 'entry'.freeze, Items::ItemEntry)
977
977
  log['time'] = now
978
978
  log['entry']['hash'] = ICFS.hash(eitem)
979
- litem = Validate.generate(log, 'log'.freeze, Items::ItemLog)
979
+ litem = Items.generate(log, 'log'.freeze, Items::ItemLog)
980
980
  cur['hash'] = ICFS.hash(litem)
981
- nitem = Validate.generate(cur, 'current'.freeze, Items::ItemCurrent)
981
+ nitem = Items.generate(cur, 'current'.freeze, Items::ItemCurrent)
982
982
 
983
983
  # write to cache
984
984
  @cache.entry_write(cid, 1, eitem)
@@ -1017,13 +1017,13 @@ class Api
1017
1017
 
1018
1018
  # form & content
1019
1019
  if idx || cse
1020
- Validate.validate(ent, 'New Entry'.freeze, Items::ItemEntryNew)
1020
+ Items.validate(ent, 'New Entry'.freeze, Items::ItemEntryNew)
1021
1021
  else
1022
- Validate.validate(ent, 'Editable Entry'.freeze, Items::ItemEntryEdit)
1022
+ Items.validate(ent, 'Editable Entry'.freeze, Items::ItemEntryEdit)
1023
1023
  end
1024
- Validate.validate(act, 'action'.freeze, Items::ItemActionEdit) if act
1025
- Validate.validate(idx, 'index'.freeze, Items::ItemIndexEdit) if idx
1026
- Validate.validate(cse, 'case'.freeze, Items::ItemCaseEdit) if cse
1024
+ Items.validate(act, 'action'.freeze, Items::ItemActionEdit) if act
1025
+ Items.validate(idx, 'index'.freeze, Items::ItemIndexEdit) if idx
1026
+ Items.validate(cse, 'case'.freeze, Items::ItemCaseEdit) if cse
1027
1027
 
1028
1028
  # edit index OR case, not both
1029
1029
  if idx && cse
@@ -1133,13 +1133,13 @@ class Api
1133
1133
 
1134
1134
  # current
1135
1135
  json = @cache.current_read(cid)
1136
- cur = Validate.parse(json, 'current'.freeze, Items::ItemCurrent)
1136
+ cur = Items.parse(json, 'current'.freeze, Items::ItemCurrent)
1137
1137
 
1138
1138
  # entry
1139
1139
  if ent['entry']
1140
1140
  enum = ent['entry']
1141
1141
  json = @cache.entry_read(cid, enum)
1142
- ent_pri = Validate.parse(json, 'entry'.freeze, Items::ItemEntry)
1142
+ ent_pri = Items.parse(json, 'entry'.freeze, Items::ItemEntry)
1143
1143
  nxt['entry'] = cur['entry']
1144
1144
  else
1145
1145
  enum = cur['entry'] + 1
@@ -1156,7 +1156,7 @@ class Api
1156
1156
  end
1157
1157
  if anum
1158
1158
  json = @cache.action_read(cid, anum)
1159
- act_pri = Validate.parse(json, 'action'.freeze, Items::ItemAction)
1159
+ act_pri = Items.parse(json, 'action'.freeze, Items::ItemAction)
1160
1160
  nxt['action'] = cur['action']
1161
1161
  elsif act
1162
1162
  anum = cur['action'] + 1
@@ -1318,7 +1318,7 @@ class Api
1318
1318
  end
1319
1319
  end
1320
1320
  ent['files'].each{|fi| fi['log'] ||= lnum } if ent['files']
1321
- eitem = Validate.generate(ent, 'entry'.freeze, Items::ItemEntry)
1321
+ eitem = Items.generate(ent, 'entry'.freeze, Items::ItemEntry)
1322
1322
  log['entry'] = {
1323
1323
  'num' => enum,
1324
1324
  'hash' => ICFS.hash(eitem)
@@ -1328,7 +1328,7 @@ class Api
1328
1328
  if act
1329
1329
  act['action'] = anum
1330
1330
  act['log'] = lnum
1331
- aitem = Validate.generate(act, 'action'.freeze, Items::ItemAction)
1331
+ aitem = Items.generate(act, 'action'.freeze, Items::ItemAction)
1332
1332
  log['action'] = {
1333
1333
  'num' => anum,
1334
1334
  'hash' => ICFS.hash(aitem)
@@ -1339,7 +1339,7 @@ class Api
1339
1339
  if idx
1340
1340
  idx['index'] = xnum
1341
1341
  idx['log'] = lnum
1342
- xitem = Validate.generate(idx, 'index'.freeze, Items::ItemIndex)
1342
+ xitem = Items.generate(idx, 'index'.freeze, Items::ItemIndex)
1343
1343
  log['index'] = {
1344
1344
  'num' => xnum,
1345
1345
  'hash' => ICFS.hash(xitem)
@@ -1349,7 +1349,7 @@ class Api
1349
1349
  # case
1350
1350
  if cse
1351
1351
  cse['log'] = lnum
1352
- citem = Validate.generate(cse, 'case'.freeze, Items::ItemCase)
1352
+ citem = Items.generate(cse, 'case'.freeze, Items::ItemCase)
1353
1353
  log['case_hash'] = ICFS.hash(citem)
1354
1354
  end
1355
1355
 
@@ -1357,11 +1357,11 @@ class Api
1357
1357
  log['log'] = lnum
1358
1358
  log['prev'] = cur['hash']
1359
1359
  log['time'] = now
1360
- litem = Validate.generate(log, 'log'.freeze, Items::ItemLog)
1360
+ litem = Items.generate(log, 'log'.freeze, Items::ItemLog)
1361
1361
  nxt['hash'] = ICFS.hash(litem)
1362
1362
 
1363
1363
  # next
1364
- nitem = Validate.generate(nxt, 'current'.freeze, Items::ItemCurrent)
1364
+ nitem = Items.generate(nxt, 'current'.freeze, Items::ItemCurrent)
1365
1365
 
1366
1366
 
1367
1367
  ####################
@@ -9,6 +9,8 @@
9
9
  # This program is distributed WITHOUT ANY WARRANTY; without even the
10
10
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
11
 
12
+ require 'json'
13
+ require 'socket'
12
14
  require_relative 'elastic'
13
15
 
14
16
 
@@ -153,6 +155,8 @@ class CacheElastic < Cache
153
155
  def initialize(map, es)
154
156
  @map = map
155
157
  @es = es
158
+ @name = '%s:%d' % [Socket.gethostname, Process.pid]
159
+ @name.freeze
156
160
  end
157
161
 
158
162
 
@@ -165,11 +169,9 @@ class CacheElastic < Cache
165
169
  ###############################################
166
170
  # (see Cache#lock_take)
167
171
  #
168
- # @todo Include client info to help with debugging
169
- #
170
172
  def lock_take(cid)
171
173
 
172
- json = '{"client":"TODO"}'.freeze
174
+ json = '{"client":"%s"}'.freeze % @name
173
175
  url = '%s/_doc/%s/_create'.freeze % [@map[:lock], CGI.escape(cid)]
174
176
  head = {'Content-Type'.freeze => 'application/json'.freeze}.freeze
175
177
 
@@ -656,7 +658,7 @@ class CacheElastic < Cache
656
658
  filter = [
657
659
  _query_term('caseid'.freeze, query[:caseid]),
658
660
  _query_term('tags'.freeze, query[:tags]),
659
- _query_prefix('title'.freeze, query[:prefix]),
661
+ _query_prefix('title.raw'.freeze, query[:prefix]),
660
662
  ].compact
661
663
  req = { 'query' => _query_bool(must, filter, nil, nil) }
662
664
 
data/lib/icfs/items.rb CHANGED
@@ -9,7 +9,9 @@
9
9
  # This program is distributed WITHOUT ANY WARRANTY; without even the
10
10
  # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
11
 
12
- #
12
+ require 'json'
13
+
14
+
13
15
  module ICFS
14
16
 
15
17
 
@@ -18,6 +20,65 @@ module ICFS
18
20
  #
19
21
  module Items
20
22
 
23
+
24
+ ###############################################
25
+ # Parse JSON string and validate
26
+ #
27
+ # @param json [String] the JSON to parse
28
+ # @param name [String] description of the item
29
+ # @param val [Hash] the check to use
30
+ # @return [Object] the item
31
+ #
32
+ # @raise [Error::NotFound] if json is nil
33
+ # @raise [Error::Value] if parsing or validation fails
34
+ #
35
+ def self.parse(json, name, val)
36
+ if json.nil?
37
+ raise(Error::NotFound, '%s not found'.freeze % name)
38
+ end
39
+ begin
40
+ itm = JSON.parse(json)
41
+ rescue
42
+ raise(Error::Value, 'JSON parsing failed'.freeze)
43
+ end
44
+ Items.validate(itm, name, val)
45
+ return itm
46
+ end # def self.parse()
47
+
48
+
49
+ ###############################################
50
+ # Validate and generate JSON
51
+ #
52
+ # @param itm [Object] item to validate
53
+ # @param name [String] description of the item
54
+ # @param val [Hash] the check to use
55
+ # @return [String] JSON encoded item
56
+ #
57
+ # @raise [Error::Value] if validation fails
58
+ #
59
+ def self.generate(itm, name, val)
60
+ Items.validate(itm, name, val)
61
+ return JSON.pretty_generate(itm)
62
+ end # def self.generate()
63
+
64
+
65
+ ###############################################
66
+ # Validate an object
67
+ #
68
+ # @param obj [Object] object to validate
69
+ # @param name [String] description of the object
70
+ # @param val [Hash] the check to use
71
+ #
72
+ # @raise [Error::Value] if validation fails
73
+ #
74
+ def self.validate(obj, name, val)
75
+ err = Validate.check(obj, val)
76
+ if err
77
+ raise(Error::Value, '%s has bad values: %s'.freeze %
78
+ [name, err.inspect])
79
+ end
80
+ end
81
+
21
82
  ##############################################################
22
83
  # Base fields
23
84
  ##############################################################
data/lib/icfs/store.rb CHANGED
@@ -115,6 +115,18 @@ class Store
115
115
  def file_write(cid, enum, lnum, fnum, tmpf); raise NotImplementedError; end
116
116
 
117
117
 
118
+ ###############################################
119
+ # Get a file size
120
+ #
121
+ # @param cid [String] caseid
122
+ # @param enum [Integer] Entry number
123
+ # @param lnum [Integer] Log number
124
+ # @param fnum [Integer] File number
125
+ # @return [Integer] The size of the file
126
+ #
127
+ def file_size(cid, enum, lnum, fnum); raise NotImplementedError; end
128
+
129
+
118
130
  ###############################################
119
131
  # Read an action
120
132
  #
@@ -176,6 +188,19 @@ class Store
176
188
  def tempfile; raise NotImplementedError; end
177
189
 
178
190
 
191
+ ###############################################
192
+ # Close the file returned by file_read()
193
+ #
194
+ # @param fi [File] The file to close
195
+ #
196
+ def close(fi)
197
+ if fi.respond_to?( :close! )
198
+ fi.close!
199
+ else
200
+ fi.close
201
+ end
202
+ end
203
+
179
204
  private
180
205
 
181
206