icfs 0.2.0 → 0.3.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/data/icfs.css +7 -1
- data/data/icfs.js +17 -19
- data/devel/run/base.rb +2 -1
- data/devel/run/case-backup.rb +24 -0
- data/devel/run/case-restore.rb +24 -0
- data/devel/run/copy-s3.rb +2 -0
- data/devel/run/init-icfs.rb +7 -37
- data/devel/run/init-template.rb +33 -0
- data/lib/icfs/api.rb +92 -48
- data/lib/icfs/cache_elastic.rb +10 -2
- data/lib/icfs/config.rb +4 -3
- data/lib/icfs/items.rb +21 -5
- data/lib/icfs/utils/backup.rb +22 -18
- data/lib/icfs/utils/check.rb +24 -22
- data/lib/icfs/web/client.rb +302 -160
- data/lib/icfs.rb +70 -1
- metadata +5 -3
- data/bin/icfs_demo_fcgi.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ba64d02837a0591aee2cab20c11795beffa59f3ec3dce2014ac7dd0b55e89e5
|
4
|
+
data.tar.gz: 1b452562fa4df0cf870eb0ed5bbbf0f686b4ba78579e47e7ce075e84e18b1954
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '02909a341866abc4eb1eaa844317dd02b72ed55c59b0df518f3e54af06a024f6cb4ac2ea8f14a2b64b99e60bdd9dc2bc87ceee421ed591c498db1f0e5c4305c4'
|
7
|
+
data.tar.gz: 562c4de6f8605b2ab7b414101642488a93b98fa94157ba4408ed640b6944f8cee33ecb3f710be87570760fd7d0fc6249c2b353163173f64ea53d52624b7b91fe
|
data/data/icfs.css
CHANGED
@@ -200,6 +200,12 @@ div.list-int {
|
|
200
200
|
}
|
201
201
|
|
202
202
|
|
203
|
+
div.list-int-sm {
|
204
|
+
width: 2em;
|
205
|
+
padding: 0 0.15em 0 0.15em;
|
206
|
+
}
|
207
|
+
|
208
|
+
|
203
209
|
div.list-perm {
|
204
210
|
width: 15em;
|
205
211
|
padding: 0 0.15em 0 0.15em;
|
@@ -238,7 +244,7 @@ div.list-text-m {
|
|
238
244
|
|
239
245
|
|
240
246
|
div.list-time {
|
241
|
-
width:
|
247
|
+
width: 15em;
|
242
248
|
padding: 0 0.15em 0 0.15em;
|
243
249
|
}
|
244
250
|
|
data/data/icfs.js
CHANGED
@@ -167,6 +167,23 @@
|
|
167
167
|
|
168
168
|
// Entry
|
169
169
|
|
170
|
+
///////////////////////////////////////////////
|
171
|
+
// Enable/disable editing the entry
|
172
|
+
function entEnable(){
|
173
|
+
var ena = document.getElementById("ent-ena");
|
174
|
+
var bdy = document.getElementById("ent-body");
|
175
|
+
|
176
|
+
var enabled = ena.getAttribute("value");
|
177
|
+
if( enabled == "true" ){
|
178
|
+
ena.setAttribute("value", "false");
|
179
|
+
bdy.setAttribute("class", "ent-body hidden");
|
180
|
+
} else {
|
181
|
+
ena.setAttribute("value", "true");
|
182
|
+
bdy.setAttribute("class", "ent-body");
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
|
170
187
|
///////////////////////////////////////////////
|
171
188
|
// Add an index
|
172
189
|
function entAddIndex(){
|
@@ -376,25 +393,6 @@
|
|
376
393
|
|
377
394
|
// Action
|
378
395
|
|
379
|
-
///////////////////////////////////////////////
|
380
|
-
// Enable/disable editing the action
|
381
|
-
function actEnable(){
|
382
|
-
var but = document.getElementById("act-task-add");
|
383
|
-
var ena = document.getElementById("act-ena");
|
384
|
-
var tsk = document.getElementById("act-tasks");
|
385
|
-
|
386
|
-
var enabled = ena.getAttribute("value");
|
387
|
-
if( enabled == "true" ){
|
388
|
-
ena.setAttribute("value", "false");
|
389
|
-
tsk.setAttribute("class", "sect-right hidden");
|
390
|
-
but.setAttribute("class", "sect-right invisible");
|
391
|
-
} else {
|
392
|
-
ena.setAttribute("value", "true");
|
393
|
-
tsk.setAttribute("class", "sect-right");
|
394
|
-
but.setAttribute("class", "sect-right");
|
395
|
-
}
|
396
|
-
}
|
397
|
-
|
398
396
|
|
399
397
|
///////////////////////////////////////////////
|
400
398
|
// Add a row to a task
|
data/devel/run/base.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Investigative Case File System
|
4
|
+
#
|
5
|
+
# Copyright 2019 by Graham A. Field
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License version 3.
|
9
|
+
#
|
10
|
+
# This program is distributed WITHOUT ANY WARRANTY; without even the
|
11
|
+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
12
|
+
|
13
|
+
# usage: <case-backup> <fs_store_dir> <caseid>
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative 'base'
|
18
|
+
require_relative '../../lib/icfs/store_fs'
|
19
|
+
require_relative '../../lib/icfs/utils/backup'
|
20
|
+
|
21
|
+
base = get_base()
|
22
|
+
backup = ICFS::Utils::Backup.new(base[:cache], base[:store], base[:log])
|
23
|
+
dst = ICFS::StoreFs.new(ARGV[0])
|
24
|
+
backup.copy(ARGV[1], dst)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Investigative Case File System
|
4
|
+
#
|
5
|
+
# Copyright 2019 by Graham A. Field
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License version 3.
|
9
|
+
#
|
10
|
+
# This program is distributed WITHOUT ANY WARRANTY; without even the
|
11
|
+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
12
|
+
|
13
|
+
# usage: <case-restore> <fs_store_dir> <caseid>
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative 'base'
|
18
|
+
require_relative '../../lib/icfs/store_fs'
|
19
|
+
require_relative '../../lib/utils/backup'
|
20
|
+
|
21
|
+
base = get_base()
|
22
|
+
backup = ICFS::Utils::Backup.new(base[:cache], base[:store], base[:log])
|
23
|
+
src = ICFS::StoreFs.new(ARGV[0])
|
24
|
+
backup.restore(ARGV[1], src)
|
data/devel/run/copy-s3.rb
CHANGED
@@ -10,6 +10,8 @@
|
|
10
10
|
# This program is distributed WITHOUT ANY WARRANTY; without even the
|
11
11
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
12
12
|
|
13
|
+
# usage: ./copy-s3.rb <source_dir> <prefix>
|
14
|
+
|
13
15
|
# frozen_string_literal: true
|
14
16
|
|
15
17
|
require 'aws-sdk-s3'
|
data/devel/run/init-icfs.rb
CHANGED
@@ -18,17 +18,6 @@ require 'aws-sdk-s3'
|
|
18
18
|
|
19
19
|
require_relative '../../lib/icfs'
|
20
20
|
require_relative '../../lib/icfs/cache_elastic'
|
21
|
-
require_relative '../../lib/icfs/store_s3'
|
22
|
-
|
23
|
-
|
24
|
-
# Minio config
|
25
|
-
Aws.config.update(
|
26
|
-
endpoint: 'http://minio:9000',
|
27
|
-
access_key_id: 'minio_key',
|
28
|
-
secret_access_key: 'minio_secret',
|
29
|
-
force_path_style: true,
|
30
|
-
region: 'us-east-1'
|
31
|
-
)
|
32
21
|
|
33
22
|
# default mapping
|
34
23
|
map = {
|
@@ -42,10 +31,15 @@ map = {
|
|
42
31
|
}.freeze
|
43
32
|
|
44
33
|
# base items
|
45
|
-
s3 = Aws::S3::Client.new
|
34
|
+
s3 = Aws::S3::Client.new(
|
35
|
+
endpoint: 'http://minio:9000',
|
36
|
+
access_key_id: 'minio_key',
|
37
|
+
secret_access_key: 'minio_secret',
|
38
|
+
force_path_style: true,
|
39
|
+
region: 'us-east-1'
|
40
|
+
)
|
46
41
|
es = Faraday.new('http://elastic:9200')
|
47
42
|
cache = ICFS::CacheElastic.new(map, es)
|
48
|
-
store = ICFS::StoreS3.new(s3, 'icfs', 'case/')
|
49
43
|
|
50
44
|
# create the indexes
|
51
45
|
cache.create(ICFS::CacheElastic::Maps)
|
@@ -54,27 +48,3 @@ puts "Indexes created"
|
|
54
48
|
# create a bucket
|
55
49
|
s3.create_bucket(bucket: 'icfs')
|
56
50
|
puts "S3 bucket created"
|
57
|
-
|
58
|
-
api = ICFS::Api.new([], nil, cache, store)
|
59
|
-
|
60
|
-
# add a template
|
61
|
-
tmpl = {
|
62
|
-
'template' => true,
|
63
|
-
'status' => true,
|
64
|
-
'title' => 'Test template',
|
65
|
-
'access' => [
|
66
|
-
{
|
67
|
-
'perm' => '[manage]',
|
68
|
-
'grant' => [
|
69
|
-
'role2'
|
70
|
-
]
|
71
|
-
}
|
72
|
-
]
|
73
|
-
}
|
74
|
-
ent = {
|
75
|
-
'caseid' => 'test_tmpl',
|
76
|
-
'title' => 'Create template',
|
77
|
-
'content' => 'To test'
|
78
|
-
}
|
79
|
-
api.case_create(ent, tmpl, nil, 'user1')
|
80
|
-
puts "Create template"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Investigative Case File System
|
4
|
+
#
|
5
|
+
# Copyright 2019 by Graham A. Field
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License version 3.
|
9
|
+
#
|
10
|
+
# This program is distributed WITHOUT ANY WARRANTY; without even the
|
11
|
+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
12
|
+
|
13
|
+
# usage: ./init-template.sh <template.json> <user>
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative 'base'
|
18
|
+
|
19
|
+
json = File.read(ARGV[0])
|
20
|
+
tmpl = ICFS::Items.parse(json, 'Template', ICFS::Items::ItemCase)
|
21
|
+
tmpl.delete('icfs')
|
22
|
+
tmpl.delete('log')
|
23
|
+
|
24
|
+
ent = {
|
25
|
+
'caseid' => tmpl['caseid'],
|
26
|
+
'title' => 'Create case',
|
27
|
+
'content' => 'Added case using manual script',
|
28
|
+
}
|
29
|
+
|
30
|
+
base = get_base()
|
31
|
+
api = base[:api]
|
32
|
+
|
33
|
+
api.case_create(ent, tmpl, nil, ARGV[1])
|
data/lib/icfs/api.rb
CHANGED
@@ -518,6 +518,7 @@ class Api
|
|
518
518
|
after: Validate::IsIntPos,
|
519
519
|
before: Validate::IsIntPos,
|
520
520
|
user: Items::FieldUsergrp,
|
521
|
+
case_edit: Validate::IsBoolean,
|
521
522
|
entry: Validate::IsIntPos,
|
522
523
|
index: Validate::IsIntPos,
|
523
524
|
action: Validate::IsIntPos,
|
@@ -908,6 +909,13 @@ class Api
|
|
908
909
|
Items.validate(ent, 'entry', Items::ItemEntryNew)
|
909
910
|
Items.validate(cse, 'case', Items::ItemCaseEdit)
|
910
911
|
|
912
|
+
# get caseid
|
913
|
+
cid = ent['caseid']
|
914
|
+
cid ||= cse['caseid']
|
915
|
+
unless cid
|
916
|
+
raise(Error::Values, 'No caseid provided')
|
917
|
+
end
|
918
|
+
|
911
919
|
# access users/roles/groups are valid, unless manually specifying user
|
912
920
|
unless unam
|
913
921
|
cse["access"].each do |acc|
|
@@ -953,11 +961,11 @@ class Api
|
|
953
961
|
# Prep
|
954
962
|
|
955
963
|
# case
|
956
|
-
cid = ent['caseid']
|
957
964
|
cse['icfs'] = 1
|
958
965
|
cse['caseid'] = cid
|
959
966
|
cse['log'] = 1
|
960
967
|
cse['tags'] ||= [ ICFS::TagNone ]
|
968
|
+
cse['entry'] = 1
|
961
969
|
citem = Items.generate(cse, 'case', Items::ItemCase)
|
962
970
|
|
963
971
|
# entry
|
@@ -979,7 +987,10 @@ class Api
|
|
979
987
|
'entry' => {
|
980
988
|
'num' => 1,
|
981
989
|
},
|
982
|
-
'
|
990
|
+
'case' => {
|
991
|
+
'set' => true,
|
992
|
+
'hash' => ICFS.hash(citem),
|
993
|
+
},
|
983
994
|
}
|
984
995
|
log['files_hash'] = fhash if fhash
|
985
996
|
|
@@ -1040,7 +1051,7 @@ class Api
|
|
1040
1051
|
###############################################
|
1041
1052
|
# Write items to a case
|
1042
1053
|
#
|
1043
|
-
# @param ent [Hash] Entry to record,
|
1054
|
+
# @param ent [Hash] Entry to record, optional
|
1044
1055
|
# @param act [Hash, Nilclass] Action to record, optional
|
1045
1056
|
# @param idx [Hash, Nilclass] Index to record, optional
|
1046
1057
|
# @param cse [Hash, Nilclass] Case to record, optional
|
@@ -1051,22 +1062,36 @@ class Api
|
|
1051
1062
|
# Sanity checks
|
1052
1063
|
|
1053
1064
|
# form & content
|
1054
|
-
if
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1065
|
+
if ent
|
1066
|
+
if (act || idx || cse)
|
1067
|
+
Items.validate(ent, 'New Entry', Items::ItemEntryNew)
|
1068
|
+
else
|
1069
|
+
Items.validate(ent, 'Editable Entry', Items::ItemEntryEdit)
|
1070
|
+
end
|
1058
1071
|
end
|
1059
1072
|
Items.validate(act, 'action', Items::ItemActionEdit) if act
|
1060
1073
|
Items.validate(idx, 'index', Items::ItemIndexEdit) if idx
|
1061
1074
|
Items.validate(cse, 'case', Items::ItemCaseEdit) if cse
|
1062
1075
|
|
1063
|
-
#
|
1064
|
-
|
1065
|
-
|
1076
|
+
# get caseid
|
1077
|
+
cid ||= ent['caseid'] if ent
|
1078
|
+
cid ||= cse['caseid'] if cse
|
1079
|
+
cid ||= act['caseid'] if act
|
1080
|
+
cid ||= idx['caseid'] if idx
|
1081
|
+
unless cid
|
1082
|
+
raise(Error::Values, 'No caseid provided')
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
# no conflicting caseids
|
1086
|
+
if( (cse && cse['caseid'] && cse['caseid'] != cid) ||
|
1087
|
+
(act && act['caseid'] && act['caseid'] != cid) ||
|
1088
|
+
(idx && idx['caseid'] && idx['caseid'] != cid) )
|
1089
|
+
raise(Error::Values, 'Conflicting caseids provided')
|
1066
1090
|
end
|
1067
1091
|
|
1068
1092
|
# no changing the action
|
1069
|
-
if act && ent
|
1093
|
+
if( act && ent && ent['action'] && act['action'] &&
|
1094
|
+
act['action'] != ent['action'] )
|
1070
1095
|
raise(Error::Conflict, 'May not change entry\'s action')
|
1071
1096
|
end
|
1072
1097
|
|
@@ -1103,17 +1128,21 @@ class Api
|
|
1103
1128
|
|
1104
1129
|
####################
|
1105
1130
|
# Prep
|
1106
|
-
cid = ent['caseid']
|
1107
1131
|
|
1108
1132
|
# entry
|
1109
|
-
ent
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1133
|
+
if ent
|
1134
|
+
ent['icfs'] = 1
|
1135
|
+
ent['tags'] ||= [ ]
|
1136
|
+
ent['user'] = @user
|
1137
|
+
ent['caseid'] = cid
|
1138
|
+
files, fhash = _pre_files(ent)
|
1139
|
+
else
|
1140
|
+
files = []
|
1141
|
+
end
|
1113
1142
|
|
1114
1143
|
# action
|
1115
1144
|
if act
|
1116
|
-
ent['tags'] << ICFS::TagAction
|
1145
|
+
ent['tags'] << ICFS::TagAction if ent
|
1117
1146
|
act['icfs'] = 1
|
1118
1147
|
act['caseid'] = cid
|
1119
1148
|
act['tasks'].each do |tk|
|
@@ -1123,7 +1152,7 @@ class Api
|
|
1123
1152
|
|
1124
1153
|
# index
|
1125
1154
|
if idx
|
1126
|
-
ent['tags'] << ICFS::TagIndex
|
1155
|
+
ent['tags'] << ICFS::TagIndex if ent
|
1127
1156
|
idx['icfs'] = 1
|
1128
1157
|
idx['caseid'] = cid
|
1129
1158
|
idx['tags'] ||= [ ICFS::TagNone ]
|
@@ -1131,7 +1160,7 @@ class Api
|
|
1131
1160
|
|
1132
1161
|
# case
|
1133
1162
|
if cse
|
1134
|
-
ent['tags'] << ICFS::TagCase
|
1163
|
+
ent['tags'] << ICFS::TagCase if ent
|
1135
1164
|
cse['icfs'] = 1
|
1136
1165
|
cse['caseid'] = cid
|
1137
1166
|
cse['tags'] ||= [ ICFS::TagNone ]
|
@@ -1146,7 +1175,7 @@ class Api
|
|
1146
1175
|
log['files_hash'] = fhash if fhash
|
1147
1176
|
|
1148
1177
|
# no tags
|
1149
|
-
ent['tags'] = [ ICFS::TagNone ] if ent['tags'].empty?
|
1178
|
+
ent['tags'] = [ ICFS::TagNone ] if ent && ent['tags'].empty?
|
1150
1179
|
|
1151
1180
|
# current
|
1152
1181
|
nxt = {
|
@@ -1171,14 +1200,18 @@ class Api
|
|
1171
1200
|
cur = Items.parse(json, 'current', Items::ItemCurrent)
|
1172
1201
|
|
1173
1202
|
# entry
|
1174
|
-
if ent
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1203
|
+
if ent
|
1204
|
+
if ent['entry']
|
1205
|
+
enum = ent['entry']
|
1206
|
+
json = @cache.entry_read(cid, enum)
|
1207
|
+
ent_pri = Items.parse(json, 'entry', Items::ItemEntry)
|
1208
|
+
nxt['entry'] = cur['entry']
|
1209
|
+
else
|
1210
|
+
enum = cur['entry'] + 1
|
1211
|
+
nxt['entry'] = enum
|
1212
|
+
end
|
1179
1213
|
else
|
1180
|
-
|
1181
|
-
nxt['entry'] = enum
|
1214
|
+
nxt['entry'] = cur['entry']
|
1182
1215
|
end
|
1183
1216
|
|
1184
1217
|
# action
|
@@ -1186,7 +1219,7 @@ class Api
|
|
1186
1219
|
anum = ent_pri['action']
|
1187
1220
|
elsif act && act['action']
|
1188
1221
|
anum = act['action']
|
1189
|
-
elsif ent['action']
|
1222
|
+
elsif ent && ent['action']
|
1190
1223
|
anum = ent['action']
|
1191
1224
|
end
|
1192
1225
|
if anum
|
@@ -1228,7 +1261,7 @@ class Api
|
|
1228
1261
|
perms = Set.new
|
1229
1262
|
|
1230
1263
|
# entry
|
1231
|
-
perms.merge(ent['perms']) if ent['perms']
|
1264
|
+
perms.merge(ent['perms']) if ent && ent['perms']
|
1232
1265
|
if ent_pri
|
1233
1266
|
|
1234
1267
|
# must have those perms
|
@@ -1326,7 +1359,7 @@ class Api
|
|
1326
1359
|
|
1327
1360
|
# write unless a case or pre-existing action
|
1328
1361
|
unless cse || act_pri
|
1329
|
-
perms.add( ICFS::PermWrite)
|
1362
|
+
perms.add( ICFS::PermWrite )
|
1330
1363
|
end
|
1331
1364
|
|
1332
1365
|
# permissions
|
@@ -1341,28 +1374,32 @@ class Api
|
|
1341
1374
|
# Items
|
1342
1375
|
|
1343
1376
|
# entry
|
1344
|
-
ent
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
if
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1377
|
+
if ent
|
1378
|
+
ent['entry'] = enum
|
1379
|
+
ent['log'] = lnum
|
1380
|
+
ent['time'] ||= now
|
1381
|
+
ent['action'] = anum if act
|
1382
|
+
if idx
|
1383
|
+
if ent['index']
|
1384
|
+
ent['index'] << xnum
|
1385
|
+
else
|
1386
|
+
ent['index'] = [ xnum ]
|
1387
|
+
end
|
1353
1388
|
end
|
1389
|
+
ent['index'].sort!.uniq! if ent['index']
|
1390
|
+
ent['files'].each{|fi| fi['log'] ||= lnum } if ent['files']
|
1391
|
+
eitem = Items.generate(ent, 'entry', Items::ItemEntry)
|
1392
|
+
log['entry'] = {
|
1393
|
+
'num' => enum,
|
1394
|
+
'hash' => ICFS.hash(eitem)
|
1395
|
+
}
|
1354
1396
|
end
|
1355
|
-
ent['files'].each{|fi| fi['log'] ||= lnum } if ent['files']
|
1356
|
-
eitem = Items.generate(ent, 'entry', Items::ItemEntry)
|
1357
|
-
log['entry'] = {
|
1358
|
-
'num' => enum,
|
1359
|
-
'hash' => ICFS.hash(eitem)
|
1360
|
-
}
|
1361
1397
|
|
1362
1398
|
# action
|
1363
1399
|
if act
|
1364
1400
|
act['action'] = anum
|
1365
1401
|
act['log'] = lnum
|
1402
|
+
act['entry'] = enum if ent
|
1366
1403
|
aitem = Items.generate(act, 'action', Items::ItemAction)
|
1367
1404
|
log['action'] = {
|
1368
1405
|
'num' => anum,
|
@@ -1374,6 +1411,7 @@ class Api
|
|
1374
1411
|
if idx
|
1375
1412
|
idx['index'] = xnum
|
1376
1413
|
idx['log'] = lnum
|
1414
|
+
idx['entry'] = enum if ent
|
1377
1415
|
xitem = Items.generate(idx, 'index', Items::ItemIndex)
|
1378
1416
|
log['index'] = {
|
1379
1417
|
'num' => xnum,
|
@@ -1384,8 +1422,12 @@ class Api
|
|
1384
1422
|
# case
|
1385
1423
|
if cse
|
1386
1424
|
cse['log'] = lnum
|
1425
|
+
cse['entry'] = enum if ent
|
1387
1426
|
citem = Items.generate(cse, 'case', Items::ItemCase)
|
1388
|
-
log['
|
1427
|
+
log['case'] = {
|
1428
|
+
'set' => true,
|
1429
|
+
'hash' => ICFS.hash(citem),
|
1430
|
+
}
|
1389
1431
|
end
|
1390
1432
|
|
1391
1433
|
# log
|
@@ -1403,8 +1445,10 @@ class Api
|
|
1403
1445
|
# Write
|
1404
1446
|
|
1405
1447
|
# entry
|
1406
|
-
|
1407
|
-
|
1448
|
+
if ent
|
1449
|
+
@cache.entry_write(cid, enum, eitem)
|
1450
|
+
@store.entry_write(cid, enum, lnum, eitem)
|
1451
|
+
end
|
1408
1452
|
|
1409
1453
|
# action
|
1410
1454
|
if act
|
data/lib/icfs/cache_elastic.rb
CHANGED
@@ -35,6 +35,7 @@ class CacheElastic < Cache
|
|
35
35
|
"icfs": { "enabled": false },
|
36
36
|
"caseid": { "type": "keyword" },
|
37
37
|
"log": { "enabled": false },
|
38
|
+
"entry": { "enabled": false },
|
38
39
|
"template": { "type": "boolean" },
|
39
40
|
"status": { "type": "boolean" },
|
40
41
|
"title": { "type": "text" },
|
@@ -66,7 +67,10 @@ class CacheElastic < Cache
|
|
66
67
|
"num": { "type": "integer" },
|
67
68
|
"hash": { "enabled": false }
|
68
69
|
}},
|
69
|
-
"
|
70
|
+
"case": { "properties": {
|
71
|
+
"set": { "type": "boolean" },
|
72
|
+
"hash": { "enabled": false }
|
73
|
+
}},
|
70
74
|
"files_hash": { "enabled": false }
|
71
75
|
}}}
|
72
76
|
}',
|
@@ -104,6 +108,7 @@ class CacheElastic < Cache
|
|
104
108
|
"caseid": { "type": "keyword" },
|
105
109
|
"action": { "type": "integer" },
|
106
110
|
"log": { "enabled": false },
|
111
|
+
"entry": { "enabled": false },
|
107
112
|
"tasks": { "type": "nested","properties": {
|
108
113
|
"assigned": { "type": "keyword" },
|
109
114
|
"title": { "type": "text" },
|
@@ -121,6 +126,7 @@ class CacheElastic < Cache
|
|
121
126
|
"caseid": { "type": "keyword" },
|
122
127
|
"index": { "type": "integer" },
|
123
128
|
"log": { "enabled": false },
|
129
|
+
"entry": { "enabled": false },
|
124
130
|
"title": {
|
125
131
|
"type": "text",
|
126
132
|
"fields": { "raw": { "type": "keyword" }}
|
@@ -532,7 +538,7 @@ class CacheElastic < Cache
|
|
532
538
|
tags: 'tags',
|
533
539
|
perms: ['perms', :empty],
|
534
540
|
action: ['action', :zero],
|
535
|
-
|
541
|
+
indexes: ['index', :size],
|
536
542
|
files: ['files', :size],
|
537
543
|
stats: ['stats', :size],
|
538
544
|
}.freeze
|
@@ -792,6 +798,7 @@ class CacheElastic < Cache
|
|
792
798
|
entry: ['entry', :sub, 'num'].freeze,
|
793
799
|
index: ['index', :sub, 'num'].freeze,
|
794
800
|
action: ['action', :sub, 'num'].freeze,
|
801
|
+
case: ['case', :sub, 'set'].freeze,
|
795
802
|
files: ['files_hash', :size].freeze,
|
796
803
|
}.freeze
|
797
804
|
|
@@ -806,6 +813,7 @@ class CacheElastic < Cache
|
|
806
813
|
_query_term('caseid', query[:caseid]),
|
807
814
|
_query_times('times', query[:after], query[:before]),
|
808
815
|
_query_term('user', query[:user]),
|
816
|
+
_query_exists('case.set', query[:case_edit]),
|
809
817
|
_query_term('entry.num', query[:entry]),
|
810
818
|
_query_term('index.num', query[:index]),
|
811
819
|
_query_term('action.num', query[:action]),
|
data/lib/icfs/config.rb
CHANGED
@@ -30,9 +30,10 @@ class Config
|
|
30
30
|
method: :string,
|
31
31
|
valid: /[+\-](0[0-9]|1[0-2]):[0-5][0-9]/.freeze,
|
32
32
|
whitelist: true,
|
33
|
-
}
|
34
|
-
|
35
|
-
|
33
|
+
}.freeze,
|
34
|
+
'rel_time' => Validate::IsBoolean,
|
35
|
+
}.freeze
|
36
|
+
}.freeze
|
36
37
|
|
37
38
|
###############################################
|
38
39
|
# New instance
|