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.rb
CHANGED
@@ -9,7 +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
|
require 'digest/sha2'
|
15
|
+
require 'date'
|
13
16
|
|
14
17
|
require_relative 'icfs/validate'
|
15
18
|
|
@@ -18,38 +21,49 @@ require_relative 'icfs/validate'
|
|
18
21
|
#
|
19
22
|
module ICFS
|
20
23
|
|
24
|
+
# version: major, minor, patch
|
25
|
+
Version = [0, 2, 0].freeze
|
26
|
+
|
27
|
+
# version pre-release
|
28
|
+
VersionPre = nil
|
29
|
+
|
30
|
+
# version string
|
31
|
+
VersionString = (
|
32
|
+
'%d.%d.%d' % Version +
|
33
|
+
(VersionPre ? ('-' + VersionPre) : '')
|
34
|
+
).freeze
|
21
35
|
|
22
36
|
# no tags
|
23
|
-
TagNone = '[none]'
|
37
|
+
TagNone = '[none]'
|
24
38
|
|
25
39
|
# edits an action
|
26
|
-
TagAction = '[action]'
|
40
|
+
TagAction = '[action]'
|
27
41
|
|
28
42
|
# edits an index
|
29
|
-
TagIndex = '[index]'
|
43
|
+
TagIndex = '[index]'
|
30
44
|
|
31
45
|
# edits the case
|
32
|
-
TagCase = '[case]'
|
46
|
+
TagCase = '[case]'
|
33
47
|
|
34
48
|
|
35
49
|
# permission to read case
|
36
|
-
PermRead = '[read]'
|
50
|
+
PermRead = '[read]'
|
37
51
|
|
38
52
|
# permission to write case
|
39
|
-
PermWrite = '[write]'
|
53
|
+
PermWrite = '[write]'
|
40
54
|
|
41
55
|
# permission to manage case
|
42
|
-
PermManage = '[manage]'
|
56
|
+
PermManage = '[manage]'
|
43
57
|
|
44
58
|
# permission to manage actions
|
45
|
-
PermAction = '[action]'
|
59
|
+
PermAction = '[action]'
|
46
60
|
|
47
61
|
# global permission to search
|
48
|
-
PermSearch = '{[search]}'
|
62
|
+
PermSearch = '{[search]}'
|
49
63
|
|
50
64
|
|
51
65
|
# user group
|
52
|
-
UserCase = '[case]'
|
66
|
+
UserCase = '[case]'
|
53
67
|
|
54
68
|
|
55
69
|
###############################################
|
@@ -67,6 +81,156 @@ module ICFS
|
|
67
81
|
end
|
68
82
|
|
69
83
|
|
84
|
+
###############################################
|
85
|
+
# Pull a time type
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
#
|
89
|
+
def self._time_type(str)
|
90
|
+
case str.downcase
|
91
|
+
when 'y', 'yr', 'yrs', 'year', 'years'
|
92
|
+
return :year
|
93
|
+
when 'm', 'mon', 'mons', 'month', 'months'
|
94
|
+
return :month
|
95
|
+
when 'w', 'wk', 'wks', 'week', 'weeks'
|
96
|
+
return :week
|
97
|
+
when 'd', 'day', 'days'
|
98
|
+
return :day
|
99
|
+
when 'h', 'hr', 'hrs', 'hour', 'hours'
|
100
|
+
return :hour
|
101
|
+
when 'min', 'mins', 'minute', 'minutes'
|
102
|
+
return :minute
|
103
|
+
when 's', 'sec', 'secs', 'second', 'seconds'
|
104
|
+
return :second
|
105
|
+
else
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
end # self._time_type()
|
109
|
+
|
110
|
+
|
111
|
+
###############################################
|
112
|
+
# Adjust the time
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
#
|
116
|
+
def self._time_adjust(num, type)
|
117
|
+
case type
|
118
|
+
when :year
|
119
|
+
ary = Time.now.utc.to_a
|
120
|
+
dte = Date.new(ary[5], ary[4], ary[3])
|
121
|
+
dte = dte << (-12 * num)
|
122
|
+
return Time.utc(dte.year, dte.month, dte.day,
|
123
|
+
ary[2], ary[1], ary[0]).to_i
|
124
|
+
when :month
|
125
|
+
ary = Time.now.utc.to_a
|
126
|
+
dte = Date.new(ary[5], ary[4], ary[3])
|
127
|
+
dte = dte << (-1 * num)
|
128
|
+
return Time.utc(dte.year, dte.month, dte.day,
|
129
|
+
ary[2], ary[1], ary[0]).to_i
|
130
|
+
when :week
|
131
|
+
return (Time.now + num * 7*24*60*60).to_i
|
132
|
+
when :day
|
133
|
+
return (Time.now + num * 24*60*60).to_i
|
134
|
+
when :hour
|
135
|
+
return (Time.now + num * 60*60).to_i
|
136
|
+
when :minute
|
137
|
+
return (Time.now + num * 60).to_i
|
138
|
+
when :second
|
139
|
+
return (Time.now + num).to_i
|
140
|
+
else
|
141
|
+
return nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
###############################################
|
147
|
+
# A time delta spec
|
148
|
+
TimeDelta = /^[[:space:]]*([Nn][Oo][Ww])?[[:space:]]*([+\-])[[:space:]]*(\d+)[[:space:]]*([^[space]]+)[[:space]]*$/.freeze
|
149
|
+
|
150
|
+
|
151
|
+
###############################################
|
152
|
+
# a relative spec
|
153
|
+
TimeRel = /^[[:space:]]*([Nn][Ee][Xx][Tt]|[Pp][Rr][Ee][Vv]|[Ll][Aa][Ss][Tt])[[:space:]]+([^[:space:]]+)[[:space:]]*$/.freeze
|
154
|
+
|
155
|
+
|
156
|
+
###############################################
|
157
|
+
# future time spec
|
158
|
+
TimeFuture = /^[[:space:]]*[Ii][Nn][[:space:]]+(\d+)[[:space:]]*([^[space]]+)[[:space]]*$/.freeze
|
159
|
+
|
160
|
+
|
161
|
+
###############################################
|
162
|
+
# historic time spec
|
163
|
+
TimeHistory = /^[[:space:]]*(\d+)[[:space:]]*([^[:space:]]+)[[:space:]]*[Aa][Gg][Oo][[:space:]]*$/.freeze
|
164
|
+
|
165
|
+
|
166
|
+
###############################################
|
167
|
+
# empty time spec
|
168
|
+
TimeEmpty = /^[[:space:]]*([Nn][Oo][Ww])?[[:space:]]*$/.freeze
|
169
|
+
|
170
|
+
|
171
|
+
###############################################
|
172
|
+
# A timezone spec
|
173
|
+
TimeZone = /[+\-]\d{2}:\d{2}[[:space:]]*$/.freeze
|
174
|
+
|
175
|
+
|
176
|
+
###############################################
|
177
|
+
# Parse a time string
|
178
|
+
#
|
179
|
+
# @param str [String] the time string
|
180
|
+
# @param cfg [Config] the config
|
181
|
+
#
|
182
|
+
# Handles:
|
183
|
+
# * blank or now
|
184
|
+
# * \[now\] +\\- <num> <type>
|
185
|
+
# * next\\prev <type>
|
186
|
+
# * in <num> <type>
|
187
|
+
# * <num> <type> ago
|
188
|
+
# * a specifc parseable time
|
189
|
+
#
|
190
|
+
def self.time_parse(str, cfg)
|
191
|
+
return nil if( !str || !str.is_a?(String) )
|
192
|
+
|
193
|
+
# empty
|
194
|
+
if ma = TimeEmpty.match(str)
|
195
|
+
return Time.now.to_i
|
196
|
+
|
197
|
+
# delta
|
198
|
+
elsif ma = TimeDelta.match(str)
|
199
|
+
num = ma[3].to_i
|
200
|
+
num = num * -1 if ma[2] == '-'
|
201
|
+
type = ICFS._time_type(ma[4])
|
202
|
+
return ICFS._time_adjust(num, type)
|
203
|
+
|
204
|
+
# relative
|
205
|
+
elsif ma = TimeRel.match(str)
|
206
|
+
num = (ma[1].downcase == 'next') ? 1 : -1
|
207
|
+
type = ICFS._time_type(ma[2])
|
208
|
+
return ICFS._time_adjust(num, type)
|
209
|
+
|
210
|
+
# future
|
211
|
+
elsif ma = TimeFuture.match(str)
|
212
|
+
num = ma[1].to_i
|
213
|
+
type = ICFS._time_type(ma[2])
|
214
|
+
return ICFS._time_adjust(num, type)
|
215
|
+
|
216
|
+
# history
|
217
|
+
elsif ma = TimeHistory.match(str)
|
218
|
+
p ma
|
219
|
+
num = -1 * ma[1].to_i
|
220
|
+
type = ICFS._time_type(ma[2])
|
221
|
+
return ICFS._time_adjust(num, type)
|
222
|
+
|
223
|
+
# parse a time spec
|
224
|
+
else
|
225
|
+
ma = TimeZone.match(str)
|
226
|
+
tstr = ma ? str : str + cfg.get('tz')
|
227
|
+
return Time.parse(tstr).to_i
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
rescue ArgumentError
|
232
|
+
return nil
|
233
|
+
end # def self.time_parse()
|
70
234
|
|
71
235
|
|
72
236
|
##########################################################################
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Graham A. Field
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2-
|
14
14
|
|
@@ -25,23 +25,35 @@ extra_rdoc_files: []
|
|
25
25
|
files:
|
26
26
|
- LICENSE.txt
|
27
27
|
- bin/icfs_demo_fcgi.rb
|
28
|
-
- bin/icfs_demo_ssl_gen.rb
|
29
28
|
- data/icfs.css
|
30
29
|
- data/icfs.js
|
31
|
-
- devel/
|
30
|
+
- devel/demo/ssl_gen.rb
|
31
|
+
- devel/demo/ssl_gen.yml
|
32
32
|
- devel/docker-compose.yml
|
33
33
|
- devel/icfs
|
34
34
|
- devel/icfs-wrk/Dockerfile
|
35
|
+
- devel/run/base.rb
|
35
36
|
- devel/run/copy-s3.rb
|
37
|
+
- devel/run/email.rb
|
38
|
+
- devel/run/email_imap.rb
|
39
|
+
- devel/run/email_smime.rb
|
36
40
|
- devel/run/init-icfs.rb
|
37
41
|
- devel/run/webrick.rb
|
38
42
|
- lib/icfs.rb
|
39
43
|
- lib/icfs/api.rb
|
40
44
|
- lib/icfs/cache.rb
|
41
45
|
- lib/icfs/cache_elastic.rb
|
46
|
+
- lib/icfs/config.rb
|
47
|
+
- lib/icfs/config_redis.rb
|
48
|
+
- lib/icfs/config_s3.rb
|
42
49
|
- lib/icfs/demo/auth.rb
|
43
50
|
- lib/icfs/demo/static.rb
|
44
51
|
- lib/icfs/elastic.rb
|
52
|
+
- lib/icfs/email/basic.rb
|
53
|
+
- lib/icfs/email/core.rb
|
54
|
+
- lib/icfs/email/from.rb
|
55
|
+
- lib/icfs/email/imap.rb
|
56
|
+
- lib/icfs/email/smime.rb
|
45
57
|
- lib/icfs/items.rb
|
46
58
|
- lib/icfs/store.rb
|
47
59
|
- lib/icfs/store_fs.rb
|
@@ -55,9 +67,6 @@ files:
|
|
55
67
|
- lib/icfs/validate.rb
|
56
68
|
- lib/icfs/web/auth_ssl.rb
|
57
69
|
- lib/icfs/web/client.rb
|
58
|
-
- lib/icfs/web/config.rb
|
59
|
-
- lib/icfs/web/config_redis.rb
|
60
|
-
- lib/icfs/web/config_s3.rb
|
61
70
|
homepage: https://github.com/g4field/icfs
|
62
71
|
licenses:
|
63
72
|
- GPL-3.0
|
data/devel/devel-webrick.yml
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Investigative Case File System
|
3
|
-
#
|
4
|
-
# Copyright 2019 by Graham A. Field
|
5
|
-
#
|
6
|
-
# This program is free software: you can redistribute it and/or modify
|
7
|
-
# it under the terms of the GNU General Public License version 3.
|
8
|
-
#
|
9
|
-
# This program is distributed WITHOUT ANY WARRANTY; without even the
|
10
|
-
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
11
|
-
|
12
|
-
version: '3'
|
13
|
-
|
14
|
-
services:
|
15
|
-
|
16
|
-
# Elasticsearch instance
|
17
|
-
elastic:
|
18
|
-
image: docker.elastic.co/elasticsearch/elasticsearch:6.7.2
|
19
|
-
environment:
|
20
|
-
discovery-type: single-node
|
21
|
-
volume:
|
22
|
-
- elastic:/usr/share/elasticsearch/data
|
23
|
-
ports:
|
24
|
-
- "127.0.0.1:9200:9200"
|
25
|
-
|
26
|
-
# Minio S3-compatible object store
|
27
|
-
minio:
|
28
|
-
image: minio/minio
|
29
|
-
environment:
|
30
|
-
MINIO_ACCESS_KEY: minio_key
|
31
|
-
MINIO_SECRET_KEY: minio_secret
|
32
|
-
volume:
|
33
|
-
- minio:/data
|
34
|
-
command: ["server", "/data"]
|
35
|
-
|
36
|
-
# Redis cache
|
37
|
-
redis:
|
38
|
-
image: redis:alpine
|
39
|
-
|
40
|
-
# the app
|
41
|
-
app:
|
42
|
-
image: icfs-wrk
|
43
|
-
ports:
|
44
|
-
- "127.0.0.1:80:8080"
|
45
|
-
|
46
|
-
|
47
|
-
volumes:
|
48
|
-
- elastic
|
49
|
-
- minio
|