icfs 0.1.3 → 0.2.0
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.
- 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/cache_elastic.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
|
require 'json'
|
13
15
|
require 'socket'
|
14
16
|
require_relative 'elastic'
|
@@ -42,7 +44,7 @@ class CacheElastic < Cache
|
|
42
44
|
"grant": { "type": "keyword" }
|
43
45
|
}}}
|
44
46
|
}}}
|
45
|
-
}'
|
47
|
+
}',
|
46
48
|
|
47
49
|
:log => '{
|
48
50
|
"mappings": { "_doc": { "properties": {
|
@@ -67,7 +69,7 @@ class CacheElastic < Cache
|
|
67
69
|
"case_hash": { "enabled": false },
|
68
70
|
"files_hash": { "enabled": false }
|
69
71
|
}}}
|
70
|
-
}'
|
72
|
+
}',
|
71
73
|
|
72
74
|
:entry => '{
|
73
75
|
"mappings": { "_doc": { "properties": {
|
@@ -94,7 +96,7 @@ class CacheElastic < Cache
|
|
94
96
|
"name": { "type": "text" }
|
95
97
|
}}
|
96
98
|
}}}
|
97
|
-
}'
|
99
|
+
}',
|
98
100
|
|
99
101
|
:action => '{
|
100
102
|
"mappings": { "_doc": { "properties": {
|
@@ -111,7 +113,7 @@ class CacheElastic < Cache
|
|
111
113
|
"tags": { "type": "keyword" }
|
112
114
|
}}
|
113
115
|
}}}
|
114
|
-
}'
|
116
|
+
}',
|
115
117
|
|
116
118
|
:index => '{
|
117
119
|
"mappings": { "_doc": { "properties": {
|
@@ -126,19 +128,19 @@ class CacheElastic < Cache
|
|
126
128
|
"content": { "type": "text" },
|
127
129
|
"tags": { "type": "keyword" }
|
128
130
|
}}}
|
129
|
-
}'
|
131
|
+
}',
|
130
132
|
|
131
133
|
:current => '{
|
132
134
|
"mappings": {"_doc": {
|
133
135
|
"enabled": false
|
134
136
|
}}
|
135
|
-
}'
|
137
|
+
}',
|
136
138
|
|
137
139
|
:lock => '{
|
138
140
|
"mappings": { "_doc": {
|
139
141
|
"enabled": false
|
140
142
|
}}
|
141
|
-
}'
|
143
|
+
}',
|
142
144
|
}.freeze
|
143
145
|
|
144
146
|
|
@@ -171,9 +173,9 @@ class CacheElastic < Cache
|
|
171
173
|
#
|
172
174
|
def lock_take(cid)
|
173
175
|
|
174
|
-
json = '{"client":"%s"}'
|
175
|
-
url = '%s/_doc/%s/_create'
|
176
|
-
head = {'Content-Type'
|
176
|
+
json = '{"client":"%s"}' % @name
|
177
|
+
url = '%s/_doc/%s/_create' % [@map[:lock], CGI.escape(cid)]
|
178
|
+
head = {'Content-Type' => 'application/json'}.freeze
|
177
179
|
|
178
180
|
# try to take
|
179
181
|
tries = 5
|
@@ -185,7 +187,7 @@ class CacheElastic < Cache
|
|
185
187
|
end
|
186
188
|
|
187
189
|
# failed to take lock
|
188
|
-
raise('Elasticsearch lock take failed: %s'
|
190
|
+
raise('Elasticsearch lock take failed: %s' % cid)
|
189
191
|
end
|
190
192
|
|
191
193
|
|
@@ -193,10 +195,10 @@ class CacheElastic < Cache
|
|
193
195
|
# (see Cache#lock_release)
|
194
196
|
#
|
195
197
|
def lock_release(cid)
|
196
|
-
url = '%s/_doc/%s'
|
198
|
+
url = '%s/_doc/%s' % [@map[:lock], CGI.escape(cid)]
|
197
199
|
resp = @es.run_request(:delete, url, '', {})
|
198
200
|
if !resp.success?
|
199
|
-
raise('Elasticsearch lock release failed: %s'
|
201
|
+
raise('Elasticsearch lock release failed: %s' % cid)
|
200
202
|
end
|
201
203
|
end
|
202
204
|
|
@@ -257,20 +259,20 @@ class CacheElastic < Cache
|
|
257
259
|
|
258
260
|
# build the query
|
259
261
|
must = [
|
260
|
-
_query_match('title'
|
262
|
+
_query_match('title', query[:title]),
|
261
263
|
].compact
|
262
264
|
filter = [
|
263
|
-
_query_term('tags'
|
264
|
-
_query_term('status'
|
265
|
-
_query_term('template'
|
265
|
+
_query_term('tags', query[:tags]),
|
266
|
+
_query_term('status', query[:status]),
|
267
|
+
_query_term('template', query[:template]),
|
266
268
|
].compact
|
267
269
|
access = [
|
268
|
-
_query_term('access.grant'
|
269
|
-
_query_term('access.perm'
|
270
|
+
_query_term('access.grant', query[:grantee]),
|
271
|
+
_query_term('access.perm', query[:perm]),
|
270
272
|
].compact
|
271
273
|
unless access.empty?
|
272
274
|
qu = (access.size == 1) ? access[0] : _query_bool(nil, access, nil, nil)
|
273
|
-
filter << _query_nested('access'
|
275
|
+
filter << _query_nested('access', qu)
|
274
276
|
end
|
275
277
|
req = { 'query' => _query_bool(must, filter, nil, nil) }
|
276
278
|
|
@@ -288,7 +290,7 @@ class CacheElastic < Cache
|
|
288
290
|
_page(query, req)
|
289
291
|
|
290
292
|
# run the search
|
291
|
-
url = @map[:case] + '/_search'
|
293
|
+
url = @map[:case] + '/_search'
|
292
294
|
body = JSON.generate(req)
|
293
295
|
head = { 'Content-Type' => 'application/json' }
|
294
296
|
resp = @es.run_request(:get, url, body, head)
|
@@ -300,11 +302,11 @@ class CacheElastic < Cache
|
|
300
302
|
|
301
303
|
# the Case results fields
|
302
304
|
ResultsCase = {
|
303
|
-
caseid: 'caseid'
|
304
|
-
template: 'template'
|
305
|
-
status: 'status'
|
306
|
-
title: 'title'
|
307
|
-
tags: 'tags'
|
305
|
+
caseid: 'caseid',
|
306
|
+
template: 'template',
|
307
|
+
status: 'status',
|
308
|
+
title: 'title',
|
309
|
+
tags: 'tags',
|
308
310
|
}.freeze
|
309
311
|
|
310
312
|
|
@@ -337,7 +339,7 @@ class CacheElastic < Cache
|
|
337
339
|
hl = hh['highlight']
|
338
340
|
|
339
341
|
if hl
|
340
|
-
snip =
|
342
|
+
snip = String.new
|
341
343
|
hl.each{|fn, ary| ary.each{|ht| snip << ht}}
|
342
344
|
else
|
343
345
|
snip = nil
|
@@ -371,7 +373,7 @@ class CacheElastic < Cache
|
|
371
373
|
obj[aa] = val.nil? ? [] : val
|
372
374
|
|
373
375
|
else
|
374
|
-
raise(ArgumentError, 'Not a valid field option'
|
376
|
+
raise(ArgumentError, 'Not a valid field option')
|
375
377
|
end
|
376
378
|
else
|
377
379
|
obj[aa] = src[bb]
|
@@ -428,7 +430,7 @@ class CacheElastic < Cache
|
|
428
430
|
# (see Cache#entry_read)
|
429
431
|
#
|
430
432
|
def entry_read(cid, enum)
|
431
|
-
_read(:entry, '%s.%d'
|
433
|
+
_read(:entry, '%s.%d' % [cid, enum])
|
432
434
|
end
|
433
435
|
|
434
436
|
|
@@ -436,7 +438,7 @@ class CacheElastic < Cache
|
|
436
438
|
# (see Cache#entry_write)
|
437
439
|
#
|
438
440
|
def entry_write(cid, enum, item)
|
439
|
-
_write(:entry, '%s.%d'
|
441
|
+
_write(:entry, '%s.%d' % [cid, enum], item)
|
440
442
|
end
|
441
443
|
|
442
444
|
|
@@ -460,23 +462,23 @@ class CacheElastic < Cache
|
|
460
462
|
|
461
463
|
# build the query
|
462
464
|
must = [
|
463
|
-
_query_match('title'
|
464
|
-
_query_match('content'
|
465
|
+
_query_match('title', query[:title]),
|
466
|
+
_query_match('content', query[:content]),
|
465
467
|
].compact
|
466
468
|
filter = [
|
467
|
-
_query_term('tags'
|
468
|
-
_query_term('caseid'
|
469
|
-
_query_times('time'
|
470
|
-
_query_term('action'
|
471
|
-
_query_term('index'
|
469
|
+
_query_term('tags', query[:tags]),
|
470
|
+
_query_term('caseid', query[:caseid]),
|
471
|
+
_query_times('time', query[:after], query[:before]),
|
472
|
+
_query_term('action', query[:action]),
|
473
|
+
_query_term('index', query[:index]),
|
472
474
|
].compact
|
473
475
|
stats = [
|
474
|
-
_query_term('stats.name'
|
475
|
-
_query_term('stats.credit'
|
476
|
+
_query_term('stats.name', query[:stat]),
|
477
|
+
_query_term('stats.credit', query[:credit]),
|
476
478
|
].compact
|
477
479
|
unless stats.empty?
|
478
480
|
qu = (stats.size == 1) ? stats[0] : _query_bool(nil, stats, nil, nil)
|
479
|
-
filter << _query_nested('stats'
|
481
|
+
filter << _query_nested('stats', qu)
|
480
482
|
end
|
481
483
|
req = { 'query' => _query_bool(must, filter, nil, nil) }
|
482
484
|
|
@@ -511,7 +513,7 @@ class CacheElastic < Cache
|
|
511
513
|
_page(query, req)
|
512
514
|
|
513
515
|
# run the search
|
514
|
-
url = @map[:entry] + '/_search'
|
516
|
+
url = @map[:entry] + '/_search'
|
515
517
|
body = JSON.generate(req)
|
516
518
|
head = { 'Content-Type' => 'application/json' }
|
517
519
|
resp = @es.run_request(:get, url, body, head)
|
@@ -523,16 +525,16 @@ class CacheElastic < Cache
|
|
523
525
|
|
524
526
|
# Entry search results fields
|
525
527
|
ResultsEntry = {
|
526
|
-
caseid: 'caseid'
|
527
|
-
entry: 'entry'
|
528
|
-
time: 'time'
|
529
|
-
title: 'title'
|
530
|
-
tags: 'tags'
|
531
|
-
perms: ['perms'
|
532
|
-
action: ['action'
|
533
|
-
index: ['index'
|
534
|
-
files: ['files'
|
535
|
-
stats: ['stats'
|
528
|
+
caseid: 'caseid',
|
529
|
+
entry: 'entry',
|
530
|
+
time: 'time',
|
531
|
+
title: 'title',
|
532
|
+
tags: 'tags',
|
533
|
+
perms: ['perms', :empty],
|
534
|
+
action: ['action', :zero],
|
535
|
+
index: ['index', :size],
|
536
|
+
files: ['files', :size],
|
537
|
+
stats: ['stats', :size],
|
536
538
|
}.freeze
|
537
539
|
|
538
540
|
|
@@ -541,7 +543,7 @@ class CacheElastic < Cache
|
|
541
543
|
# (see Cache#action_read)
|
542
544
|
#
|
543
545
|
def action_read(cid, anum)
|
544
|
-
_read(:action, '%s.%d'
|
546
|
+
_read(:action, '%s.%d' % [cid, anum])
|
545
547
|
end
|
546
548
|
|
547
549
|
|
@@ -549,7 +551,7 @@ class CacheElastic < Cache
|
|
549
551
|
# (see Cache#action_write)
|
550
552
|
#
|
551
553
|
def action_write(cid, anum, item)
|
552
|
-
_write(:action, '%s.%d'
|
554
|
+
_write(:action, '%s.%d' % [cid, anum], item)
|
553
555
|
end
|
554
556
|
|
555
557
|
|
@@ -560,23 +562,23 @@ class CacheElastic < Cache
|
|
560
562
|
|
561
563
|
# build the query
|
562
564
|
task_must = [
|
563
|
-
_query_match('tasks.title'
|
565
|
+
_query_match('tasks.title', query[:title])
|
564
566
|
].compact
|
565
567
|
task_filter = [
|
566
|
-
_query_term('tasks.assigned'
|
567
|
-
_query_term('tasks.status'
|
568
|
-
_query_term('tasks.flag'
|
569
|
-
_query_times('tasks.time'
|
570
|
-
_query_term('tasks.tags'
|
568
|
+
_query_term('tasks.assigned', query[:assigned]),
|
569
|
+
_query_term('tasks.status', query[:status]),
|
570
|
+
_query_term('tasks.flag', query[:flag]),
|
571
|
+
_query_times('tasks.time', query[:after], query[:before]),
|
572
|
+
_query_term('tasks.tags', query[:tags]),
|
571
573
|
].compact
|
572
574
|
must = [
|
573
575
|
_query_nested(
|
574
|
-
'tasks'
|
576
|
+
'tasks',
|
575
577
|
_query_bool(task_must, task_filter, nil, nil)
|
576
578
|
)
|
577
579
|
]
|
578
580
|
filter = [
|
579
|
-
_query_term('caseid'
|
581
|
+
_query_term('caseid', query[:caseid])
|
580
582
|
].compact
|
581
583
|
req = { 'query' => _query_bool(must, filter, nil, nil) }
|
582
584
|
|
@@ -595,9 +597,9 @@ class CacheElastic < Cache
|
|
595
597
|
'tasks.time' => {
|
596
598
|
'order' => srt,
|
597
599
|
'nested' => {
|
598
|
-
'path' => 'tasks'
|
600
|
+
'path' => 'tasks',
|
599
601
|
'filter' => _query_term(
|
600
|
-
'tasks.assigned'
|
602
|
+
'tasks.assigned', query[:assigned])
|
601
603
|
}
|
602
604
|
}
|
603
605
|
},
|
@@ -609,7 +611,7 @@ class CacheElastic < Cache
|
|
609
611
|
_page(query, req)
|
610
612
|
|
611
613
|
# run the search
|
612
|
-
url = @map[:action] + '/_search'
|
614
|
+
url = @map[:action] + '/_search'
|
613
615
|
body = JSON.generate(req)
|
614
616
|
head = { 'Content-Type' => 'application/json' }
|
615
617
|
resp = @es.run_request(:get, url, body, head)
|
@@ -634,7 +636,7 @@ class CacheElastic < Cache
|
|
634
636
|
# (see Cache#index_write)
|
635
637
|
#
|
636
638
|
def index_write(cid, xnum, item)
|
637
|
-
_write(:index, '%s.%d'
|
639
|
+
_write(:index, '%s.%d' % [cid, xnum], item)
|
638
640
|
end
|
639
641
|
|
640
642
|
|
@@ -642,7 +644,7 @@ class CacheElastic < Cache
|
|
642
644
|
# (see Cache#index_read)
|
643
645
|
#
|
644
646
|
def index_read(cid, xnum)
|
645
|
-
_read(:index, '%s.%d'
|
647
|
+
_read(:index, '%s.%d' % [cid, xnum])
|
646
648
|
end
|
647
649
|
|
648
650
|
|
@@ -652,13 +654,13 @@ class CacheElastic < Cache
|
|
652
654
|
|
653
655
|
# build the query
|
654
656
|
must = [
|
655
|
-
_query_match('title'
|
656
|
-
_query_match('content'
|
657
|
+
_query_match('title', query[:title]),
|
658
|
+
_query_match('content', query[:content]),
|
657
659
|
].compact
|
658
660
|
filter = [
|
659
|
-
_query_term('caseid'
|
660
|
-
_query_term('tags'
|
661
|
-
_query_prefix('title.raw'
|
661
|
+
_query_term('caseid', query[:caseid]),
|
662
|
+
_query_term('tags', query[:tags]),
|
663
|
+
_query_prefix('title.raw', query[:prefix]),
|
662
664
|
].compact
|
663
665
|
req = { 'query' => _query_bool(must, filter, nil, nil) }
|
664
666
|
|
@@ -704,7 +706,7 @@ class CacheElastic < Cache
|
|
704
706
|
_page(query, req)
|
705
707
|
|
706
708
|
# run the search
|
707
|
-
url = @map[:index] + '/_search'
|
709
|
+
url = @map[:index] + '/_search'
|
708
710
|
body = JSON.generate(req)
|
709
711
|
head = { 'Content-Type' => 'application/json' }
|
710
712
|
resp = @es.run_request(:get, url, body, head)
|
@@ -716,10 +718,10 @@ class CacheElastic < Cache
|
|
716
718
|
|
717
719
|
# Index search results fields
|
718
720
|
ResultsIndex = {
|
719
|
-
caseid: 'caseid'
|
720
|
-
index: 'index'
|
721
|
-
title: 'title'
|
722
|
-
tags: 'tags'
|
721
|
+
caseid: 'caseid',
|
722
|
+
index: 'index',
|
723
|
+
title: 'title',
|
724
|
+
tags: 'tags',
|
723
725
|
}.freeze
|
724
726
|
|
725
727
|
|
@@ -729,8 +731,8 @@ class CacheElastic < Cache
|
|
729
731
|
def index_tags(query)
|
730
732
|
|
731
733
|
# build the query
|
732
|
-
ag = _agg_terms('tags'
|
733
|
-
qu = _query_term('caseid'
|
734
|
+
ag = _agg_terms('tags', 'tags', nil)
|
735
|
+
qu = _query_term('caseid', query[:caseid])
|
734
736
|
qu = _query_constant(qu)
|
735
737
|
req = {
|
736
738
|
'query' => qu,
|
@@ -739,11 +741,11 @@ class CacheElastic < Cache
|
|
739
741
|
}
|
740
742
|
|
741
743
|
# run the search
|
742
|
-
url = @map[:index] + '/_search'
|
744
|
+
url = @map[:index] + '/_search'
|
743
745
|
body = JSON.generate(req)
|
744
|
-
head = { 'Content-Type' => 'application/json'
|
746
|
+
head = { 'Content-Type' => 'application/json' }
|
745
747
|
resp = @es.run_request(:get, url, body, head)
|
746
|
-
raise 'search failed'
|
748
|
+
raise 'search failed' if !resp.success?
|
747
749
|
|
748
750
|
# extract tags
|
749
751
|
rh = JSON.parse(resp.body)
|
@@ -769,7 +771,7 @@ class CacheElastic < Cache
|
|
769
771
|
# (see Cache#log_read)
|
770
772
|
#
|
771
773
|
def log_read(cid, lnum)
|
772
|
-
_read(:log, '%s.%d'
|
774
|
+
_read(:log, '%s.%d' % [cid, lnum])
|
773
775
|
end
|
774
776
|
|
775
777
|
|
@@ -777,20 +779,20 @@ class CacheElastic < Cache
|
|
777
779
|
# (see Cache#log_write)
|
778
780
|
#
|
779
781
|
def log_write(cid, lnum, item)
|
780
|
-
_write(:log, '%s.%d'
|
782
|
+
_write(:log, '%s.%d' % [cid, lnum], item)
|
781
783
|
end
|
782
784
|
|
783
785
|
|
784
786
|
# Log search results fields
|
785
787
|
ResultsLog = {
|
786
|
-
caseid: 'caseid'
|
787
|
-
log: 'log'
|
788
|
-
time: 'time'
|
789
|
-
user: 'user'
|
790
|
-
entry: ['entry'
|
791
|
-
index: ['index'
|
792
|
-
action: ['action'
|
793
|
-
files: ['files_hash'
|
788
|
+
caseid: 'caseid',
|
789
|
+
log: 'log',
|
790
|
+
time: 'time',
|
791
|
+
user: 'user',
|
792
|
+
entry: ['entry', :sub, 'num'].freeze,
|
793
|
+
index: ['index', :sub, 'num'].freeze,
|
794
|
+
action: ['action', :sub, 'num'].freeze,
|
795
|
+
files: ['files_hash', :size].freeze,
|
794
796
|
}.freeze
|
795
797
|
|
796
798
|
|
@@ -801,12 +803,12 @@ class CacheElastic < Cache
|
|
801
803
|
|
802
804
|
# build the query
|
803
805
|
filter = [
|
804
|
-
_query_term('caseid'
|
805
|
-
_query_times('times'
|
806
|
-
_query_term('user'
|
807
|
-
_query_term('entry.num'
|
808
|
-
_query_term('index.num'
|
809
|
-
_query_term('action.num'
|
806
|
+
_query_term('caseid', query[:caseid]),
|
807
|
+
_query_times('times', query[:after], query[:before]),
|
808
|
+
_query_term('user', query[:user]),
|
809
|
+
_query_term('entry.num', query[:entry]),
|
810
|
+
_query_term('index.num', query[:index]),
|
811
|
+
_query_term('action.num', query[:action]),
|
810
812
|
].compact
|
811
813
|
req = { 'query' => _query_bool(nil, filter, nil, nil) }
|
812
814
|
|
@@ -828,7 +830,7 @@ class CacheElastic < Cache
|
|
828
830
|
_page(query, req)
|
829
831
|
|
830
832
|
# run the search
|
831
|
-
url = @map[:log] + '/_search'
|
833
|
+
url = @map[:log] + '/_search'
|
832
834
|
body = JSON.generate(req)
|
833
835
|
head = { 'Content-Type' => 'application/json' }
|
834
836
|
resp = @es.run_request(:get, url, body, head)
|
@@ -948,18 +950,18 @@ class CacheElastic < Cache
|
|
948
950
|
def stats(query)
|
949
951
|
|
950
952
|
# aggs
|
951
|
-
ag = _agg_stats('vals'
|
952
|
-
ag = _agg_terms('stats'
|
953
|
+
ag = _agg_stats('vals', 'stats.value')
|
954
|
+
ag = _agg_terms('stats', 'stats.name', ag)
|
953
955
|
if query[:credit]
|
954
|
-
cd = _query_term('stats.credit'
|
955
|
-
ag = _agg_filter('credit'
|
956
|
+
cd = _query_term('stats.credit', query[:credit])
|
957
|
+
ag = _agg_filter('credit', cd, ag)
|
956
958
|
end
|
957
|
-
ag = _agg_nested('nested'
|
959
|
+
ag = _agg_nested('nested', 'stats', ag)
|
958
960
|
|
959
961
|
# build the query
|
960
962
|
filt = [
|
961
|
-
_query_term('caseid'
|
962
|
-
_query_times('time'
|
963
|
+
_query_term('caseid', query[:caseid]),
|
964
|
+
_query_times('time', query[:after], query[:before]),
|
963
965
|
].compact
|
964
966
|
qu = _query_bool(nil, filt, nil, nil)
|
965
967
|
|
@@ -971,7 +973,7 @@ class CacheElastic < Cache
|
|
971
973
|
}
|
972
974
|
|
973
975
|
# run the search
|
974
|
-
url = @map[:entry] + '/_search'
|
976
|
+
url = @map[:entry] + '/_search'
|
975
977
|
body = JSON.generate(req)
|
976
978
|
head = { 'Content-Type' => 'application/json' }
|
977
979
|
resp = @es.run_request(:get, url, body, head)
|
@@ -1018,8 +1020,8 @@ class CacheElastic < Cache
|
|
1018
1020
|
def entry_tags(query)
|
1019
1021
|
|
1020
1022
|
# build the query
|
1021
|
-
ag = _agg_terms('tags'
|
1022
|
-
qu = _query_term('caseid'
|
1023
|
+
ag = _agg_terms('tags', 'tags', nil)
|
1024
|
+
qu = _query_term('caseid', query[:caseid])
|
1023
1025
|
qu = _query_constant(qu)
|
1024
1026
|
req = {
|
1025
1027
|
'query' => qu,
|
@@ -1028,7 +1030,7 @@ class CacheElastic < Cache
|
|
1028
1030
|
}
|
1029
1031
|
|
1030
1032
|
# run the search
|
1031
|
-
url = @map[:entry] + '/_search'
|
1033
|
+
url = @map[:entry] + '/_search'
|
1032
1034
|
body = JSON.generate(req)
|
1033
1035
|
head = { 'Content-Type' => 'application/json' }
|
1034
1036
|
resp = @es.run_request(:get, url, body, head)
|
@@ -1061,19 +1063,19 @@ class CacheElastic < Cache
|
|
1061
1063
|
|
1062
1064
|
# build the query
|
1063
1065
|
filter = [
|
1064
|
-
_query_term('status'
|
1065
|
-
_query_term('template'
|
1066
|
+
_query_term('status', query[:status]),
|
1067
|
+
_query_term('template', query[:template]),
|
1066
1068
|
].compact
|
1067
1069
|
access = [
|
1068
|
-
_query_term('access.grant'
|
1069
|
-
_query_term('access.perm'
|
1070
|
+
_query_term('access.grant', query[:grantee]),
|
1071
|
+
_query_term('access.perm', query[:perm]),
|
1070
1072
|
].compact
|
1071
1073
|
unless access.empty?
|
1072
1074
|
qu = (access.size == 1) ? access[0] : _query_bool(nil, access, nil, nil)
|
1073
|
-
filter << _query_nested('access'
|
1075
|
+
filter << _query_nested('access', qu)
|
1074
1076
|
end
|
1075
1077
|
qu = _query_bool(nil, filter, nil, nil)
|
1076
|
-
ag = _agg_terms('tags'
|
1078
|
+
ag = _agg_terms('tags', 'tags', nil)
|
1077
1079
|
req = {
|
1078
1080
|
'query' => qu,
|
1079
1081
|
'aggs' => ag,
|
@@ -1081,7 +1083,7 @@ class CacheElastic < Cache
|
|
1081
1083
|
}
|
1082
1084
|
|
1083
1085
|
# run the search
|
1084
|
-
url = @map[:case] + '/_search'
|
1086
|
+
url = @map[:case] + '/_search'
|
1085
1087
|
body = JSON.generate(req)
|
1086
1088
|
head = { 'Content-Type' => 'application/json' }
|
1087
1089
|
resp = @es.run_request(:get, url, body, head)
|
@@ -1113,17 +1115,17 @@ class CacheElastic < Cache
|
|
1113
1115
|
|
1114
1116
|
# build the query
|
1115
1117
|
task_filter = [
|
1116
|
-
_query_term('tasks.assigned'
|
1117
|
-
_query_term('tasks.status'
|
1118
|
-
_query_term('tasks.flag'
|
1119
|
-
_query_times('tasks.time'
|
1118
|
+
_query_term('tasks.assigned', query[:assigned]),
|
1119
|
+
_query_term('tasks.status', query[:status]),
|
1120
|
+
_query_term('tasks.flag', query[:flag]),
|
1121
|
+
_query_times('tasks.time', query[:after], query[:before]),
|
1120
1122
|
].compact
|
1121
1123
|
qu_filt = _query_bool(nil, task_filter, nil, nil)
|
1122
|
-
ag = _agg_terms('tags'
|
1123
|
-
ag = _agg_filter('filt'
|
1124
|
-
ag = _agg_nested('nest'
|
1124
|
+
ag = _agg_terms('tags', 'tasks.tags', nil)
|
1125
|
+
ag = _agg_filter('filt', qu_filt, ag)
|
1126
|
+
ag = _agg_nested('nest', 'tasks', ag)
|
1125
1127
|
if query[:caseid]
|
1126
|
-
qu = _query_term('caseid'
|
1128
|
+
qu = _query_term('caseid', query[:caseid])
|
1127
1129
|
else
|
1128
1130
|
qu = _query_all()
|
1129
1131
|
end
|
@@ -1134,7 +1136,7 @@ class CacheElastic < Cache
|
|
1134
1136
|
}
|
1135
1137
|
|
1136
1138
|
# run the search
|
1137
|
-
url = @map[:action] + '/_search'
|
1139
|
+
url = @map[:action] + '/_search'
|
1138
1140
|
body = JSON.generate(req)
|
1139
1141
|
head = { 'Content-Type' => 'application/json' }
|
1140
1142
|
resp = @es.run_request(:get, url, body, head)
|
@@ -9,9 +9,10 @@
|
|
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
|
-
module Web
|
15
16
|
|
16
17
|
##########################################################################
|
17
18
|
# Configuration storage interface
|
@@ -102,7 +103,6 @@ class Config
|
|
102
103
|
def save; raise NotImplementedError; end
|
103
104
|
|
104
105
|
|
105
|
-
end # class ICFS::
|
106
|
+
end # class ICFS::Config
|
106
107
|
|
107
|
-
end # module ICFS::Web
|
108
108
|
end # module ICFS
|
@@ -9,10 +9,11 @@
|
|
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
|
require_relative 'config'
|
13
15
|
|
14
16
|
module ICFS
|
15
|
-
module Web
|
16
17
|
|
17
18
|
##########################################################################
|
18
19
|
# Implement Config with a Redis cache
|
@@ -33,7 +34,7 @@ class ConfigRedis < Config
|
|
33
34
|
super(base.defaults)
|
34
35
|
@redis = redis
|
35
36
|
@base = base
|
36
|
-
@pre = opts[:prefix] || ''
|
37
|
+
@pre = opts[:prefix] || ''
|
37
38
|
@exp = opts[:expires] || 1*60*60 # 1 hour default
|
38
39
|
end
|
39
40
|
|
@@ -42,14 +43,14 @@ class ConfigRedis < Config
|
|
42
43
|
# (see Config#load)
|
43
44
|
#
|
44
45
|
def load(unam)
|
45
|
-
Items.validate(unam, 'User/Role/Group name'
|
46
|
+
Items.validate(unam, 'User/Role/Group name', Items::FieldUsergrp)
|
46
47
|
@unam = unam.dup
|
47
48
|
key = _key(unam)
|
48
49
|
|
49
50
|
# try cache
|
50
51
|
json = @redis.get(key)
|
51
52
|
if json
|
52
|
-
@data = Items.parse(json, 'Config values'
|
53
|
+
@data = Items.parse(json, 'Config values', Config::ValConfig)
|
53
54
|
return true
|
54
55
|
end
|
55
56
|
|
@@ -64,15 +65,14 @@ class ConfigRedis < Config
|
|
64
65
|
# (see Config#save)
|
65
66
|
#
|
66
67
|
def save()
|
67
|
-
raise(RuntimeError, 'Save requires a user name'
|
68
|
-
json = Items.generate(@data, 'Config values'
|
68
|
+
raise(RuntimeError, 'Save requires a user name') if !@unam
|
69
|
+
json = Items.generate(@data, 'Config values', Config::ValConfig)
|
69
70
|
@redis.del(_key(@unam))
|
70
71
|
@base.data = @data
|
71
72
|
@base.save
|
72
73
|
end # def save()
|
73
74
|
|
74
75
|
|
75
|
-
end # class ICFS::
|
76
|
+
end # class ICFS::Config
|
76
77
|
|
77
|
-
end # module ICFS::Web
|
78
78
|
end # module ICFS
|