kstor 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/bin/kstor +48 -40
- data/bin/kstor-srv +2 -2
- data/lib/kstor/config.rb +2 -1
- data/lib/kstor/controller/authentication.rb +25 -4
- data/lib/kstor/controller/base.rb +61 -0
- data/lib/kstor/controller/request_handler.rb +84 -16
- data/lib/kstor/controller/secret.rb +63 -64
- data/lib/kstor/controller/users.rb +11 -22
- data/lib/kstor/controller.rb +3 -3
- data/lib/kstor/crypto/armored_value.rb +82 -0
- data/lib/kstor/crypto/keys.rb +9 -41
- data/lib/kstor/crypto.rb +0 -1
- data/lib/kstor/error.rb +36 -3
- data/lib/kstor/log/simple_logger.rb +83 -0
- data/lib/kstor/log/systemd_logger.rb +22 -0
- data/lib/kstor/log.rb +53 -4
- data/lib/kstor/message/base.rb +223 -0
- data/lib/kstor/message/error.rb +15 -0
- data/lib/kstor/message/group_create.rb +14 -0
- data/lib/kstor/message/group_created.rb +16 -0
- data/lib/kstor/message/ping.rb +14 -0
- data/lib/kstor/message/pong.rb +14 -0
- data/lib/kstor/message/secret_create.rb +16 -0
- data/lib/kstor/message/secret_created.rb +14 -0
- data/lib/kstor/message/secret_delete.rb +14 -0
- data/lib/kstor/message/secret_deleted.rb +14 -0
- data/lib/kstor/message/secret_list.rb +14 -0
- data/lib/kstor/message/secret_search.rb +14 -0
- data/lib/kstor/message/secret_unlock.rb +14 -0
- data/lib/kstor/message/secret_update_meta.rb +15 -0
- data/lib/kstor/message/secret_update_value.rb +15 -0
- data/lib/kstor/message/secret_updated.rb +14 -0
- data/lib/kstor/message/secret_value.rb +35 -0
- data/lib/kstor/message.rb +26 -113
- data/lib/kstor/model.rb +42 -25
- data/lib/kstor/server.rb +15 -3
- data/lib/kstor/session.rb +34 -2
- data/lib/kstor/socket_server.rb +20 -1
- data/lib/kstor/sql_connection.rb +16 -1
- data/lib/kstor/store.rb +182 -72
- data/lib/kstor/systemd.rb +5 -0
- data/lib/kstor/version.rb +2 -1
- data/lib/kstor.rb +1 -1
- metadata +25 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74582d56a367754e14553d134666e9fe82322f5a61d2e87905b846e539f5a395
|
4
|
+
data.tar.gz: 36bc6b27ea95681d1214f2c2194773114cee637b4f039a56571b0fdf606174a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18522832bdcd1af680938d8f89857ce74c535763d4912782ea40b303374ce3bbd8fe9d6f8432773b19c86b44459ded250e3048a897678086b6b72c8cc863cdc6
|
7
|
+
data.tar.gz: 76798cadbb665be06ca2292c5365603fc242b3f841efc2411d9e93f32091e05366bc82ba06dc9d0ed87e178f0bdd552cf1021deb129a33ea1f8511b2abba9c96
|
data/README.md
CHANGED
@@ -28,7 +28,7 @@ group key pairs. Group private keys are used to decrypt secrets. Pfew!
|
|
28
28
|
4. systemctl --user start kstor.socket
|
29
29
|
5. bundle exec kstor --help
|
30
30
|
|
31
|
-
|
31
|
+
## Available request types
|
32
32
|
|
33
33
|
So far I've implemented:
|
34
34
|
* group-create
|
@@ -39,7 +39,7 @@ So far I've implemented:
|
|
39
39
|
* secret-update-value
|
40
40
|
* secret-delete
|
41
41
|
|
42
|
-
|
42
|
+
## Notes
|
43
43
|
|
44
44
|
On first access, it will create your user in database (login defaults to your
|
45
45
|
login). Passwords are asked interactively.
|
@@ -47,3 +47,7 @@ login). Passwords are asked interactively.
|
|
47
47
|
It will store session ID in XDG_RUNTIME_DIR/kstor/session-id .
|
48
48
|
|
49
49
|
Each request can be authentified either with login/password or with session ID.
|
50
|
+
|
51
|
+
## Badges
|
52
|
+
|
53
|
+
Gem version on Rubygems.org: [![Gem Version](https://badge.fury.io/rb/kstor.svg)](https://badge.fury.io/rb/kstor)
|
data/bin/kstor
CHANGED
@@ -13,14 +13,17 @@ module KStor
|
|
13
13
|
# Manage KStor client configuration and state on disk.
|
14
14
|
module ClientState
|
15
15
|
class << self
|
16
|
+
# Default client config.
|
16
17
|
DEFAULT_CONFIG = {
|
17
|
-
'socket' => '/
|
18
|
+
'socket' => '/run/kstor.socket'
|
18
19
|
}.freeze
|
19
20
|
|
21
|
+
# Load client config from disk.
|
20
22
|
def load_config(progr)
|
21
23
|
DEFAULT_CONFIG.merge(load_config_file(progr))
|
22
24
|
end
|
23
25
|
|
26
|
+
# Path to session ID file on disk.
|
24
27
|
def session_id_file(progr)
|
25
28
|
dir = File.join(xdg_runtime, progr)
|
26
29
|
FileUtils.mkdir_p(dir)
|
@@ -30,6 +33,7 @@ module KStor
|
|
30
33
|
file
|
31
34
|
end
|
32
35
|
|
36
|
+
# Load session ID from disk.
|
33
37
|
def load_session_id(progr)
|
34
38
|
sid = nil
|
35
39
|
File.open(session_id_file(progr)) { |f| sid = f.read.chomp }
|
@@ -59,12 +63,11 @@ module KStor
|
|
59
63
|
def config_file(progr)
|
60
64
|
dir = File.join(xdg_config, progr)
|
61
65
|
FileUtils.mkdir_p(dir)
|
62
|
-
File.join(dir, '
|
66
|
+
File.join(dir, 'config.yaml')
|
63
67
|
end
|
64
68
|
|
65
69
|
def load_config_file(progr)
|
66
|
-
|
67
|
-
YAML.parse(data)
|
70
|
+
YAML.load_file(config_file(progr))
|
68
71
|
rescue Errno::ENOENT
|
69
72
|
{}
|
70
73
|
end
|
@@ -73,14 +76,16 @@ module KStor
|
|
73
76
|
|
74
77
|
# Sub-commands that can be invoked from the command-line.
|
75
78
|
module ClientSubCommands
|
79
|
+
# Create a user group.
|
76
80
|
def group_create
|
77
|
-
request('
|
81
|
+
request('group_create') do |o|
|
78
82
|
o.string('-n', '--name', 'Group name')
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
86
|
+
# Create a secret.
|
82
87
|
def secret_create
|
83
|
-
|
88
|
+
request_with_meta('secret_create') do |o|
|
84
89
|
o.string('-p', '--plaintext', 'Value of the secret')
|
85
90
|
o.array('-g', '--group_ids', 'Groups that can unlock the secret')
|
86
91
|
o.string('-a', '--app', 'application of this secret')
|
@@ -89,11 +94,11 @@ module KStor
|
|
89
94
|
o.string('-S', '--server', 'server of this secret')
|
90
95
|
o.string('-u', '--url', 'url for this secret')
|
91
96
|
end
|
92
|
-
reorganize_secret_meta_args(req)
|
93
97
|
end
|
94
98
|
|
99
|
+
# Return a list of matching secrets.
|
95
100
|
def secret_search
|
96
|
-
|
101
|
+
request_with_meta('secret_search') do |o|
|
97
102
|
o.string('-a', '--app', 'secrets for this application')
|
98
103
|
o.string('-d', '--database', 'secrets for this database')
|
99
104
|
o.string('-l', '--login', 'secrets for this login')
|
@@ -102,14 +107,16 @@ module KStor
|
|
102
107
|
end
|
103
108
|
end
|
104
109
|
|
110
|
+
# Decrypt secret value and metadata
|
105
111
|
def secret_unlock
|
106
|
-
request('
|
112
|
+
request('secret_unlock') do |o|
|
107
113
|
o.string('-s', '--secret-id', 'secret ID to unlock')
|
108
114
|
end
|
109
115
|
end
|
110
116
|
|
117
|
+
# Update secret metadata
|
111
118
|
def secret_update_meta
|
112
|
-
|
119
|
+
request_with_meta('secret_update_meta') do |o|
|
113
120
|
o.string('-s', '--secret-id', 'secret ID to modify')
|
114
121
|
o.string('-a', '--app', 'new application of this secret')
|
115
122
|
o.string('-d', '--database', 'new database of this secret')
|
@@ -117,18 +124,19 @@ module KStor
|
|
117
124
|
o.string('-S', '--server', 'new server of this secret')
|
118
125
|
o.string('-u', '--url', 'new url for this secret')
|
119
126
|
end
|
120
|
-
reorganize_secret_meta_args(req)
|
121
127
|
end
|
122
128
|
|
129
|
+
# Update secret value
|
123
130
|
def secret_update_value
|
124
|
-
request('
|
131
|
+
request('secret_update_value') do |o|
|
125
132
|
o.string('-s', '--secret-id', 'secret ID to modify')
|
126
133
|
o.string('-p', '--plaintext', 'new plaintext value')
|
127
134
|
end
|
128
135
|
end
|
129
136
|
|
137
|
+
# Delete secret
|
130
138
|
def secret_delete
|
131
|
-
request('
|
139
|
+
request('secret_delete') do |o|
|
132
140
|
o.string('-s', '--secret-id', 'secret ID to delete')
|
133
141
|
end
|
134
142
|
end
|
@@ -138,14 +146,16 @@ module KStor
|
|
138
146
|
class Client
|
139
147
|
include ClientSubCommands
|
140
148
|
|
149
|
+
# Create new command-line client.
|
141
150
|
def initialize
|
142
151
|
@progr = File.basename($PROGRAM_NAME)
|
143
152
|
@config = ClientState.load_config(@progr)
|
144
153
|
@user = user_from_argv
|
145
154
|
end
|
146
155
|
|
156
|
+
# Read command-line args, send request to server and display results..
|
147
157
|
def run
|
148
|
-
request_type = ARGV.shift
|
158
|
+
request_type = ARGV.shift.to_sym
|
149
159
|
resp = send_request(request_type)
|
150
160
|
handle_error!(resp) if resp.error?
|
151
161
|
|
@@ -178,7 +188,7 @@ module KStor
|
|
178
188
|
end
|
179
189
|
|
180
190
|
def handle_error!(resp)
|
181
|
-
if resp.
|
191
|
+
if resp.code == 'AUTH/BADSESSION'
|
182
192
|
FileUtils.rm(ClientState.session_id_file(@progr))
|
183
193
|
warn('session expired')
|
184
194
|
else
|
@@ -195,34 +205,23 @@ module KStor
|
|
195
205
|
socket.send(req.serialize, 0)
|
196
206
|
|
197
207
|
data, = socket.recvfrom(4096)
|
198
|
-
|
199
|
-
rescue UnparsableResponse
|
200
|
-
warn('
|
208
|
+
Message::Base.parse(data)
|
209
|
+
rescue Message::UnparsableResponse
|
210
|
+
warn('Invalid response from server; look at logs!')
|
201
211
|
exit(1)
|
202
212
|
end
|
203
213
|
|
204
|
-
REQUEST_METHODS = {
|
205
|
-
'group-create' => :group_create,
|
206
|
-
'secret-create' => :secret_create,
|
207
|
-
'secret-search' => :secret_search,
|
208
|
-
'secret-unlock' => :secret_unlock,
|
209
|
-
'secret-update-meta' => :secret_update_meta,
|
210
|
-
'secret-update-value' => :secret_update_value,
|
211
|
-
'secret-delete' => :secret_delete
|
212
|
-
}.freeze
|
213
|
-
|
214
214
|
def method_name(request_type)
|
215
215
|
if request_type.nil?
|
216
216
|
base_usage
|
217
217
|
exit 0
|
218
218
|
end
|
219
|
-
|
220
|
-
if meth.nil?
|
219
|
+
unless KStor::Message::Base.type?(request_type)
|
221
220
|
warn("Unknown request type #{request_type.inspect}")
|
222
221
|
base_usage
|
223
222
|
exit 1
|
224
223
|
end
|
225
|
-
|
224
|
+
request_type
|
226
225
|
end
|
227
226
|
|
228
227
|
def user_from_argv
|
@@ -250,19 +249,28 @@ module KStor
|
|
250
249
|
session_id = ClientState.load_session_id(@progr)
|
251
250
|
|
252
251
|
if session_id
|
253
|
-
{
|
252
|
+
{ session_id: }
|
254
253
|
else
|
255
|
-
{
|
254
|
+
{ login: @user, password: ask_password }
|
256
255
|
end
|
257
256
|
end
|
258
257
|
|
258
|
+
def request_with_meta(type, &block)
|
259
|
+
args = parse_opts(type) { |o| block.call(o) }
|
260
|
+
args['meta'] = {
|
261
|
+
'app' => args.delete('app'),
|
262
|
+
'database' => args.delete('database'),
|
263
|
+
'login' => args.delete('login'),
|
264
|
+
'server' => args.delete('server'),
|
265
|
+
'url' => args.delete('url')
|
266
|
+
}
|
267
|
+
args['meta'].compact!
|
268
|
+
KStor::Message::Base.for_type(type, args, **auth)
|
269
|
+
end
|
270
|
+
|
259
271
|
def request(type, &block)
|
260
|
-
|
261
|
-
|
262
|
-
hreq['args'] = parse_opts(type) do |o|
|
263
|
-
block.call(o)
|
264
|
-
end
|
265
|
-
KStor::Message.parse_request(hreq.merge(auth).to_json)
|
272
|
+
args = parse_opts(type) { |o| block.call(o) }
|
273
|
+
KStor::Message::Base.for_type(type, args, **auth)
|
266
274
|
end
|
267
275
|
|
268
276
|
def parse_opts(request_type)
|
@@ -277,7 +285,7 @@ module KStor
|
|
277
285
|
o.separator('')
|
278
286
|
yield o
|
279
287
|
end
|
280
|
-
opts.to_hash.compact
|
288
|
+
opts.to_hash.compact.transform_keys(&:to_s)
|
281
289
|
end
|
282
290
|
end
|
283
291
|
end
|
data/bin/kstor-srv
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
|
4
4
|
require 'kstor'
|
5
5
|
|
6
|
-
KStor::Log.reporting_level = Journald::LOG_DEBUG
|
7
|
-
|
8
6
|
config = KStor::Config.load(ARGV.shift)
|
9
7
|
|
8
|
+
KStor::Log.reporting_level = config.log_level
|
9
|
+
|
10
10
|
store = KStor::Store.new(config.database)
|
11
11
|
session_store = KStor::SessionStore.new(
|
12
12
|
config.session_idle_timeout,
|
data/lib/kstor/config.rb
CHANGED
@@ -8,13 +8,28 @@ require 'kstor/model'
|
|
8
8
|
|
9
9
|
module KStor
|
10
10
|
module Controller
|
11
|
-
#
|
11
|
+
# Specialized controller for user authentication and sessions.
|
12
12
|
class Authentication
|
13
|
+
# Create new auth controller.
|
14
|
+
#
|
15
|
+
# @param store [KStor::Store] data store where users are
|
16
|
+
# @param session_store [KStor::SessionStore] where user sessions are
|
17
|
+
# @return [KStor::Controller::Authentication] new auth controller
|
13
18
|
def initialize(store, session_store)
|
14
19
|
@store = store
|
15
20
|
@sessions = session_store
|
16
21
|
end
|
17
22
|
|
23
|
+
# Authenticate request user.
|
24
|
+
#
|
25
|
+
# Request may either contain a login/password, or a session ID.
|
26
|
+
#
|
27
|
+
# @param req [KStor::Message::Base] client request
|
28
|
+
# @return [KStor::Model::User] client user
|
29
|
+
# @raise [KStor::InvalidSession] if session ID is invalid
|
30
|
+
# @raise [KStor::UserNotAllowed] if user is not allowed
|
31
|
+
# @raise [KStor::MissingLoginPassword] if database is empty and request
|
32
|
+
# only contains a session ID
|
18
33
|
def authenticate(req)
|
19
34
|
if @store.users?
|
20
35
|
unlock_user(req)
|
@@ -23,13 +38,19 @@ module KStor
|
|
23
38
|
end
|
24
39
|
end
|
25
40
|
|
26
|
-
#
|
41
|
+
# Check if user is allowed to access the application.
|
42
|
+
#
|
43
|
+
# @param user [KStor::Model::User] client user
|
44
|
+
# @return [Boolean] true if login is allowed to access application data.
|
27
45
|
def allowed?(user)
|
28
46
|
user.status == 'new' || user.status == 'active'
|
29
47
|
end
|
30
48
|
|
49
|
+
private
|
50
|
+
|
51
|
+
# Load user from database and decrypt private key and keychain.
|
31
52
|
def unlock_user(req)
|
32
|
-
if req.
|
53
|
+
if req.session_request?
|
33
54
|
session_id = req.session_id
|
34
55
|
user, secret_key = load_session(session_id)
|
35
56
|
else
|
@@ -72,7 +93,7 @@ module KStor
|
|
72
93
|
)
|
73
94
|
secret_key = user.secret_key(req.password)
|
74
95
|
user.unlock(secret_key)
|
75
|
-
@store.user_create(user)
|
96
|
+
user.id = @store.user_create(user)
|
76
97
|
Log.info("user #{user.login} created")
|
77
98
|
|
78
99
|
session = Session.create(user, secret_key)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KStor
|
4
|
+
# Various controllers that participate in serving client.
|
5
|
+
module Controller
|
6
|
+
# Common code for all controllers (except RequestHandler).
|
7
|
+
#
|
8
|
+
# @abstract
|
9
|
+
class Base
|
10
|
+
class << self
|
11
|
+
attr_accessor :request_types
|
12
|
+
attr_accessor :response_types
|
13
|
+
|
14
|
+
# Declare that this controller handles this type of request.
|
15
|
+
def request_type(klass)
|
16
|
+
@request_types ||= []
|
17
|
+
@request_types << klass
|
18
|
+
end
|
19
|
+
|
20
|
+
# Declare that this controller produces this type of response.
|
21
|
+
def response_type(klass)
|
22
|
+
@response_types ||= []
|
23
|
+
@response_types << klass
|
24
|
+
end
|
25
|
+
|
26
|
+
# True if sub-controller handles these requests.
|
27
|
+
#
|
28
|
+
# @param type [String] request type
|
29
|
+
# @return [Boolean] true if request type may be handled
|
30
|
+
def handles?(req)
|
31
|
+
@request_types.include?(req.class)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create sub-controller with access to data store.
|
36
|
+
#
|
37
|
+
# @param store [KStor::Store] data store
|
38
|
+
# @return [KStor::Controller::Base] a new sub-controller
|
39
|
+
def initialize(store)
|
40
|
+
@store = store
|
41
|
+
@request_handlers = self.class.request_types.to_h do |klass|
|
42
|
+
meth = "handle_#{klass.type}".to_sym
|
43
|
+
[klass, meth]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Handle client request.
|
48
|
+
#
|
49
|
+
# @param user [KStor::Model::User] user making this request
|
50
|
+
# @param req [KStor::Message::Base] client request
|
51
|
+
def handle_request(user, sid, req)
|
52
|
+
unless @request_handlers.key?(req.class)
|
53
|
+
raise Error.for_code('REQ/UNKNOWN', req.type)
|
54
|
+
end
|
55
|
+
|
56
|
+
klass, args = __send__(@request_handlers[req.class], user, req)
|
57
|
+
klass.new(args, { session_id: sid })
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -9,41 +9,109 @@ require 'kstor/controller/users'
|
|
9
9
|
|
10
10
|
module KStor
|
11
11
|
module Controller
|
12
|
-
#
|
12
|
+
# Undeclared response type.
|
13
|
+
class UnknownResponseType < RuntimeError
|
14
|
+
end
|
15
|
+
|
16
|
+
# Top-level request handler.
|
17
|
+
#
|
18
|
+
# Dispatches requests to specialized sub-controller.
|
13
19
|
class RequestHandler
|
20
|
+
class << self
|
21
|
+
# List of sub-controllers.
|
22
|
+
attr_accessor :controllers
|
23
|
+
|
24
|
+
# Request types handled by all sub-controllers.
|
25
|
+
#
|
26
|
+
# @return [Array[String]] list of all handled request types
|
27
|
+
def request_types
|
28
|
+
@controllers.map(&:request_types).inject([], &:+)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Response types that sub-controllers can produce.
|
32
|
+
#
|
33
|
+
# @return [Array[String]] list of all response types that this handler
|
34
|
+
# can produce
|
35
|
+
def response_types
|
36
|
+
[Message::Error] + @controllers.map(&:response_types).inject([], &:+)
|
37
|
+
end
|
38
|
+
|
39
|
+
# All message types handled and produced by this controller.
|
40
|
+
#
|
41
|
+
# @return [Array[String]] List of all message types
|
42
|
+
def message_types
|
43
|
+
request_types + response_types
|
44
|
+
end
|
45
|
+
|
46
|
+
# True if this controller can handle this request type.
|
47
|
+
#
|
48
|
+
# @param type [Class] request type
|
49
|
+
# @return [Boolean] true if handled
|
50
|
+
def handles?(type)
|
51
|
+
request_types.include?(type)
|
52
|
+
end
|
53
|
+
|
54
|
+
# True if this controller can respond to a client with this type of
|
55
|
+
# reponse.
|
56
|
+
#
|
57
|
+
# @param type [String] response type
|
58
|
+
# @return [Boolean] true if can be produced.
|
59
|
+
def responds?(type)
|
60
|
+
response_types.include?(type)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
self.controllers = [Controller::User, Controller::Secret]
|
65
|
+
|
66
|
+
# Create new request handler controller from data store and session store.
|
67
|
+
#
|
68
|
+
# @param store [KStor::Store] data store
|
69
|
+
# @param session_store [KStor::SessionStore] session store
|
70
|
+
# @return [KStor::Controller::RequestHandler] new top-level controller.
|
14
71
|
def initialize(store, session_store)
|
15
72
|
@auth = Controller::Authentication.new(store, session_store)
|
16
|
-
@secret = Controller::Secret.new(store)
|
17
|
-
@user = Controller::User.new(store)
|
18
73
|
@store = store
|
74
|
+
@controllers = self.class.controllers.map do |klass|
|
75
|
+
klass.new(store)
|
76
|
+
end
|
19
77
|
end
|
20
78
|
|
79
|
+
# Serve a client.
|
80
|
+
#
|
81
|
+
# @param req [KStor::Message::Base] client request
|
82
|
+
# @return [KStor::Message::Base] server response
|
21
83
|
def handle_request(req)
|
22
84
|
user, sid = @auth.authenticate(req)
|
23
85
|
controller = controller_from_request_type(req)
|
24
|
-
resp = @store.transaction { controller.handle_request(user, req) }
|
86
|
+
resp = @store.transaction { controller.handle_request(user, sid, req) }
|
25
87
|
user.lock
|
26
|
-
resp
|
27
|
-
resp
|
88
|
+
finish_response(resp)
|
28
89
|
rescue RbNaClError => e
|
29
90
|
Log.exception(e)
|
30
|
-
Error.for_code('CRYPTO/UNSPECIFIED').response
|
31
|
-
rescue
|
91
|
+
Error.for_code('CRYPTO/UNSPECIFIED').response(sid)
|
92
|
+
rescue KStor::MissingMessageArgument => e
|
93
|
+
raise e
|
94
|
+
rescue KStor::Error => e
|
32
95
|
Log.info(e.message)
|
33
|
-
e.response
|
96
|
+
e.response(sid)
|
34
97
|
end
|
35
98
|
|
36
99
|
private
|
37
100
|
|
101
|
+
def finish_response(resp)
|
102
|
+
unless self.class.responds?(resp.class)
|
103
|
+
raise UnknownResponseType, 'Unknown response type ' \
|
104
|
+
"#{resp.type.inspect}"
|
105
|
+
end
|
106
|
+
resp
|
107
|
+
end
|
108
|
+
|
38
109
|
def controller_from_request_type(req)
|
39
|
-
|
40
|
-
|
41
|
-
@secret
|
42
|
-
when /^group-create$/
|
43
|
-
@user
|
44
|
-
else
|
45
|
-
raise Error.for_code('REQ/UNKNOWN', req.type)
|
110
|
+
@controllers.each do |ctrl|
|
111
|
+
return ctrl if ctrl.class.handles?(req)
|
46
112
|
end
|
113
|
+
|
114
|
+
raise Error.for_code('REQ/UNKNOWN', req.type)
|
47
115
|
end
|
48
116
|
end
|
49
117
|
end
|