wire-framework 0.1.4.26 → 0.1.5
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/LICENSE +201 -339
- data/README.md +16 -0
- data/lib/app.rb +38 -19
- data/lib/app/cache.rb +93 -84
- data/lib/app/db.rb +195 -196
- data/lib/app/file.rb +76 -72
- data/lib/app/history.rb +50 -49
- data/lib/app/history/svn.rb +43 -24
- data/lib/app/login.rb +23 -8
- data/lib/app/render.rb +16 -105
- data/lib/app/render/document.rb +57 -40
- data/lib/app/render/editor.rb +59 -44
- data/lib/app/render/error.rb +55 -35
- data/lib/app/render/instant.rb +71 -60
- data/lib/app/render/page.rb +104 -79
- data/lib/app/render/partial.rb +120 -99
- data/lib/app/render/style.rb +56 -42
- data/lib/app/repo.rb +141 -135
- data/lib/app/repo/svn.rb +203 -177
- data/lib/closet.rb +104 -92
- data/lib/closet/auth.rb +37 -53
- data/lib/closet/config.rb +34 -0
- data/lib/closet/context.rb +142 -98
- data/lib/closet/renderer.rb +44 -41
- data/lib/wire.rb +28 -16
- metadata +11 -40
- data/lib/closet/resource.rb +0 -20
data/lib/closet/auth.rb
CHANGED
@@ -1,57 +1,41 @@
|
|
1
|
+
##
|
2
|
+
# Copyright 2017 Bryan T. Meyers
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
##
|
1
16
|
|
2
17
|
module Wire
|
3
|
-
|
4
|
-
|
5
|
-
|
18
|
+
# Auth is a module for handling authorization
|
19
|
+
# @author Bryan T. Meyers
|
20
|
+
module Auth
|
6
21
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
actions = [:create, :read, :readAll, :update, :delete]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
actions
|
31
|
-
end
|
32
|
-
|
33
|
-
# Setup auth for an App
|
34
|
-
# @param [Symbol] level the type of authz to perform
|
35
|
-
# @param [Proc] block setup for the authz
|
36
|
-
# @return [void]
|
37
|
-
def auth(level, &block)
|
38
|
-
$current_app[:auth] = { level: level }
|
39
|
-
unless (level == :any) || (block.nil?)
|
40
|
-
Docile.dsl_eval(self, &block)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Select handler for :app level of auth
|
45
|
-
# @param [Module] handler the type of authz to perform
|
46
|
-
# @return [void]
|
47
|
-
def handler(handler)
|
48
|
-
$current_app[:auth][:handler] = handler
|
49
|
-
end
|
50
|
-
|
51
|
-
# Select user for :user level of auth
|
52
|
-
# @return [void]
|
53
|
-
def user(user)
|
54
|
-
$current_app[:auth][:user] = user
|
55
|
-
end
|
56
|
-
end
|
22
|
+
# Get the allowed actions for the current URI
|
23
|
+
# @param [Hash] context the context for this request
|
24
|
+
# @return [Array] the allowed actions for this URI
|
25
|
+
def actions_allowed(context)
|
26
|
+
if context.config['auth_read_only']
|
27
|
+
[:read, :readAll]
|
28
|
+
elsif context.config['auth_user']
|
29
|
+
if context.user == context.config['auth_user']
|
30
|
+
[:create, :read, :readAll, :update, :delete]
|
31
|
+
else
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
elsif context.config['auth_handler']
|
35
|
+
context.config['auth_handler'].actions_allowed(context)
|
36
|
+
else
|
37
|
+
[:create, :read, :readAll, :update, :delete]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
57
41
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
##
|
2
|
+
# Copyright 2017 Bryan T. Meyers
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
##
|
16
|
+
|
17
|
+
require 'yaml'
|
18
|
+
|
19
|
+
module Wire
|
20
|
+
module Config
|
21
|
+
def self.read_config_dir(dir, callback)
|
22
|
+
configs = {}
|
23
|
+
Dir[File.join(dir, '*.yaml')].each do |entry|
|
24
|
+
name = File.basename(entry, '.yaml')
|
25
|
+
config = YAML.load_file(File.join(dir, entry))
|
26
|
+
if callback
|
27
|
+
config = callback.call(config)
|
28
|
+
end
|
29
|
+
configs[name] = config
|
30
|
+
end
|
31
|
+
configs
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/closet/context.rb
CHANGED
@@ -1,106 +1,150 @@
|
|
1
|
+
##
|
2
|
+
# Copyright 2017 Bryan T. Meyers
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
##
|
16
|
+
|
17
|
+
require 'json'
|
18
|
+
require 'rest-less'
|
19
|
+
|
1
20
|
module Wire
|
2
|
-
|
3
|
-
|
21
|
+
# Context is a class containing information related to the current request
|
22
|
+
# @author Bryan T. Meyers
|
23
|
+
|
24
|
+
class Context
|
25
|
+
#@!attribute [r] action
|
26
|
+
# @return [Symbol] the action
|
27
|
+
#@!attribute [r] app
|
28
|
+
# @return [Hash] the name of the Wire::App
|
29
|
+
#@!attribute [r] body
|
30
|
+
# @return [String] the unparsed body
|
31
|
+
#@!attribute [r] config
|
32
|
+
# @return [Hash] the Wire::App configuration
|
33
|
+
#@!attribute [r] json
|
34
|
+
# @return [Hash] the JSON parsed body
|
35
|
+
#@!attribute [r] query
|
36
|
+
# @return [Hash] the parsed query string
|
37
|
+
#@!attribute [r] query_string
|
38
|
+
# @return [String] the raw query string
|
39
|
+
#@!attribute [r] rack_env
|
40
|
+
# @return [Hash] the raw Rack environment
|
41
|
+
#@!attribute [r] referer
|
42
|
+
# @return [Array] the referer URI
|
43
|
+
#@!attribute [r] resource
|
44
|
+
# @return [Symbol] the name of the resource
|
45
|
+
#@!attribute [r] uri
|
46
|
+
# @return [Array] the complete URI
|
47
|
+
#@!attribute [r] user
|
48
|
+
# @return [String] the REMOTE_USER
|
49
|
+
#@!attribute [r] verb
|
50
|
+
# @return [Symbol] the HTTP verb
|
51
|
+
|
52
|
+
attr_reader :action, :app, :body, :rack_env, :json, :query,
|
53
|
+
:query_string, :referer, :resource, :type,
|
54
|
+
:uri, :user, :verb
|
55
|
+
attr_writer :referer
|
4
56
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# @return [Hash] the raw Rack environment of the current request
|
14
|
-
#@!attribute [r] json
|
15
|
-
# @return [Hash] the JSON parsed body of the current request
|
16
|
-
#@!attribute [r] query
|
17
|
-
# @return [Hash] the parsed query string of the current request
|
18
|
-
#@!attribute [r] query_string
|
19
|
-
# @return [String] the raw query string of the current request
|
20
|
-
#@!attribute [r] referer
|
21
|
-
# @return [Array] the referer URI of the current request
|
22
|
-
#@!attribute [r] resource
|
23
|
-
# @return [Symbol] the Wire::Resource configuration of the current request
|
24
|
-
#@!attribute [r] type
|
25
|
-
# @return [Module] the Wire::App of the current request
|
26
|
-
#@!attribute [r] uri
|
27
|
-
# @return [Array] the URI of the current request
|
28
|
-
#@!attribute [r] user
|
29
|
-
# @return [String] the REMOTE_USER of the current request
|
30
|
-
#@!attribute [r] verb
|
31
|
-
# @return [Symbol] the HTTP verb of the current request
|
57
|
+
# Maps HTTP verbs to actions
|
58
|
+
HTTP_ACTIONS = {
|
59
|
+
'GET': :read,
|
60
|
+
'HEAD': :read,
|
61
|
+
'POST': :create,
|
62
|
+
'PUT': :update,
|
63
|
+
'DELETE': :delete
|
64
|
+
}
|
32
65
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
66
|
+
# Maps HTTP verbs to Symbols
|
67
|
+
HTTP_VERBS = {
|
68
|
+
'GET': :get,
|
69
|
+
'HEAD': :head,
|
70
|
+
'POST': :post,
|
71
|
+
'PUT': :put,
|
72
|
+
'DELETE': :delete
|
73
|
+
}
|
37
74
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
75
|
+
# Add user info to session
|
76
|
+
# @param [Hash] env the Rack environment
|
77
|
+
# @return [Hash] the updated environment
|
78
|
+
def update_session(env)
|
79
|
+
user = env['HTTP_REMOTE_USER']
|
80
|
+
unless user.nil? or user.empty? or user.eql? 'nobody' or user.eql? '(null)'
|
81
|
+
env['rack.session']['user'] = user
|
82
|
+
end
|
83
|
+
env['REMOTE_USER'] = env['rack.session']['user'] ? env['rack.session']['user'] : nil
|
84
|
+
env
|
85
|
+
end
|
46
86
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
87
|
+
# Builds a new Context
|
88
|
+
# @param [Hash] env the Rack environment
|
89
|
+
# @return [Context] a new Context
|
90
|
+
def initialize(env)
|
91
|
+
@rack_env = update_session(env)
|
92
|
+
@user = env['rack.session']['user']
|
93
|
+
@verb = HTTP_VERBS[env['REQUEST_METHOD']]
|
94
|
+
@action = HTTP_ACTIONS[env['REQUEST_METHOD']]
|
95
|
+
@uri = env['REQUEST_URI'].split('?')[0].split('/')
|
96
|
+
if env['HTTP_REFERER']
|
97
|
+
@referer = env['HTTP_REFERER'].split('/')
|
98
|
+
else
|
99
|
+
@referer = ['http:', '', env['HTTP_HOST']].concat(@uri[1...@uri.length])
|
100
|
+
end
|
101
|
+
@config = $wire_apps[@uri[1]]
|
102
|
+
if @config
|
103
|
+
@app = @uri[1]
|
104
|
+
@resource = @uri[2]
|
105
|
+
@id = context.uri[3...context.uri.length].join('/')
|
106
|
+
else
|
107
|
+
throw Exception.new("App: #{@uri[1]} is Undefined")
|
108
|
+
end
|
109
|
+
@query = {}
|
110
|
+
env['QUERY_STRING'].split('&').each do |q|
|
111
|
+
param = q.split('=')
|
112
|
+
@query[param[0].to_sym] = param[1]
|
113
|
+
end
|
114
|
+
@query_string = env['QUERY_STRING']
|
115
|
+
if env['rack.input']
|
116
|
+
@body = env['rack.input'].read
|
117
|
+
begin
|
118
|
+
@json = JSON.parse_clean(@body)
|
119
|
+
rescue JSON::ParserError
|
120
|
+
$stderr.puts 'Warning: Failed to parse body as JSON'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
55
124
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
env['REMOTE_USER'] = env['rack.session']['user'] ? env['rack.session']['user'] : nil
|
65
|
-
env
|
66
|
-
end
|
125
|
+
CONVERT = {
|
126
|
+
create: :post,
|
127
|
+
read: :get,
|
128
|
+
readAll: :get,
|
129
|
+
update: :put,
|
130
|
+
delete: :delete
|
131
|
+
}
|
67
132
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
@resource = app[:resources][@uri[2]]
|
86
|
-
@type = app[:type]
|
87
|
-
else
|
88
|
-
throw Exception.new("App: #{@uri[1]} is Undefined")
|
89
|
-
end
|
90
|
-
@query = {}
|
91
|
-
env['QUERY_STRING'].split('&').each do |q|
|
92
|
-
param = q.split('=')
|
93
|
-
@query[param[0].to_sym] = param[1]
|
94
|
-
end
|
95
|
-
@query_string = env['QUERY_STRING']
|
96
|
-
if env['rack.input']
|
97
|
-
@body = env['rack.input'].read
|
98
|
-
begin
|
99
|
-
@json = JSON.parse_clean(@body)
|
100
|
-
rescue JSON::ParserError
|
101
|
-
$stderr.puts 'Warning: Failed to parse body as JSON'
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
133
|
+
# Proxy method used when forwarding requests
|
134
|
+
# @param [Symbol] method the action to use when forwarding
|
135
|
+
# @return [Response] a Rack Response triplet, or status code
|
136
|
+
def forward(method)
|
137
|
+
headers = { referer: @referer.join('/'),
|
138
|
+
remote_user: @user }
|
139
|
+
verb = CONVERT[method]
|
140
|
+
uri = "http://#{@app['remote']}/#{@uri[2]}"
|
141
|
+
if [:update, :read, :delete].include?(method)
|
142
|
+
uri += "/#{@uri[3...@uri.length].join('/')}"
|
143
|
+
end
|
144
|
+
uri += '?' + @query_string
|
145
|
+
body = [:create, :update].include?(method) ? @body : nil
|
146
|
+
$stderr.puts "#{verb.upcase}: Forward Request to #{uri}"
|
147
|
+
RL.request verb, uri, headers, body
|
148
|
+
end
|
149
|
+
end
|
106
150
|
end
|
data/lib/closet/renderer.rb
CHANGED
@@ -1,46 +1,49 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
##
|
2
|
+
# Copyright 2017 Bryan T. Meyers
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
##
|
16
|
+
|
17
|
+
require 'tilt'
|
18
|
+
require_relative 'config'
|
5
19
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def renderer(klass, &block)
|
11
|
-
$current_renderer = klass
|
12
|
-
$current_editor = nil
|
13
|
-
Docile.dsl_eval(self, &block)
|
14
|
-
end
|
20
|
+
module Wire
|
21
|
+
# Renderer is a module for mapping mime to rendering templates
|
22
|
+
# @author Bryan T. Meyers
|
23
|
+
module Renderer
|
15
24
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
if $current_editor
|
25
|
-
$editors[mime] = $current_editor
|
26
|
-
end
|
27
|
-
end
|
25
|
+
# Callback for handling partials
|
26
|
+
# @param [Hash] conf the raw configuration
|
27
|
+
# @return [Hash] post-processed configuration
|
28
|
+
def self.configure_partial(conf)
|
29
|
+
conf['partial'] = Tilt.new(conf['partial'], 1, { ugly: true })
|
30
|
+
conf
|
31
|
+
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
# Callback for handling templates
|
34
|
+
# @param [Hash] conf the raw configuration
|
35
|
+
# @return [Hash] post-processed configuration
|
36
|
+
def self.configure_template(conf)
|
37
|
+
conf['partial'] = Tilt.new(conf['file'], 1, { ugly: true })
|
38
|
+
conf
|
39
|
+
end
|
35
40
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
41
|
+
# Read all of the configs in './configs/apps'
|
42
|
+
# @return [void]
|
43
|
+
def self.read_configs
|
44
|
+
$wire_editors = Wire::Config.read_config_dir('config/editors', method(:configure_partial))
|
45
|
+
$wire_renderers = Wire::Config.read_config_dir('config/renderers', method(:configure_partial))
|
46
|
+
$wire_templates = Wire::Config.read_config_dir('config/templates', method(:configure_template))
|
47
|
+
end
|
48
|
+
end
|
46
49
|
end
|