icfs 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/icfs_demo_fcgi.rb +2 -0
- data/{bin/icfs_demo_ssl_gen.rb → devel/demo/ssl_gen.rb} +25 -13
- data/devel/demo/ssl_gen.yml +14 -0
- data/devel/icfs-wrk/Dockerfile +1 -1
- data/devel/run/base.rb +92 -0
- data/devel/run/copy-s3.rb +2 -0
- data/devel/run/email.rb +36 -0
- data/devel/run/email_imap.rb +43 -0
- data/devel/run/email_smime.rb +47 -0
- data/devel/run/init-icfs.rb +2 -0
- data/devel/run/webrick.rb +5 -57
- data/lib/icfs/api.rb +101 -90
- data/lib/icfs/cache.rb +2 -0
- data/lib/icfs/cache_elastic.rb +127 -125
- data/lib/icfs/{web/config.rb → config.rb} +3 -3
- data/lib/icfs/{web/config_redis.rb → config_redis.rb} +8 -8
- data/lib/icfs/{web/config_s3.rb → config_s3.rb} +8 -8
- data/lib/icfs/demo/auth.rb +5 -7
- data/lib/icfs/demo/static.rb +2 -0
- data/lib/icfs/elastic.rb +10 -8
- data/lib/icfs/email/basic.rb +242 -0
- data/lib/icfs/email/core.rb +293 -0
- data/lib/icfs/email/from.rb +52 -0
- data/lib/icfs/email/imap.rb +148 -0
- data/lib/icfs/email/smime.rb +139 -0
- data/lib/icfs/items.rb +5 -3
- data/lib/icfs/store.rb +20 -18
- data/lib/icfs/store_fs.rb +7 -5
- data/lib/icfs/store_s3.rb +4 -2
- data/lib/icfs/users.rb +5 -3
- data/lib/icfs/users_fs.rb +8 -6
- data/lib/icfs/users_redis.rb +12 -10
- data/lib/icfs/users_s3.rb +6 -4
- data/lib/icfs/utils/backup.rb +30 -29
- data/lib/icfs/utils/check.rb +36 -34
- data/lib/icfs/validate.rb +24 -15
- data/lib/icfs/web/auth_ssl.rb +7 -9
- data/lib/icfs/web/client.rb +671 -679
- data/lib/icfs.rb +174 -10
- metadata +16 -7
- data/devel/devel-webrick.yml +0 -49
data/lib/icfs/api.rb
CHANGED
@@ -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
|
+
# frozen_string_literal: true
|
13
|
+
|
12
14
|
#
|
13
15
|
module ICFS
|
14
16
|
|
@@ -49,12 +51,14 @@ class Api
|
|
49
51
|
# @param users [Users] the User/role/group interface
|
50
52
|
# @param cache [Cache] the cache
|
51
53
|
# @param store [Store] the store
|
54
|
+
# @param config [Config] the config settings, optional
|
52
55
|
#
|
53
|
-
def initialize(stats, users, cache, store)
|
56
|
+
def initialize(stats, users, cache, store, config=nil)
|
54
57
|
@users = users
|
55
58
|
@cache = cache
|
56
59
|
@store = store
|
57
60
|
@gstats = stats.map{|st| st.dup.freeze }.freeze
|
61
|
+
@config = config
|
58
62
|
reset
|
59
63
|
end # def initialize
|
60
64
|
|
@@ -67,8 +71,8 @@ class Api
|
|
67
71
|
def user=(uname)
|
68
72
|
@user = uname.dup.freeze
|
69
73
|
urgp = @users.read(uname)
|
70
|
-
raise(Error::NotFound, 'User name not found'
|
71
|
-
raise(Error::Value, 'Not a user'
|
74
|
+
raise(Error::NotFound, 'User name not found') if !urgp
|
75
|
+
raise(Error::Value, 'Not a user') if urgp['type'] != 'user'
|
72
76
|
if urgp['roles']
|
73
77
|
@roles = urgp['roles'].map{|rn| rn.freeze }.freeze
|
74
78
|
else
|
@@ -96,6 +100,8 @@ class Api
|
|
96
100
|
@ur.merge @roles
|
97
101
|
@ur.freeze
|
98
102
|
|
103
|
+
@config.load(@user) if @config
|
104
|
+
|
99
105
|
reset
|
100
106
|
end # def user=()
|
101
107
|
|
@@ -143,6 +149,11 @@ class Api
|
|
143
149
|
attr_reader :urg
|
144
150
|
|
145
151
|
|
152
|
+
###############################################
|
153
|
+
# Config settings
|
154
|
+
attr_reader :config
|
155
|
+
|
156
|
+
|
146
157
|
###############################################
|
147
158
|
# Reset the cached cases and access
|
148
159
|
#
|
@@ -213,7 +224,7 @@ class Api
|
|
213
224
|
###############################################
|
214
225
|
# See if we are tasked
|
215
226
|
def tasked?(cid, anum)
|
216
|
-
id = '%s.%d'
|
227
|
+
id = '%s.%d' % [cid, anum]
|
217
228
|
unless @tasked.key?(id)
|
218
229
|
act = _action_read(cid, anum)
|
219
230
|
|
@@ -283,12 +294,12 @@ class Api
|
|
283
294
|
def case_read(cid, lnum=0)
|
284
295
|
if lnum != 0
|
285
296
|
json = @store.case_read(cid, lnum)
|
286
|
-
return Items.parse(json, 'case'
|
297
|
+
return Items.parse(json, 'case', Items::ItemCase)
|
287
298
|
end
|
288
299
|
|
289
300
|
if !@cases.key?(cid)
|
290
301
|
json = @cache.case_read(cid)
|
291
|
-
cur = Items.parse(json, 'case'
|
302
|
+
cur = Items.parse(json, 'case', Items::ItemCase)
|
292
303
|
@cases[cid] = cur
|
293
304
|
end
|
294
305
|
return @cases[cid]
|
@@ -308,12 +319,12 @@ class Api
|
|
308
319
|
# get access list
|
309
320
|
al = access_list(cid)
|
310
321
|
if !al.include?(ICFS::PermRead)
|
311
|
-
raise(Error::Perms, 'missing perms: %s'
|
322
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead)
|
312
323
|
end
|
313
324
|
|
314
325
|
# read
|
315
326
|
json = @cache.log_read(cid, lnum)
|
316
|
-
return Items.parse(json, 'log'
|
327
|
+
return Items.parse(json, 'log', Items::ItemLog)
|
317
328
|
end # def log_read()
|
318
329
|
|
319
330
|
|
@@ -331,7 +342,7 @@ class Api
|
|
331
342
|
# get access list and current entry
|
332
343
|
al = access_list(cid)
|
333
344
|
json = @cache.entry_read(cid, enum)
|
334
|
-
ec = Items.parse(json, 'entry'
|
345
|
+
ec = Items.parse(json, 'entry', Items::ItemEntry)
|
335
346
|
|
336
347
|
# see if we can read the entry
|
337
348
|
need = Set.new
|
@@ -339,7 +350,7 @@ class Api
|
|
339
350
|
need.merge(ec['perms']) if ec['perms']
|
340
351
|
need.subtract(al)
|
341
352
|
unless need.empty?
|
342
|
-
raise(Error::Perms, 'missing perms: %s'
|
353
|
+
raise(Error::Perms, 'missing perms: %s' %
|
343
354
|
need.to_a.sort.join(', ') )
|
344
355
|
end
|
345
356
|
|
@@ -348,7 +359,7 @@ class Api
|
|
348
359
|
return ec
|
349
360
|
else
|
350
361
|
json = @store.entry_read(cid, enum, lnum)
|
351
|
-
return Items.parse(json, 'entry'
|
362
|
+
return Items.parse(json, 'entry', Items::ItemEntry)
|
352
363
|
end
|
353
364
|
end # def entry_read()
|
354
365
|
|
@@ -366,7 +377,7 @@ class Api
|
|
366
377
|
def file_read(cid, enum, lnum, fnum)
|
367
378
|
entry_read(cid, enum)
|
368
379
|
fi = @store.file_read(cid, enum, lnum, fnum)
|
369
|
-
raise(Error::NotFound, 'file not found'
|
380
|
+
raise(Error::NotFound, 'file not found') if !fi
|
370
381
|
return fi
|
371
382
|
end # def file_read()
|
372
383
|
|
@@ -377,10 +388,10 @@ class Api
|
|
377
388
|
# Internal version.
|
378
389
|
#
|
379
390
|
def _action_read(cid, anum)
|
380
|
-
id = '%s.%d'
|
391
|
+
id = '%s.%d' % [cid, anum]
|
381
392
|
unless @actions.key?(id)
|
382
393
|
json = @cache.action_read(cid, anum)
|
383
|
-
act = Items.parse(json, 'action'
|
394
|
+
act = Items.parse(json, 'action', Items::ItemAction)
|
384
395
|
@actions[id] = act
|
385
396
|
end
|
386
397
|
return @actions[id]
|
@@ -405,7 +416,7 @@ class Api
|
|
405
416
|
|
406
417
|
# see if we can read the action
|
407
418
|
unless _can_read?(cid, anum)
|
408
|
-
raise(Error::Perms, 'missing perms: %s'
|
419
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead )
|
409
420
|
end
|
410
421
|
|
411
422
|
# return the requested version
|
@@ -413,7 +424,7 @@ class Api
|
|
413
424
|
return ac
|
414
425
|
else
|
415
426
|
json = @store.action_read( cid, anum, lnum)
|
416
|
-
return Items.parse(json, 'action'
|
427
|
+
return Items.parse(json, 'action', Items::ItemAction)
|
417
428
|
end
|
418
429
|
end # def action_read()
|
419
430
|
|
@@ -432,19 +443,19 @@ class Api
|
|
432
443
|
# get access list
|
433
444
|
al = access_list(cid)
|
434
445
|
if !al.include?(ICFS::PermRead)
|
435
|
-
raise(Error::Perms, 'missing perms: %s'
|
446
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead )
|
436
447
|
end
|
437
448
|
|
438
449
|
# read curent index
|
439
450
|
json = @cache.index_read(cid, xnum)
|
440
|
-
xc = Items.parse(json, 'index'
|
451
|
+
xc = Items.parse(json, 'index', Items::ItemIndex)
|
441
452
|
|
442
453
|
# return the requested version
|
443
454
|
if( lnum == 0 || xc['log'] == lnum )
|
444
455
|
return xc
|
445
456
|
else
|
446
457
|
json = @store.index_read(cid, xnum, lnum)
|
447
|
-
return Items.parse(json, 'index'
|
458
|
+
return Items.parse(json, 'index', Items::ItemIndex)
|
448
459
|
end
|
449
460
|
end # def index_read()
|
450
461
|
|
@@ -458,11 +469,11 @@ class Api
|
|
458
469
|
|
459
470
|
al = access_list(cid)
|
460
471
|
if !al.include?(ICFS::PermRead)
|
461
|
-
raise(Error::Perms, 'missing perms: %s'
|
472
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead)
|
462
473
|
end
|
463
474
|
|
464
475
|
json = @cache.current_read(cid)
|
465
|
-
return Items.parse(json, 'current'
|
476
|
+
return Items.parse(json, 'current', Items::ItemCurrent)
|
466
477
|
end # end def current_read()
|
467
478
|
|
468
479
|
|
@@ -494,7 +505,7 @@ class Api
|
|
494
505
|
# @param query [Hash] a query
|
495
506
|
#
|
496
507
|
def case_search(query)
|
497
|
-
Items.validate(query, 'Case Search'
|
508
|
+
Items.validate(query, 'Case Search', ValCaseSearch)
|
498
509
|
@cache.case_search(query)
|
499
510
|
end
|
500
511
|
|
@@ -516,8 +527,8 @@ class Api
|
|
516
527
|
sort: {
|
517
528
|
method: :string,
|
518
529
|
allowed: Set[
|
519
|
-
'time_desc'
|
520
|
-
'time_asc'
|
530
|
+
'time_desc',
|
531
|
+
'time_asc',
|
521
532
|
].freeze,
|
522
533
|
whitelist: true,
|
523
534
|
}.freeze
|
@@ -531,7 +542,7 @@ class Api
|
|
531
542
|
# @param query [Hash] a query
|
532
543
|
#
|
533
544
|
def log_search(query)
|
534
|
-
Items.validate(query, 'Log Search'
|
545
|
+
Items.validate(query, 'Log Search', ValLogSearch)
|
535
546
|
@cache.log_search(query)
|
536
547
|
end
|
537
548
|
|
@@ -556,8 +567,8 @@ class Api
|
|
556
567
|
sort: {
|
557
568
|
method: :string,
|
558
569
|
allowed: Set[
|
559
|
-
'time_desc'
|
560
|
-
'time_asc'
|
570
|
+
'time_desc',
|
571
|
+
'time_asc',
|
561
572
|
].freeze,
|
562
573
|
whitelist: true,
|
563
574
|
}.freeze
|
@@ -570,14 +581,14 @@ class Api
|
|
570
581
|
# Search for entries
|
571
582
|
#
|
572
583
|
def entry_search(query)
|
573
|
-
Items.validate(query, 'Entry Search'
|
584
|
+
Items.validate(query, 'Entry Search', ValEntrySearch)
|
574
585
|
|
575
586
|
# check permissions
|
576
587
|
# - have global search permissions / read access to the case
|
577
588
|
# - are searching for an action they can read
|
578
589
|
unless( _search?(query) || (query[:caseid] &&
|
579
590
|
query[:action] && tasked?(query[:caseid], query[:action])))
|
580
|
-
raise(Error::Perms, 'Does not have permission to search'
|
591
|
+
raise(Error::Perms, 'Does not have permission to search')
|
581
592
|
end
|
582
593
|
|
583
594
|
# run the query
|
@@ -645,8 +656,8 @@ class Api
|
|
645
656
|
sort: {
|
646
657
|
method: :string,
|
647
658
|
allowed: Set[
|
648
|
-
'time_desc'
|
649
|
-
'time_asc'
|
659
|
+
'time_desc',
|
660
|
+
'time_asc',
|
650
661
|
].freeze,
|
651
662
|
whitelist: true,
|
652
663
|
}.freeze
|
@@ -658,7 +669,7 @@ class Api
|
|
658
669
|
# Search for actions
|
659
670
|
#
|
660
671
|
def action_search(query)
|
661
|
-
Items.validate(query, 'Action Search'
|
672
|
+
Items.validate(query, 'Action Search', ValActionSearch)
|
662
673
|
|
663
674
|
# permissions check
|
664
675
|
# - have global search permissions / read access to the case
|
@@ -666,7 +677,7 @@ class Api
|
|
666
677
|
unless( _search?(query) || @ur.include?(query[:assigned]) ||
|
667
678
|
(query[:assigned] == ICFS::UserCase && query[:caseid] &&
|
668
679
|
access_list(query[:caseid]).include?(ICFS::PermAction) ))
|
669
|
-
raise(Error::Perms, 'Does not have permission to search'
|
680
|
+
raise(Error::Perms, 'Does not have permission to search')
|
670
681
|
end
|
671
682
|
|
672
683
|
# run the search
|
@@ -689,10 +700,10 @@ class Api
|
|
689
700
|
sort: {
|
690
701
|
method: :string,
|
691
702
|
allowed: Set[
|
692
|
-
'title_desc'
|
693
|
-
'title_asc'
|
694
|
-
'index_desc'
|
695
|
-
'index_asc'
|
703
|
+
'title_desc',
|
704
|
+
'title_asc',
|
705
|
+
'index_desc',
|
706
|
+
'index_asc',
|
696
707
|
].freeze,
|
697
708
|
whitelist: true,
|
698
709
|
}.freeze
|
@@ -704,12 +715,12 @@ class Api
|
|
704
715
|
# Search for indexes
|
705
716
|
#
|
706
717
|
def index_search(query)
|
707
|
-
Items.validate(query, 'Index Search'
|
718
|
+
Items.validate(query, 'Index Search', ValIndexSearch)
|
708
719
|
|
709
720
|
# permissions check
|
710
721
|
# - have global search permissions / read access to the case
|
711
722
|
unless _search?(query)
|
712
|
-
raise(Error::Perms, 'Do not have permission to search'
|
723
|
+
raise(Error::Perms, 'Do not have permission to search')
|
713
724
|
end
|
714
725
|
|
715
726
|
# run the query
|
@@ -746,13 +757,13 @@ class Api
|
|
746
757
|
# Analyze stats
|
747
758
|
#
|
748
759
|
def stats(query)
|
749
|
-
Items.validate(query, 'Stats Search'
|
760
|
+
Items.validate(query, 'Stats Search', ValStatsSearch)
|
750
761
|
|
751
762
|
# permissions check
|
752
763
|
# - have global search permissions / read access to the case
|
753
764
|
# - are searching for a user/role/group you have
|
754
765
|
unless _search?(query) || (query[:credit] && @urg.include?(query[:credit]))
|
755
|
-
raise(Error::Perms, 'Do not have permissions to search'
|
766
|
+
raise(Error::Perms, 'Do not have permissions to search')
|
756
767
|
end
|
757
768
|
|
758
769
|
@cache.stats(query)
|
@@ -775,7 +786,7 @@ class Api
|
|
775
786
|
# Get case tags
|
776
787
|
#
|
777
788
|
def case_tags(query)
|
778
|
-
Items.validate(query, 'Case Tags Search'
|
789
|
+
Items.validate(query, 'Case Tags Search', ValCaseTags)
|
779
790
|
return @cache.case_tags(query)
|
780
791
|
end # def case_tags()
|
781
792
|
|
@@ -796,12 +807,12 @@ class Api
|
|
796
807
|
# Get entry tags
|
797
808
|
#
|
798
809
|
def entry_tags(query)
|
799
|
-
Items.validate(query, 'Entry Tags Search'
|
810
|
+
Items.validate(query, 'Entry Tags Search', ValEntryTags)
|
800
811
|
|
801
812
|
# permissions
|
802
813
|
# - read access to case
|
803
814
|
unless access_list(query[:caseid]).include?(ICFS::PermRead)
|
804
|
-
raise(Error::Perms, 'missing perms: %s'
|
815
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead)
|
805
816
|
end
|
806
817
|
return @cache.entry_tags(query)
|
807
818
|
end # def entry_tags()
|
@@ -837,13 +848,13 @@ class Api
|
|
837
848
|
# Get action tags
|
838
849
|
#
|
839
850
|
def action_tags(query)
|
840
|
-
Items.validate(query, 'Task Tags Search'
|
851
|
+
Items.validate(query, 'Task Tags Search', ValActionTags)
|
841
852
|
|
842
853
|
# only allow searches for user/roles you have
|
843
854
|
unless @ur.include?(query[:assigned]) ||
|
844
855
|
(query[:assigned] == ICFS::UserCase && query[:caseid] &&
|
845
856
|
access_list(query[:caseid]).include?(ICFS::PermAction) )
|
846
|
-
raise(Error::Perms, 'May not search for other\'s tasks'
|
857
|
+
raise(Error::Perms, 'May not search for other\'s tasks')
|
847
858
|
end
|
848
859
|
|
849
860
|
# run the search
|
@@ -867,9 +878,9 @@ class Api
|
|
867
878
|
# Get index tags
|
868
879
|
#
|
869
880
|
def index_tags(query)
|
870
|
-
Items.validate(query, 'Index Tags'
|
881
|
+
Items.validate(query, 'Index Tags', ValIndexTags)
|
871
882
|
unless access_list(query[:caseid]).include?(ICFS::PermRead)
|
872
|
-
raise(Error::Perms, 'missing perms: %s'
|
883
|
+
raise(Error::Perms, 'missing perms: %s' % ICFS::PermRead)
|
873
884
|
end
|
874
885
|
return @cache.index_tags(query)
|
875
886
|
end
|
@@ -894,8 +905,8 @@ class Api
|
|
894
905
|
# Sanity checks
|
895
906
|
|
896
907
|
# form & values
|
897
|
-
Items.validate(ent, 'entry'
|
898
|
-
Items.validate(cse, 'case'
|
908
|
+
Items.validate(ent, 'entry', Items::ItemEntryNew)
|
909
|
+
Items.validate(cse, 'case', Items::ItemCaseEdit)
|
899
910
|
|
900
911
|
# access users/roles/groups are valid, unless manually specifying user
|
901
912
|
unless unam
|
@@ -903,7 +914,7 @@ class Api
|
|
903
914
|
acc["grant"].each do |gnt|
|
904
915
|
urg = @users.read(gnt)
|
905
916
|
if !urg
|
906
|
-
raise(Error::NotFound, 'User/role/group %s not found'
|
917
|
+
raise(Error::NotFound, 'User/role/group %s not found' % urg)
|
907
918
|
end
|
908
919
|
end
|
909
920
|
end
|
@@ -917,26 +928,26 @@ class Api
|
|
917
928
|
if tid
|
918
929
|
tmpl = case_read(tid)
|
919
930
|
unless tmpl['template']
|
920
|
-
raise(Error::Perms, 'Not a template'
|
931
|
+
raise(Error::Perms, 'Not a template')
|
921
932
|
end
|
922
933
|
|
923
934
|
al = access_list(tid)
|
924
935
|
unless al.include?(ICFS::PermManage)
|
925
|
-
raise(Error::Perms, 'May not create cases from this template'
|
936
|
+
raise(Error::Perms, 'May not create cases from this template')
|
926
937
|
end
|
927
938
|
end
|
928
939
|
|
929
940
|
# no action/indexes
|
930
941
|
if ent['action']
|
931
|
-
raise(Error::Value, 'No Action for a new case entry'
|
942
|
+
raise(Error::Value, 'No Action for a new case entry')
|
932
943
|
end
|
933
944
|
if ent['index']
|
934
|
-
raise(Error::Value, 'No Index for a new case entry'
|
945
|
+
raise(Error::Value, 'No Index for a new case entry')
|
935
946
|
end
|
936
947
|
|
937
948
|
# Allow case creation without a Users system in place
|
938
949
|
user = @user ? @user : unam
|
939
|
-
raise(ArgumentError, 'No user specified'
|
950
|
+
raise(ArgumentError, 'No user specified') if user.nil?
|
940
951
|
|
941
952
|
####################
|
942
953
|
# Prep
|
@@ -947,7 +958,7 @@ class Api
|
|
947
958
|
cse['caseid'] = cid
|
948
959
|
cse['log'] = 1
|
949
960
|
cse['tags'] ||= [ ICFS::TagNone ]
|
950
|
-
citem = Items.generate(cse, 'case'
|
961
|
+
citem = Items.generate(cse, 'case', Items::ItemCase)
|
951
962
|
|
952
963
|
# entry
|
953
964
|
ent['icfs'] = 1
|
@@ -989,7 +1000,7 @@ class Api
|
|
989
1000
|
@cache.lock_take(cid)
|
990
1001
|
begin
|
991
1002
|
if @cache.case_read(cid)
|
992
|
-
raise(Error::Conflict, 'Case already exists'
|
1003
|
+
raise(Error::Conflict, 'Case already exists')
|
993
1004
|
end
|
994
1005
|
|
995
1006
|
now = Time.now.to_i
|
@@ -997,12 +1008,12 @@ class Api
|
|
997
1008
|
# finish items
|
998
1009
|
ent['time'] ||= now
|
999
1010
|
ent['files'].each{|fi| fi['log'] ||= 1 } if ent['files']
|
1000
|
-
eitem = Items.generate(ent, 'entry'
|
1011
|
+
eitem = Items.generate(ent, 'entry', Items::ItemEntry)
|
1001
1012
|
log['time'] = now
|
1002
1013
|
log['entry']['hash'] = ICFS.hash(eitem)
|
1003
|
-
litem = Items.generate(log, 'log'
|
1014
|
+
litem = Items.generate(log, 'log', Items::ItemLog)
|
1004
1015
|
cur['hash'] = ICFS.hash(litem)
|
1005
|
-
nitem = Items.generate(cur, 'current'
|
1016
|
+
nitem = Items.generate(cur, 'current', Items::ItemCurrent)
|
1006
1017
|
|
1007
1018
|
# write to cache
|
1008
1019
|
@cache.entry_write(cid, 1, eitem)
|
@@ -1041,22 +1052,22 @@ class Api
|
|
1041
1052
|
|
1042
1053
|
# form & content
|
1043
1054
|
if idx || cse
|
1044
|
-
Items.validate(ent, 'New Entry'
|
1055
|
+
Items.validate(ent, 'New Entry', Items::ItemEntryNew)
|
1045
1056
|
else
|
1046
|
-
Items.validate(ent, 'Editable Entry'
|
1057
|
+
Items.validate(ent, 'Editable Entry', Items::ItemEntryEdit)
|
1047
1058
|
end
|
1048
|
-
Items.validate(act, 'action'
|
1049
|
-
Items.validate(idx, 'index'
|
1050
|
-
Items.validate(cse, 'case'
|
1059
|
+
Items.validate(act, 'action', Items::ItemActionEdit) if act
|
1060
|
+
Items.validate(idx, 'index', Items::ItemIndexEdit) if idx
|
1061
|
+
Items.validate(cse, 'case', Items::ItemCaseEdit) if cse
|
1051
1062
|
|
1052
1063
|
# edit index OR case, not both
|
1053
1064
|
if idx && cse
|
1054
|
-
raise(Error::Value, 'May not edit both case and index at once'
|
1065
|
+
raise(Error::Value, 'May not edit both case and index at once')
|
1055
1066
|
end
|
1056
1067
|
|
1057
1068
|
# no changing the action
|
1058
1069
|
if act && ent['action'] && act['action'] && act['action'] != ent['action']
|
1059
|
-
raise(Error::Conflict, 'May not change entry\'s action'
|
1070
|
+
raise(Error::Conflict, 'May not change entry\'s action')
|
1060
1071
|
end
|
1061
1072
|
|
1062
1073
|
# access users/roles/groups are valid
|
@@ -1065,7 +1076,7 @@ class Api
|
|
1065
1076
|
acc['grant'].each do |gnt|
|
1066
1077
|
urg = @users.read(gnt)
|
1067
1078
|
if !urg
|
1068
|
-
raise(Error::NotFound, 'User/role/group %s not found'
|
1079
|
+
raise(Error::NotFound, 'User/role/group %s not found' % gnt)
|
1069
1080
|
end
|
1070
1081
|
end
|
1071
1082
|
end
|
@@ -1078,12 +1089,12 @@ class Api
|
|
1078
1089
|
tsk = act['tasks'][ix]
|
1079
1090
|
ur = @users.read(tsk['assigned'])
|
1080
1091
|
if !ur
|
1081
|
-
raise(Error::NotFound, 'User/role %s not found'
|
1092
|
+
raise(Error::NotFound, 'User/role %s not found' %
|
1082
1093
|
tsk['assigned'])
|
1083
1094
|
end
|
1084
1095
|
type = ur['type']
|
1085
1096
|
if type != 'user' && type != 'role'
|
1086
|
-
raise(Error::Values, 'Not a user or role: %s'
|
1097
|
+
raise(Error::Values, 'Not a user or role: %s' %
|
1087
1098
|
tsk['assigned'])
|
1088
1099
|
end
|
1089
1100
|
end
|
@@ -1157,13 +1168,13 @@ class Api
|
|
1157
1168
|
|
1158
1169
|
# current
|
1159
1170
|
json = @cache.current_read(cid)
|
1160
|
-
cur = Items.parse(json, 'current'
|
1171
|
+
cur = Items.parse(json, 'current', Items::ItemCurrent)
|
1161
1172
|
|
1162
1173
|
# entry
|
1163
1174
|
if ent['entry']
|
1164
1175
|
enum = ent['entry']
|
1165
1176
|
json = @cache.entry_read(cid, enum)
|
1166
|
-
ent_pri = Items.parse(json, 'entry'
|
1177
|
+
ent_pri = Items.parse(json, 'entry', Items::ItemEntry)
|
1167
1178
|
nxt['entry'] = cur['entry']
|
1168
1179
|
else
|
1169
1180
|
enum = cur['entry'] + 1
|
@@ -1180,7 +1191,7 @@ class Api
|
|
1180
1191
|
end
|
1181
1192
|
if anum
|
1182
1193
|
json = @cache.action_read(cid, anum)
|
1183
|
-
act_pri = Items.parse(json, 'action'
|
1194
|
+
act_pri = Items.parse(json, 'action', Items::ItemAction)
|
1184
1195
|
nxt['action'] = cur['action']
|
1185
1196
|
elsif act
|
1186
1197
|
anum = cur['action'] + 1
|
@@ -1225,7 +1236,7 @@ class Api
|
|
1225
1236
|
|
1226
1237
|
# may not change action
|
1227
1238
|
if ent_pri['action'] && (ent['action'] != ent_pri['action'])
|
1228
|
-
raise(Error::Conflict, 'May not change entry\'s action'
|
1239
|
+
raise(Error::Conflict, 'May not change entry\'s action')
|
1229
1240
|
end
|
1230
1241
|
|
1231
1242
|
# may not remove or add action, index, case tags
|
@@ -1235,7 +1246,7 @@ class Api
|
|
1235
1246
|
ent['tags'].include?(ICFS::TagIndex) ) ||
|
1236
1247
|
(ent_pri['tags'].include?(ICFS::TagCase) !=
|
1237
1248
|
ent['tags'].include?(ICFS::TagCase) ) )
|
1238
|
-
raise(Error::Conflict, 'May not change entry\'s special tags'
|
1249
|
+
raise(Error::Conflict, 'May not change entry\'s special tags')
|
1239
1250
|
end
|
1240
1251
|
end
|
1241
1252
|
|
@@ -1247,7 +1258,7 @@ class Api
|
|
1247
1258
|
|
1248
1259
|
# not allowed to delete tasks
|
1249
1260
|
if pri_tsk.size > cur_tsk.size
|
1250
|
-
raise(Error::Conflict, 'May not delete tasks'
|
1261
|
+
raise(Error::Conflict, 'May not delete tasks')
|
1251
1262
|
end
|
1252
1263
|
|
1253
1264
|
# check each task
|
@@ -1259,17 +1270,17 @@ class Api
|
|
1259
1270
|
|
1260
1271
|
# may not delete a tasking
|
1261
1272
|
if pt && pt['assigned'] != ct['assigned']
|
1262
|
-
raise(Error::Conflict, 'May not delete task'
|
1273
|
+
raise(Error::Conflict, 'May not delete task')
|
1263
1274
|
end
|
1264
1275
|
|
1265
1276
|
# new taskings require action to be open
|
1266
1277
|
if !pt && !act_open
|
1267
|
-
raise(Error::Value, 'New tasks require the action be open'
|
1278
|
+
raise(Error::Value, 'New tasks require the action be open')
|
1268
1279
|
end
|
1269
1280
|
|
1270
1281
|
# may not have a task open if action is closed
|
1271
1282
|
if ct['status'] && !act_open
|
1272
|
-
raise(Error::Value, 'Open tasks on closed action'
|
1283
|
+
raise(Error::Value, 'Open tasks on closed action')
|
1273
1284
|
end
|
1274
1285
|
|
1275
1286
|
# can set any values for our tasks
|
@@ -1280,7 +1291,7 @@ class Api
|
|
1280
1291
|
|
1281
1292
|
# must be flagged if new tasking or re-opening
|
1282
1293
|
if !ct['flag'] && (!pt || (ct['status'] && !pt['status']))
|
1283
|
-
raise(Error::Value, 'New or re-opened taskings must flag'
|
1294
|
+
raise(Error::Value, 'New or re-opened taskings must flag')
|
1284
1295
|
end
|
1285
1296
|
|
1286
1297
|
# no changing other's taskings, no deflagging, and no
|
@@ -1289,7 +1300,7 @@ class Api
|
|
1289
1300
|
(pt['title'] != ct['title']) || (pt['time'] != ct['time']) ||
|
1290
1301
|
(pt['tags'] != ct['tags']) || (pt['flag'] && !ct['flag']) ||
|
1291
1302
|
(pt['status'] && !ct['status'] && !perm_act) )
|
1292
|
-
raise(Error::Value, 'May not change other\'s tasks'
|
1303
|
+
raise(Error::Value, 'May not change other\'s tasks')
|
1293
1304
|
end
|
1294
1305
|
end
|
1295
1306
|
|
@@ -1306,7 +1317,7 @@ class Api
|
|
1306
1317
|
if cse
|
1307
1318
|
# no changing template
|
1308
1319
|
unless cse['template'] == cse_pri['template']
|
1309
|
-
raise(Error::Conflict, 'May not change template status'
|
1320
|
+
raise(Error::Conflict, 'May not change template status')
|
1310
1321
|
end
|
1311
1322
|
|
1312
1323
|
# manage required
|
@@ -1321,7 +1332,7 @@ class Api
|
|
1321
1332
|
# permissions
|
1322
1333
|
perms_miss = perms - al
|
1323
1334
|
unless perms_miss.empty?
|
1324
|
-
raise(Error::Perms, 'Missing perms: %s'
|
1335
|
+
raise(Error::Perms, 'Missing perms: %s' %
|
1325
1336
|
perms_miss.to_a.sort.join(', ') )
|
1326
1337
|
end
|
1327
1338
|
|
@@ -1342,7 +1353,7 @@ class Api
|
|
1342
1353
|
end
|
1343
1354
|
end
|
1344
1355
|
ent['files'].each{|fi| fi['log'] ||= lnum } if ent['files']
|
1345
|
-
eitem = Items.generate(ent, 'entry'
|
1356
|
+
eitem = Items.generate(ent, 'entry', Items::ItemEntry)
|
1346
1357
|
log['entry'] = {
|
1347
1358
|
'num' => enum,
|
1348
1359
|
'hash' => ICFS.hash(eitem)
|
@@ -1352,7 +1363,7 @@ class Api
|
|
1352
1363
|
if act
|
1353
1364
|
act['action'] = anum
|
1354
1365
|
act['log'] = lnum
|
1355
|
-
aitem = Items.generate(act, 'action'
|
1366
|
+
aitem = Items.generate(act, 'action', Items::ItemAction)
|
1356
1367
|
log['action'] = {
|
1357
1368
|
'num' => anum,
|
1358
1369
|
'hash' => ICFS.hash(aitem)
|
@@ -1363,7 +1374,7 @@ class Api
|
|
1363
1374
|
if idx
|
1364
1375
|
idx['index'] = xnum
|
1365
1376
|
idx['log'] = lnum
|
1366
|
-
xitem = Items.generate(idx, 'index'
|
1377
|
+
xitem = Items.generate(idx, 'index', Items::ItemIndex)
|
1367
1378
|
log['index'] = {
|
1368
1379
|
'num' => xnum,
|
1369
1380
|
'hash' => ICFS.hash(xitem)
|
@@ -1373,7 +1384,7 @@ class Api
|
|
1373
1384
|
# case
|
1374
1385
|
if cse
|
1375
1386
|
cse['log'] = lnum
|
1376
|
-
citem = Items.generate(cse, 'case'
|
1387
|
+
citem = Items.generate(cse, 'case', Items::ItemCase)
|
1377
1388
|
log['case_hash'] = ICFS.hash(citem)
|
1378
1389
|
end
|
1379
1390
|
|
@@ -1381,11 +1392,11 @@ class Api
|
|
1381
1392
|
log['log'] = lnum
|
1382
1393
|
log['prev'] = cur['hash']
|
1383
1394
|
log['time'] = now
|
1384
|
-
litem = Items.generate(log, 'log'
|
1395
|
+
litem = Items.generate(log, 'log', Items::ItemLog)
|
1385
1396
|
nxt['hash'] = ICFS.hash(litem)
|
1386
1397
|
|
1387
1398
|
# next
|
1388
|
-
nitem = Items.generate(nxt, 'current'
|
1399
|
+
nitem = Items.generate(nxt, 'current', Items::ItemCurrent)
|
1389
1400
|
|
1390
1401
|
|
1391
1402
|
####################
|