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.
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
- # Auth is a module for handling authorization
4
- # @author Bryan T. Meyers
5
- module Auth
18
+ # Auth is a module for handling authorization
19
+ # @author Bryan T. Meyers
20
+ module Auth
6
21
 
7
- # Get the allowed actions for the current URI
8
- # @param [Hash] context the context for this request
9
- # @return [Array] the allowed actions for this URI
10
- def actions_allowed(context)
11
- actions = []
12
- app = context.app
13
- user = context.user
14
- if app
15
- auth = app[:auth]
16
- level = auth[:level]
17
- case level
18
- when :any
19
- actions = [:create, :read, :readAll, :update, :delete]
20
- when :app
21
- actions = auth[:handler].actions_allowed(context)
22
- when :read_only
23
- actions = [:read,:readAll]
24
- when :user
25
- if user == auth[:user]
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
@@ -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
- # Context is a class containing request information
3
- # @author Bryan T. Meyers
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
- class Context
6
- #@!attribute [r] action
7
- # @return [Symbol] the action for the current request
8
- #@!attribute [r] app
9
- # @return [Hash] the Wire::App configuration for the current request
10
- #@!attribute [r] body
11
- # @return [String] the unparsed body of the current request
12
- #@!attribute [r] env
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
- attr_reader :action, :app, :body, :env, :json, :query,
34
- :query_string, :referer, :resource, :type,
35
- :uri, :user, :verb
36
- attr_writer :referer
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
- # Maps HTTP verbs to actions
39
- HTTP_ACTIONS = {
40
- 'GET' => :read,
41
- 'HEAD' => :read,
42
- 'POST' => :create,
43
- 'PUT' => :update,
44
- 'DELETE' => :delete
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
- # Maps HTTP verbs to Symbols
48
- HTTP_VERBS = {
49
- 'GET' => :get,
50
- 'HEAD' => :head,
51
- 'POST' => :post,
52
- 'PUT' => :put,
53
- 'DELETE' => :delete
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
- # Add user info to session
57
- # @param [Hash] env the Rack environment
58
- # @return [Hash] the updated environment
59
- def update_session(env)
60
- user = env['HTTP_REMOTE_USER']
61
- unless user.nil? or user.empty? or user.eql? 'nobody' or user.eql? '(null)'
62
- env['rack.session']['user'] = user
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
- # Builds a new Context
69
- # @param [Hash] env the Rack environment
70
- # @return [Context] a new Context
71
- def initialize(env)
72
- @env = update_session(env)
73
- @user = env['rack.session']['user']
74
- @verb = HTTP_VERBS[env['REQUEST_METHOD']]
75
- @action = HTTP_ACTIONS[env['REQUEST_METHOD']]
76
- @uri = env['REQUEST_URI'].split('?')[0].split('/')
77
- if env['HTTP_REFERER']
78
- @referer = env['HTTP_REFERER'].split('/')
79
- else
80
- @referer = [ 'http:' , '' , env['HTTP_HOST']].concat(@uri[1...@uri.length])
81
- end
82
- app = $apps[@uri[1]]
83
- if app
84
- @app = app
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
@@ -1,46 +1,49 @@
1
- module Wire
2
- # Renderer is a module for mapping mime to rendering templates
3
- # @author Bryan T. Meyers
4
- module Renderer
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
- # Setup a Renderer
7
- # @param [Class] klass the type of renderer to use
8
- # @param [Proc] block for configuring this renderer
9
- # @return [void]
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
- # Associate a MIME type to the current Renderer or Editor
17
- # @param [String] mime the MIME type
18
- # @return [void]
19
- def mime(mime)
20
- if $current_renderer
21
- $renderers[mime] = $current_renderer
22
- $templates[$current_renderer] = $current_template
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
- # Setup a new template
30
- # @param [String] template the template for a renderer or editor
31
- # @return [void]
32
- def partial(template)
33
- $current_template = Tilt.new(template, 1, { ugly: true })
34
- end
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
- # Setup an Editor
37
- # @param [Class] editor the template for this Editor
38
- # @param [Proc] block for configuring this Editor
39
- # @return [void]
40
- def editor(editor, &block)
41
- $current_editor = Tilt.new(editor, 1, { ugly: true })
42
- $current_renderer = nil
43
- Docile.dsl_eval(self, &block)
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