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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28031e9c5c67e30c2cf4778fbf56a7840117d256e4384e6e044e7cc888958d09
|
4
|
+
data.tar.gz: 3abea632e084b00bd09ac570710eab52e99a152d073c6f96779a04c23dbc1c21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd28dc30f59e5bec1b272508d5b64ecb950a3e2b6d26d4318156069d19c338093177302ac09207a4b76b7decfa8272f84a8839f3165eeee28fdb9f15ae5c6ef3
|
7
|
+
data.tar.gz: '08f19a62a3d3c21cdf46c8120bd0b5846107a57409aba71939587affed4e7daf32c4d0bd805919d884baa4d24b520521527f62e8edf66ed6f886cf2237122b27'
|
data/bin/icfs_demo_fcgi.rb
CHANGED
@@ -10,15 +10,23 @@
|
|
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
|
+
# frozen_string_literal: true
|
14
|
+
|
13
15
|
require 'openssl'
|
16
|
+
require 'yaml'
|
17
|
+
|
18
|
+
# read the configuration
|
19
|
+
cfg = YAML.load(File.read(ARGV[0]))
|
20
|
+
|
14
21
|
|
22
|
+
serial = Time.now.to_i
|
15
23
|
|
16
|
-
# make a CA
|
24
|
+
# make a CA cert
|
17
25
|
ca_key = OpenSSL::PKey::RSA.new 2048
|
18
26
|
ca_cert = OpenSSL::X509::Certificate.new
|
19
27
|
ca_cert.version = 2
|
20
|
-
ca_cert.serial =
|
21
|
-
ca_cert.subject = OpenSSL::X509::Name.parse('
|
28
|
+
ca_cert.serial = serial
|
29
|
+
ca_cert.subject = OpenSSL::X509::Name.parse(cfg['ca']['cn'])
|
22
30
|
ca_cert.issuer = ca_cert.subject
|
23
31
|
ca_cert.public_key = ca_key.public_key
|
24
32
|
ca_cert.not_before = Time.now
|
@@ -36,11 +44,11 @@ ca_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
|
|
36
44
|
File.open("ca_cert.pem", "wb"){|fi| fi.write ca_cert.to_pem }
|
37
45
|
|
38
46
|
|
39
|
-
# make a server key
|
47
|
+
# make a server cert & key
|
40
48
|
srv_key = OpenSSL::PKey::RSA.new 2048
|
41
49
|
srv_cert = OpenSSL::X509::Certificate.new
|
42
50
|
srv_cert.version = 2
|
43
|
-
srv_cert.serial =
|
51
|
+
srv_cert.serial = serial + 1
|
44
52
|
srv_cert.subject = OpenSSL::X509::Name.parse('/OU=org/OU=example/OU=Test Server/CN=localhost')
|
45
53
|
srv_cert.issuer = ca_cert.subject
|
46
54
|
srv_cert.public_key = srv_key.public_key
|
@@ -52,19 +60,22 @@ ef.issuer_certificate = ca_cert
|
|
52
60
|
srv_cert.add_extension(ef.create_extension("basicConstraints", "CA:FALSE"))
|
53
61
|
srv_cert.add_extension(ef.create_extension("keyUsage", "keyEncipherment,dataEncipherment,digitalSignature"))
|
54
62
|
srv_cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
|
63
|
+
srv_cert.add_extension(ef.create_extension("subjectAltName", "email:%s" % cfg['server']['email'], false))
|
55
64
|
srv_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
|
56
65
|
|
57
|
-
# save server key
|
66
|
+
# save server cert & key
|
58
67
|
File.open("srv_cert.pem", "wb"){|fi| fi.write srv_cert.to_pem }
|
59
68
|
File.open("srv_key.pem", "wb"){|fi| fi.write srv_key.to_pem }
|
60
69
|
|
61
|
-
# make client certs
|
62
|
-
|
70
|
+
# make client certs with key included
|
71
|
+
cnt = 0
|
72
|
+
cfg['clients'].each do |cc|
|
73
|
+
cnt += 1
|
63
74
|
clt_key = OpenSSL::PKey::RSA.new 2048
|
64
75
|
clt_cert = OpenSSL::X509::Certificate.new
|
65
76
|
clt_cert.version = 2
|
66
|
-
clt_cert.serial =
|
67
|
-
clt_cert.subject = OpenSSL::X509::Name.parse('
|
77
|
+
clt_cert.serial = serial + 2 + cnt
|
78
|
+
clt_cert.subject = OpenSSL::X509::Name.parse(cc['cn'])
|
68
79
|
clt_cert.issuer = ca_cert.subject
|
69
80
|
clt_cert.public_key = clt_key.public_key
|
70
81
|
clt_cert.not_before = Time.now
|
@@ -74,11 +85,12 @@ File.open("srv_key.pem", "wb"){|fi| fi.write srv_key.to_pem }
|
|
74
85
|
ef.issuer_certificate = ca_cert
|
75
86
|
clt_cert.add_extension(ef.create_extension("basicConstraints", "CA:FALSE"))
|
76
87
|
clt_cert.add_extension(ef.create_extension("keyUsage", "keyEncipherment,dataEncipherment,digitalSignature"))
|
88
|
+
clt_cert.add_extension(ef.create_extension("subjectAltName", "email:%s" % cc['email'], false))
|
77
89
|
clt_cert.sign(ca_key, OpenSSL::Digest::SHA256.new)
|
78
90
|
|
79
91
|
# pkcs12
|
80
|
-
clt_pkcs12 = OpenSSL::PKCS12.create('demo', 'client-%d' %
|
92
|
+
clt_pkcs12 = OpenSSL::PKCS12.create('demo', 'client-%d' % cnt, clt_key, clt_cert)
|
81
93
|
|
82
|
-
# save cert
|
83
|
-
File.open('clt_%d.pfx' %
|
94
|
+
# save cert w/key
|
95
|
+
File.open('clt_%d.pfx' % cnt, 'wb'){|fi| fi.write clt_pkcs12.to_der }
|
84
96
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
ca:
|
3
|
+
cn: "/OU=org/OU=example/CN=Test Root CA"
|
4
|
+
|
5
|
+
server:
|
6
|
+
cn: "/OU=org/OU=example/OU=Test Server/CN=localhost"
|
7
|
+
email: "server@example.org"
|
8
|
+
|
9
|
+
clients:
|
10
|
+
- cn: "/OU=org/OU=example/OU=Test Client/CN=client 1"
|
11
|
+
email: "client1@example.org"
|
12
|
+
|
13
|
+
- cn: "/OU=org/OU=example/OU=Test Client/CN=client 2"
|
14
|
+
email: "client2example.org"
|
data/devel/icfs-wrk/Dockerfile
CHANGED
@@ -16,7 +16,7 @@ RUN apk update && \
|
|
16
16
|
apk upgrade && \
|
17
17
|
apk --update add ruby fcgi ruby-json tzdata vim curl git bash && \
|
18
18
|
apk --update add --virtual build-deps ruby-dev build-base fcgi-dev && \
|
19
|
-
gem install -N rack webrick etc faraday yard aws-sdk-s3 redis && \
|
19
|
+
gem install -N rack webrick etc faraday yard aws-sdk-s3 redis mail && \
|
20
20
|
apk del build-deps && \
|
21
21
|
rm -rf /var/cache/apk/*
|
22
22
|
|
data/devel/run/base.rb
ADDED
@@ -0,0 +1,92 @@
|
|
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
|
+
# frozen_string_literal: true
|
14
|
+
|
15
|
+
require 'faraday'
|
16
|
+
require 'aws-sdk-s3'
|
17
|
+
require 'redis'
|
18
|
+
|
19
|
+
require_relative '../../lib/icfs'
|
20
|
+
require_relative '../../lib/icfs/cache_elastic'
|
21
|
+
require_relative '../../lib/icfs/store_s3'
|
22
|
+
require_relative '../../lib/icfs/users_s3'
|
23
|
+
require_relative '../../lib/icfs/users_redis'
|
24
|
+
require_relative '../../lib/icfs/config_s3'
|
25
|
+
require_relative '../../lib/icfs/config_redis'
|
26
|
+
|
27
|
+
#################################################
|
28
|
+
# Get the API
|
29
|
+
#
|
30
|
+
def get_base
|
31
|
+
|
32
|
+
# the log
|
33
|
+
log = Logger.new(STDERR)
|
34
|
+
log.level = Logger::INFO
|
35
|
+
|
36
|
+
# S3
|
37
|
+
s3 = Aws::S3::Client.new(
|
38
|
+
endpoint: 'http://minio:9000',
|
39
|
+
access_key_id: 'minio_key',
|
40
|
+
secret_access_key: 'minio_secret',
|
41
|
+
force_path_style: true,
|
42
|
+
region: 'us-east-1'
|
43
|
+
)
|
44
|
+
|
45
|
+
# redis
|
46
|
+
redis = Redis.new(host: 'redis')
|
47
|
+
|
48
|
+
# elasic
|
49
|
+
es = Faraday.new('http://elastic:9200')
|
50
|
+
|
51
|
+
# default mapping
|
52
|
+
map = {
|
53
|
+
entry: 'entry',
|
54
|
+
case: 'case',
|
55
|
+
action: 'action',
|
56
|
+
index: 'index',
|
57
|
+
log: 'log',
|
58
|
+
lock: 'lock',
|
59
|
+
current: 'current',
|
60
|
+
}.freeze
|
61
|
+
|
62
|
+
# default config
|
63
|
+
defaults = {
|
64
|
+
'tz' => '-04:00'
|
65
|
+
}
|
66
|
+
|
67
|
+
# base objects
|
68
|
+
cache = ICFS::CacheElastic.new(map, es)
|
69
|
+
store = ICFS::StoreS3.new(s3, 'icfs', 'case/')
|
70
|
+
users_base = ICFS::UsersS3.new(s3, 'icfs', 'users/')
|
71
|
+
users = ICFS::UsersRedis.new(redis, users_base, {
|
72
|
+
prefix: 'users/',
|
73
|
+
expires: 60, # one minute cache for testing
|
74
|
+
log: log,
|
75
|
+
})
|
76
|
+
config_base = ICFS::ConfigS3.new(defaults, s3, 'icfs', 'config/')
|
77
|
+
config = ICFS::ConfigRedis.new(redis, config_base, {
|
78
|
+
prefix: 'config/',
|
79
|
+
expires: 60, # debug, only cache for one minute
|
80
|
+
})
|
81
|
+
api = ICFS::Api.new([], users, cache, store, config)
|
82
|
+
|
83
|
+
return {
|
84
|
+
cache: cache,
|
85
|
+
store: store,
|
86
|
+
users: users,
|
87
|
+
config: config,
|
88
|
+
api: api,
|
89
|
+
log: log,
|
90
|
+
}
|
91
|
+
|
92
|
+
end # def base
|
data/devel/run/copy-s3.rb
CHANGED
data/devel/run/email.rb
ADDED
@@ -0,0 +1,36 @@
|
|
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
|
+
# frozen_string_literal: true
|
14
|
+
|
15
|
+
require_relative 'base'
|
16
|
+
require_relative '../../lib/icfs/email/from'
|
17
|
+
require_relative '../../lib/icfs/email/basic'
|
18
|
+
|
19
|
+
# api
|
20
|
+
base = get_base
|
21
|
+
api = base[:api]
|
22
|
+
log = base[:log]
|
23
|
+
log.level = Logger::DEBUG
|
24
|
+
|
25
|
+
# load the email map
|
26
|
+
map_email = JSON.parse(File.read(ARGV[0]))
|
27
|
+
|
28
|
+
# email gateway
|
29
|
+
email_basic = ICFS::Email::Basic.new
|
30
|
+
email_from = ICFS::Email::From.new(map_email)
|
31
|
+
email = ICFS::Email::Core.new(api, log, [email_from, email_basic])
|
32
|
+
|
33
|
+
txt = STDIN.read
|
34
|
+
res = email.receive(txt)
|
35
|
+
|
36
|
+
p res
|
@@ -0,0 +1,43 @@
|
|
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
|
+
# frozen_string_literal: true
|
14
|
+
|
15
|
+
# <app> <email_map.json> <config.json>
|
16
|
+
|
17
|
+
require_relative 'base'
|
18
|
+
require_relative '../../lib/icfs/email/from'
|
19
|
+
require_relative '../../lib/icfs/email/basic'
|
20
|
+
require_relative '../../lib/icfs/email/imap'
|
21
|
+
|
22
|
+
# api
|
23
|
+
base = get_base
|
24
|
+
api = base[:api]
|
25
|
+
log = base[:log]
|
26
|
+
log.level = Logger::DEBUG
|
27
|
+
|
28
|
+
# load the email map
|
29
|
+
map_email = JSON.parse(File.read(ARGV[0]))
|
30
|
+
|
31
|
+
# load the IMAP config
|
32
|
+
cfg_raw = JSON.parse(File.read(ARGV[1]))
|
33
|
+
cfg = {}
|
34
|
+
cfg_raw.each{|key, val| cfg[key.to_sym] = val}
|
35
|
+
|
36
|
+
# email gateway
|
37
|
+
email_basic = ICFS::Email::Basic.new
|
38
|
+
email_from = ICFS::Email::From.new(map_email)
|
39
|
+
email = ICFS::Email::Core.new(api, log, [email_from, email_basic])
|
40
|
+
imap = ICFS::Email::Imap.new(email, log, cfg)
|
41
|
+
|
42
|
+
# and fetch
|
43
|
+
imap.reconnect
|
@@ -0,0 +1,47 @@
|
|
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
|
+
# <app> <srv_cert.pem> <srv_key.pem> <ca.pem> < <email.eml>
|
14
|
+
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require_relative 'base'
|
18
|
+
require_relative '../../lib/icfs/email/smime'
|
19
|
+
require_relative '../../lib/icfs/email/basic'
|
20
|
+
|
21
|
+
# api
|
22
|
+
base = get_base
|
23
|
+
api = base[:api]
|
24
|
+
log = base[:log]
|
25
|
+
log.level = Logger::DEBUG
|
26
|
+
|
27
|
+
# load the email map
|
28
|
+
cert = ::OpenSSL::X509::Certificate.new(File.read(ARGV[0]))
|
29
|
+
key = ::OpenSSL::PKey.read(File.read(ARGV[1]))
|
30
|
+
ca = ::OpenSSL::X509::Store.new
|
31
|
+
ca.add_file(ARGV[2])
|
32
|
+
|
33
|
+
map_cn = {
|
34
|
+
'CN=client 1,OU=Test Client,OU=example,OU=org' => 'user1',
|
35
|
+
'CN=client 2,OU=Test Client,OU=example,OU=org' => 'user2',
|
36
|
+
'CN=client 3,OU=Test Client,OU=example,OU=org' => 'user3',
|
37
|
+
}
|
38
|
+
|
39
|
+
# email gateway
|
40
|
+
email_basic = ICFS::Email::Basic.new
|
41
|
+
email_smime = ICFS::Email::Smime.new(key, cert, ca, map_cn)
|
42
|
+
email = ICFS::Email::Core.new(api, log, [email_smime, email_basic])
|
43
|
+
|
44
|
+
txt = STDIN.read
|
45
|
+
res = email.receive(txt)
|
46
|
+
|
47
|
+
p res
|
data/devel/run/init-icfs.rb
CHANGED
data/devel/run/webrick.rb
CHANGED
@@ -10,68 +10,16 @@
|
|
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
|
-
|
14
|
-
require 'aws-sdk-s3'
|
15
|
-
require 'redis'
|
13
|
+
# frozen_string_literal: true
|
16
14
|
|
17
|
-
require_relative '
|
18
|
-
require_relative '../../lib/icfs/cache_elastic'
|
19
|
-
require_relative '../../lib/icfs/store_s3'
|
20
|
-
require_relative '../../lib/icfs/users_s3'
|
21
|
-
require_relative '../../lib/icfs/users_redis'
|
15
|
+
require_relative 'base'
|
22
16
|
require_relative '../../lib/icfs/web/client'
|
23
|
-
require_relative '../../lib/icfs/web/config_s3'
|
24
|
-
require_relative '../../lib/icfs/web/config_redis'
|
25
17
|
require_relative '../../lib/icfs/demo/auth'
|
26
18
|
require_relative '../../lib/icfs/demo/static'
|
27
19
|
|
28
|
-
|
29
|
-
|
30
|
-
endpoint: 'http://minio:9000',
|
31
|
-
access_key_id: 'minio_key',
|
32
|
-
secret_access_key: 'minio_secret',
|
33
|
-
force_path_style: true,
|
34
|
-
region: 'us-east-1'
|
35
|
-
)
|
20
|
+
base = get_base()
|
21
|
+
api = base[:api]
|
36
22
|
|
37
|
-
# default mapping
|
38
|
-
map = {
|
39
|
-
entry: 'entry',
|
40
|
-
case: 'case',
|
41
|
-
action: 'action',
|
42
|
-
index: 'index',
|
43
|
-
log: 'log',
|
44
|
-
lock: 'lock',
|
45
|
-
current: 'current',
|
46
|
-
}.freeze
|
47
|
-
|
48
|
-
# default config
|
49
|
-
defaults = {
|
50
|
-
'tz' => '-04:00'
|
51
|
-
}
|
52
|
-
|
53
|
-
# the log
|
54
|
-
log = Logger.new(STDERR)
|
55
|
-
log.level = Logger::INFO
|
56
|
-
|
57
|
-
# base items
|
58
|
-
s3 = Aws::S3::Client.new
|
59
|
-
redis = Redis.new(host: 'redis')
|
60
|
-
es = Faraday.new('http://elastic:9200')
|
61
|
-
cache = ICFS::CacheElastic.new(map, es)
|
62
|
-
store = ICFS::StoreS3.new(s3, 'icfs'.freeze, 'case/'.freeze)
|
63
|
-
users_base = ICFS::UsersS3.new(s3, 'icfs'.freeze, 'users/'.freeze)
|
64
|
-
users = ICFS::UsersRedis.new(redis, users_base, {
|
65
|
-
prefix: 'users/'.freeze,
|
66
|
-
expires: 60, # one minute cache for testing
|
67
|
-
log: log,
|
68
|
-
})
|
69
|
-
api = ICFS::Api.new([], users, cache, store)
|
70
|
-
config_base = ICFS::Web::ConfigS3.new(defaults, s3, 'icfs', 'config/')
|
71
|
-
config = ICFS::Web::ConfigRedis.new(redis, config_base, {
|
72
|
-
prefix: 'config/',
|
73
|
-
expires: 60, # debug, only cache for one minute
|
74
|
-
})
|
75
23
|
web = ICFS::Web::Client.new('/static/icfs.css', '/static/icfs.js')
|
76
24
|
|
77
25
|
# static files
|
@@ -87,7 +35,7 @@ static = {
|
|
87
35
|
}
|
88
36
|
|
89
37
|
app = Rack::Builder.new do
|
90
|
-
use(ICFS::Demo::Auth, api
|
38
|
+
use(ICFS::Demo::Auth, api)
|
91
39
|
use(ICFS::Demo::Static, static)
|
92
40
|
run web
|
93
41
|
end
|