tzispa 0.7.6 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13911ddd5b938320efb3e6aa971d996be88581e5
4
- data.tar.gz: a054ae603791f5a57a66b40a837ea5fd95b254cb
3
+ metadata.gz: 4afde718b4afe167e5e25031d064aa92c826162b
4
+ data.tar.gz: 51c74b98a6a21715a6cd1f23dcf70b5974c1211b
5
5
  SHA512:
6
- metadata.gz: 28359f1534f2799ab711386a2caab2641bb047b663a864de73c815851192e772e520acc3d71831c2cabe3143e4706b3fa4702975a9d8b7e147f85212b55c4135
7
- data.tar.gz: 976f8d1b4b7e18af9887e3400d56320de2a45e300822b696846441dc7f2557f35eed6a56eb649722d02f711dcc91f88f6b7e611aa0004385ff073c48f6b6cd77
6
+ metadata.gz: 63d7bb48cd522eacd349ca5284271fc30ae263558f82a959e4308e31a5ed5e9de56b7cb77489b9bd07faf6382394f8243cee3dabe7b4dd5b399911f6818654fb
7
+ data.tar.gz: 93450d79ad98a19086ff28b9555efb179bb3da19f4565e8157569b5ad1d44085dc9ee2978da87c4ba3724a8e88cb2efab3277e43ad4c413bb85be20420032fe7
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@ Tzispa
2
2
 
3
3
  General purpose web framework
4
4
 
5
+ ## v0.8.0
6
+ - introducing support for other template engines
7
+ - improve errors log
8
+ - bugs fixes
9
+
5
10
  ## v0.7.6
6
11
  - added custom error pages option in base controller
7
12
  - disable custom error page in the api controller
@@ -29,14 +29,15 @@ module Tzispa
29
29
 
30
30
  using Tzispa::Utils::TzString
31
31
 
32
- attr_reader :context, :type, :data, :error, :status
32
+ attr_reader :context, :type, :data, :error, :rescue_hook, :status
33
33
  def_delegators :@context, :request, :response, :app, :repository,
34
- :config, :logger, :unauthorized_but_logged, :login_redirect
34
+ :config, :logger, :error_log, :info_log
35
35
 
36
36
  def initialize(context)
37
37
  @context = context
38
38
  @error = nil
39
39
  @status = nil
40
+ @rescue_hook = nil
40
41
  end
41
42
 
42
43
  def result(type:, data: nil)
@@ -56,20 +57,31 @@ module Tzispa
56
57
  result type: :redirect, data: data
57
58
  end
58
59
 
59
- def error_status(code, http_status = nil)
60
- @error = code
60
+ def error_status(error_code, http_status = nil)
61
+ @error = error_code
61
62
  @status = http_status
62
- result_json error_message: message, error_code: code
63
+ result_json error_message: error_message
64
+ end
65
+ # alias result_error error_status
66
+
67
+ def on_error(http_error, error_code = nil, logger = nil)
68
+ @rescue_hook = { logger: logger, error_code: error_code, http_error: http_error }
63
69
  end
64
- alias result_error error_status
65
70
 
66
71
  def run!(verb, predicate = nil)
67
72
  raise UnknownHandlerVerb.new(verb, self.class.name) unless provides? verb
68
73
  raise InvalidSign if sign_required? && !sign_valid?
69
74
  do_before
70
- # process compound predicates
71
- args = predicate ? predicate.split(',') : nil
72
- send verb, *args
75
+ begin
76
+ send verb, *(predicate&.split(','))
77
+ rescue => err
78
+ if rescue_hook
79
+ send(rescue_hook[:logger], err) if rescue_hook.include? :logger
80
+ send(rescue_hook[:http_error], rescue_hook[:error_code])
81
+ else
82
+ raise
83
+ end
84
+ end
73
85
  do_after
74
86
  end
75
87
 
@@ -15,7 +15,7 @@ module Tzispa
15
15
  @error && @error != HANDLER_OK
16
16
  end
17
17
 
18
- def message
18
+ def error_message
19
19
  I18n.t(error_id, default: error.to_s) if error
20
20
  end
21
21
 
@@ -23,52 +23,52 @@ module Tzispa
23
23
  "#{self.class.name.dottize}.#{error}" if error
24
24
  end
25
25
 
26
- def http_bad_request(error = nil)
27
- error_status error || :bad_requuest, 400
26
+ def http_bad_request(code = nil)
27
+ error_status code || :bad_request, 400
28
28
  end
29
29
 
30
- def http_unauthorized(error = nil)
31
- error_status error || :unauthorized, 401
30
+ def http_unauthorized(code = nil)
31
+ error_status code || :unauthorized, 401
32
32
  end
33
33
 
34
- def http_forbidden(error = nil)
35
- error_status error || :forbidden, 403
34
+ def http_forbidden(code = nil)
35
+ error_status code || :forbidden, 403
36
36
  end
37
37
 
38
- def http_not_found(error = nil)
39
- error_status error || :not_found, 404
38
+ def http_not_found(code = nil)
39
+ error_status code || :not_found, 404
40
40
  end
41
41
 
42
- def http_not_aceptable(error = nil)
43
- error_status error || :not_acceptable, 406
42
+ def http_not_aceptable(code = nil)
43
+ error_status code || :not_acceptable, 406
44
44
  end
45
45
 
46
- def http_conflict(error = nil)
47
- error_status error || :conflict, 409
46
+ def http_conflict(code = nil)
47
+ error_status code || :conflict, 409
48
48
  end
49
49
 
50
- def http_gone(error = nil)
51
- error_status error || :gone, 410
50
+ def http_gone(code = nil)
51
+ error_status code || :gone, 410
52
52
  end
53
53
 
54
- def http_token_required(error = nil)
55
- error_status error || :token_required, 499
54
+ def http_token_required(code = nil)
55
+ error_status code || :token_required, 499
56
56
  end
57
57
 
58
- def http_server_error(error = nil)
59
- error_status error || :internal_server_error, 500
58
+ def http_server_error(code = nil)
59
+ error_status code || :internal_server_error, 500
60
60
  end
61
61
 
62
- def http_not_implemented(error = nil)
63
- error_status error || :not_implemented, 501
62
+ def http_not_implemented(code = nil)
63
+ error_status code || :not_implemented, 501
64
64
  end
65
65
 
66
- def http_bad_gateway(error = nil)
67
- error_status error || :bad_gateway, 502
66
+ def http_bad_gateway(code = nil)
67
+ error_status code || :bad_gateway, 502
68
68
  end
69
69
 
70
- def http_service_unavailable(error = nil)
71
- error_status error || :service_unavailable, 503
70
+ def http_service_unavailable(code = nil)
71
+ error_status code || :service_unavailable, 503
72
72
  end
73
73
 
74
74
  end
data/lib/tzispa/app.rb CHANGED
@@ -4,9 +4,9 @@ require 'forwardable'
4
4
  require 'logger'
5
5
  require 'i18n'
6
6
  require 'tzispa/domain'
7
- require 'tzispa/route_set'
8
7
  require 'tzispa/config/app_config'
9
8
  require 'tzispa/config/db_config'
9
+ require 'tzispa/engine'
10
10
  require 'tzispa_data'
11
11
 
12
12
  module Tzispa
@@ -14,10 +14,10 @@ module Tzispa
14
14
  class Application
15
15
  extend Forwardable
16
16
 
17
- attr_reader :domain, :logger, :map_path
17
+ include Tzispa::Engine
18
18
 
19
+ attr_reader :domain, :logger, :map_path, :engine, :routes
19
20
  def_delegators :@domain, :name, :path
20
- def_delegators :@routes, :routing, :index, :api, :signed_api, :layout
21
21
 
22
22
  class << self
23
23
  alias __new__ :new
@@ -49,9 +49,10 @@ module Tzispa
49
49
  end
50
50
  end
51
51
 
52
- def initialize(appid, on: nil, &block)
52
+ def initialize(appid, engine:, on: nil, &block)
53
53
  @domain = Domain.new(appid)
54
54
  @map_path = on
55
+ @engine = engine
55
56
  instance_eval(&block) if block
56
57
  end
57
58
 
@@ -62,11 +63,11 @@ module Tzispa
62
63
  def load!
63
64
  tap do |app|
64
65
  app.class.synchronize do
65
- logging
66
- load_locales
66
+ logging_setup
67
+ locales_setup
67
68
  repository&.load!(domain)
68
69
  domain.setup
69
- routes.setup
70
+ routes_setup
70
71
  end
71
72
  end
72
73
  end
@@ -75,18 +76,10 @@ module Tzispa
75
76
  self.class[domain]
76
77
  end
77
78
 
78
- def default_layout?(layout)
79
- config.default_layout.to_sym == layout
80
- end
81
-
82
79
  def env
83
80
  Tzispa::Environment.instance
84
81
  end
85
82
 
86
- def routes
87
- @routes ||= RouteSet.new(self, map_path)
88
- end
89
-
90
83
  def config
91
84
  @config ||= Config::AppConfig.new(@domain).load!
92
85
  end
@@ -100,13 +93,17 @@ module Tzispa
100
93
 
101
94
  private
102
95
 
103
- def logging
96
+ def routes_setup
97
+ @routes = send :"#{engine}_routes", self, map_path
98
+ end
99
+
100
+ def logging_setup
104
101
  return unless config&.logging&.enabled
105
102
  @logger = Logger.new("logs/#{domain.name}.log", config.logging&.shift_age)
106
103
  @logger.level = Tzispa::Environment.development? ? Logger::DEBUG : Logger::INFO
107
104
  end
108
105
 
109
- def load_locales
106
+ def locales_setup
110
107
  return unless config.respond_to?(:locales)
111
108
  I18n.enforce_available_locales = false
112
109
  I18n.load_path += Dir['config/locales/*.yml', "#{domain.path}/locales/*.yml"]
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
- require 'tzispa/controller/api'
4
+ require 'tzispa/engine/rig/api'
5
5
  require 'tzispa/commands/command'
6
6
  require 'tzispa/utils/indenter'
7
7
 
@@ -19,10 +19,10 @@ module Tzispa
19
19
  end
20
20
 
21
21
  def generate
22
- file_name = Tzispa::Controller::Api.handler_class_file(domain, name, verb)
22
+ file_name = Tzispa::Engine::Rig::Api.handler_class_file(domain, name, verb)
23
23
  raise "The handler '#{name}' already exist" if File.exist?(file_name)
24
- namespace = Tzispa::Controller::Api.handler_namespace(domain, verb)
25
- class_name = Tzispa::Controller::Api.handler_class_name(name)
24
+ namespace = Tzispa::Engine::Rig::Api.handler_namespace(domain, verb)
25
+ class_name = Tzispa::Engine::Rig::Api.handler_class_name(name)
26
26
  create_file file_name, namespace, class_name
27
27
  end
28
28
 
@@ -1,87 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'tzispa/helpers/error_view'
5
3
  require 'tzispa/helpers/hooks/before'
6
4
  require 'tzispa/helpers/hooks/after'
7
- require 'tzispa/http/context'
8
5
  require 'tzispa/environment'
6
+ require 'tzispa/context'
9
7
 
10
8
  module Tzispa
11
9
  module Controller
12
10
 
13
11
  class Base
14
- extend Forwardable
15
12
 
16
- include Tzispa::Helpers::ErrorView
17
13
  include Tzispa::Helpers::Hooks::Before
18
14
  include Tzispa::Helpers::Hooks::After
19
15
 
20
- attr_reader :context, :application, :callmethod, :custom_error
21
- def_delegators :@context, :request, :response, :config,
22
- :login_redirect, :unauthorized_but_logged
16
+ attr_reader :application, :context, :context_class, :callmethod
23
17
 
24
- def initialize(app, callmethod = nil, custom_error = true)
25
- @callmethod = callmethod
18
+ def initialize(app, callmethod, context_class = Tzispa::Context)
26
19
  @application = app
27
- @custom_error = custom_error
20
+ @callmethod = callmethod
21
+ @context_class = context_class
28
22
  end
29
23
 
30
24
  def call(env)
31
- @context = Tzispa::Http::Context.new(@application, env)
32
- invoke if callmethod
33
- response.finish
25
+ @context = context_class.new(application, env)
26
+ invoke
34
27
  end
35
28
 
36
29
  private
37
30
 
38
31
  def invoke
39
- prepare_response catch(:halt) {
32
+ catch(:halt) {
40
33
  do_before
41
34
  send callmethod
42
35
  do_after
43
36
  }
44
- rescue Tzispa::Rig::NotFound => ex
45
- prepare_response(404, error: ex)
46
- rescue StandardError, ScriptError, SecurityError => ex
47
- prepare_response(500, error: ex)
48
37
  end
49
38
 
50
- def prepare_response(status, error: nil)
51
- response.status = status if status.is_a?(Integer)
52
- if context.client_error?
53
- prepare_client_error(status, error)
54
- elsif context.server_error?
55
- prepare_server_error(status, error)
56
- end
57
- end
58
-
59
- def prepare_client_error(status, error = nil)
60
- status.tap do |code|
61
- context.logger.info log_format(code, error.to_s) if error
62
- response.body = error_page(context.domain, status: code) if custom_error
63
- end
64
- end
65
-
66
- def prepare_server_error(status, error = nil)
67
- status.tap do |code|
68
- context.logger.error log_format(code, error_log(error)) if error
69
- if custom_error
70
- response.body = if error && Tzispa::Environment.development?
71
- debug_info(error)
72
- else
73
- error_page(context.domain, status: code)
74
- end
75
- end
76
- end
77
- end
78
-
79
- def log_format(status, msg)
80
- String.new.tap do |str|
81
- str << "[#{context.request.ip} #{DateTime.now}] #{context.request.request_method}"
82
- str << " #{context.request.fullpath} #{status}\n#{msg}"
83
- end
84
- end
85
39
  end
86
40
 
87
41
  end
@@ -0,0 +1,67 @@
1
+ require 'forwardable'
2
+ require 'tzispa/helpers/error_view'
3
+ require 'tzispa/controller/base'
4
+ require 'tzispa/http/context'
5
+
6
+ module Tzispa
7
+ module Controller
8
+
9
+ class Http < Tzispa::Controller::Base
10
+ extend Forwardable
11
+
12
+ include Tzispa::Helpers::ErrorView
13
+
14
+ attr_reader :custom_errors
15
+ def_delegators :@context, :request, :response, :config
16
+
17
+ def initialize(app, callmethod, context_class = Tzispa::Http::Context, custom_errors = true)
18
+ super app, callmethod, context_class
19
+ @custom_errors = custom_errors
20
+ end
21
+
22
+ def call(env)
23
+ super
24
+ response.finish
25
+ end
26
+
27
+ private
28
+
29
+ def invoke
30
+ prepare_response super
31
+ rescue StandardError, ScriptError, SecurityError => ex
32
+ prepare_response(500, error: ex)
33
+ end
34
+
35
+ def prepare_response(status, error: nil)
36
+ response.status = status if status.is_a?(Integer)
37
+ if context.client_error?
38
+ prepare_client_error(status, error)
39
+ elsif context.server_error?
40
+ prepare_server_error(status, error)
41
+ end
42
+ end
43
+
44
+ def prepare_client_error(status, error = nil)
45
+ status.tap do |code|
46
+ context.info_log(error, code) if error
47
+ response.body = error_page(context.domain, status: code) if custom_errors
48
+ end
49
+ end
50
+
51
+ def prepare_server_error(status, error = nil)
52
+ status.tap do |code|
53
+ context.error_log(error, code) if error
54
+ if custom_errors
55
+ response.body = if error && Tzispa::Environment.development?
56
+ debug_info(error)
57
+ else
58
+ error_page(context.domain, status: code)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'tzispa/domain'
5
+ require 'tzispa/controller/http'
6
+ require 'tzispa/controller/exceptions'
7
+ require 'tzispa/helpers/response'
8
+ require 'tzispa/utils/string'
9
+ require 'tzispa/engine/rig/context'
10
+
11
+ module Tzispa
12
+ module Engine
13
+ module Rig
14
+
15
+ class ControllerException < StandardError; end
16
+
17
+ class Api < Tzispa::Controller::Http
18
+ using Tzispa::Utils::TzString
19
+
20
+ include Tzispa::Helpers::Response
21
+
22
+ def initialize(app)
23
+ super app, :dispatch!, Tzispa::Engine::Rig::Context, false
24
+ end
25
+
26
+ def dispatch!
27
+ verb = context.router_params[:verb]
28
+ predicate = context.router_params[:predicate]
29
+ handler = prepare_handler
30
+ handler.run! verb, predicate
31
+ send(handler.type || :empty, handler)
32
+ end
33
+
34
+ def prepare_handler
35
+ self.class.handler_class(request_method, domain, handler_name).new(context)
36
+ end
37
+
38
+ def domain
39
+ _, domain_name = context.router_params[:handler].split('.').reverse
40
+ domain_name ? Tzispa::Domain.new(name: domain_name) : context.app.domain
41
+ end
42
+
43
+ def handler_name
44
+ context.router_params[:handler].split('.').last
45
+ end
46
+
47
+ def handler_redirect_url(url)
48
+ if url && !url.strip.empty?
49
+ url.start_with?('#') ? "#{request.referer}#{url}" : url
50
+ else
51
+ request.referer
52
+ end
53
+ end
54
+
55
+ def empty(handler)
56
+ api_response handler.status
57
+ end
58
+
59
+ def redirect(handler)
60
+ api_flash(handler.message) if handler.error?
61
+ context.redirect handler.redirect_url(handler.data), config.absolute_redirects, response
62
+ end
63
+
64
+ def html(handler)
65
+ content = handler.data unless handler.error?
66
+ api_response handler.status, content, :htm
67
+ end
68
+
69
+ def json(handler)
70
+ content = handler.data.is_a?(::String) ? JSON.parse(handler.data) : handler.data.to_json
71
+ api_response handler.status, content, :json
72
+ end
73
+
74
+ def text(handler)
75
+ content = handler.data unless handler.error?
76
+ api_response handler.status, content, :text
77
+ end
78
+
79
+ def download(handler)
80
+ send_file handler.data[:path], handler.data
81
+ end
82
+
83
+ def api_flash(message)
84
+ context.flash << message if config.sessions&.enabled
85
+ end
86
+
87
+ def api_response(status, content = nil, type = nil)
88
+ content_type(type) if type
89
+ response.body = content if content
90
+ response.status = status if status
91
+ end
92
+
93
+ def request_method
94
+ context.request_method.downcase
95
+ end
96
+
97
+ class << self
98
+ def handler_class_name(handler_name)
99
+ "#{handler_name.camelize}Handler"
100
+ end
101
+
102
+ def handler_class_file(domain, handler_name, request_method)
103
+ "#{domain.path}/api/#{request_method}/#{handler_name}.rb"
104
+ end
105
+
106
+ def handler_namespace(domain, request_method)
107
+ "#{domain.name.to_s.camelize}::Api::#{request_method.capitalize}"
108
+ end
109
+
110
+ def handler_class(request_method, domain, handler_name)
111
+ domain.require "api/#{request_method}/#{handler_name}"
112
+ "#{handler_namespace domain, request_method}::#{handler_class_name handler_name}"
113
+ .constantize
114
+ end
115
+ end
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/engine/rig/layout'
4
+ require 'tzispa/helpers/login'
5
+
6
+ module Tzispa
7
+ module Engine
8
+ module Rig
9
+
10
+ class AuthLayout < Tzispa::Engine::Rig::Layout
11
+ include Tzispa::Helpers::Login
12
+
13
+ before :login_redirect
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/http/context'
4
+ require 'tzispa/helpers/security'
5
+
6
+ module Tzispa
7
+ module Engine
8
+ module Rig
9
+
10
+ class Context < Tzispa::Http::Context
11
+ include Tzispa::Helpers::Security
12
+
13
+ def layout
14
+ router_params&.fetch(:layout, nil)
15
+ end
16
+
17
+ def default_layout?(layout)
18
+ config.default_layout&.to_sym == layout
19
+ end
20
+
21
+ def layout_path(layout, params = {})
22
+ is_default = default_layout? layout
23
+ params = normalize_format(params.merge(layout: layout)) unless is_default
24
+ app.routes.path layout, params
25
+ end
26
+
27
+ def app_layout_path(app_name, layout, params = {})
28
+ is_default = app[app_name].default_layout? == layout
29
+ params = normalize_format(params.merge(layout: layout)) unless is_default
30
+ app[app_name].routes.path layout, params
31
+ end
32
+
33
+ def layout_canonical_url(layout, params = {})
34
+ "#{canonical_root}#{layout_path(layout, params)}"
35
+ end
36
+
37
+ def app_layout_canonical_url(app_name, layout, params = {})
38
+ "#{canonical_root}#{app_layout_path(app_name, layout, params)}"
39
+ end
40
+
41
+ def path_sign?(sign, *args)
42
+ sign == sign_array(args, config.salt)
43
+ end
44
+
45
+ def api(handler, verb, predicate = nil, sufix = nil, app_name = nil)
46
+ if app_name
47
+ app_canonical_url app_name, :api, handler: handler, verb: verb,
48
+ predicate: predicate, sufix: sufix
49
+ else
50
+ canonical_url :api, handler: handler, verb: verb,
51
+ predicate: predicate, sufix: sufix
52
+ end
53
+ end
54
+
55
+ def sapi(handler, verb, predicate = nil, sufix = nil, app_name = nil)
56
+ if app_name
57
+ sign = sign_array [handler, verb, predicate], app[:app_name].config.salt
58
+ app_canonical_url app_name, :sapi, sign: sign, handler: handler,
59
+ verb: verb, predicate: predicate, sufix: sufix
60
+ else
61
+ sign = sign_array [handler, verb, predicate], app.config.salt
62
+ canonical_url :sapi, sign: sign, handler: handler,
63
+ verb: verb, predicate: predicate, sufix: sufix
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa_rig'
4
+ require 'tzispa/controller/http'
5
+ require 'tzispa/controller/exceptions'
6
+ require 'tzispa/helpers/response'
7
+ require 'tzispa/engine/rig/context'
8
+
9
+ module Tzispa
10
+ module Engine
11
+ module Rig
12
+
13
+ class Layout < Tzispa::Controller::Http
14
+ include Tzispa::Helpers::Response
15
+
16
+ def initialize(app)
17
+ super app, :render!, Tzispa::Engine::Rig::Context, true
18
+ end
19
+
20
+ def render!
21
+ layout_template.tap do |rig|
22
+ response.body << rig.render(context)
23
+ content_type rig.content_type
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def layout_template
30
+ Tzispa::Rig::Factory.layout name: layout_name,
31
+ domain: application.domain,
32
+ content_type: context.router_params[:format] ||
33
+ config.default_format
34
+ end
35
+
36
+ def invoke
37
+ super
38
+ rescue Tzispa::Rig::NotFound => ex
39
+ prepare_response(404, error: ex)
40
+ end
41
+
42
+ def layout_name
43
+ context.layout || config.default_layout
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/route_set'
4
+
5
+ module Tzispa
6
+ module Engine
7
+ module Rig
8
+
9
+ class Router < Tzispa::RouteSet
10
+ def initialize(app, root = nil)
11
+ super app, root, 'Tzispa::Engine::Rig'
12
+ end
13
+
14
+ def index(path, controller: nil, methods: nil)
15
+ add :index, path, controller || 'layout', methods: methods
16
+ end
17
+
18
+ def layout(layout, path, controller: nil, methods: nil)
19
+ add layout, path, controller || 'layout', methods: methods,
20
+ matching: { layout: layout.to_s }
21
+ end
22
+
23
+ def api(path, controller: nil, methods: nil)
24
+ add :api, path, controller || 'api', methods: methods
25
+ end
26
+
27
+ def signed_api(path, controller: nil, methods: nil)
28
+ add :sapi, path, controller || 'api', methods: methods
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/engine/rig/router'
4
+
5
+ module Tzispa
6
+ module Engine
7
+
8
+ def rig_routes(app, map_path)
9
+ Rig::Router.new(app, map_path).setup
10
+ end
11
+
12
+ end
13
+ end
@@ -6,7 +6,6 @@ require 'tzispa/http/response'
6
6
  require 'tzispa/http/request'
7
7
  require 'tzispa/helpers/response'
8
8
  require 'tzispa/helpers/session'
9
- require 'tzispa/helpers/security'
10
9
 
11
10
  module Tzispa
12
11
  module Http
@@ -15,7 +14,6 @@ module Tzispa
15
14
  extend Forwardable
16
15
 
17
16
  include Tzispa::Helpers::Response
18
- include Tzispa::Helpers::Security
19
17
  include Tzispa::Helpers::Session
20
18
 
21
19
  attr_reader :request, :response
@@ -41,22 +39,6 @@ module Tzispa
41
39
  env['router.params'] || {}
42
40
  end
43
41
 
44
- def layout
45
- router_params&.fetch(:layout, nil)
46
- end
47
-
48
- def login_redirect
49
- redirect(layout_path(config.login_layout.to_sym), true, response) if login_redirect?
50
- end
51
-
52
- def login_redirect?
53
- !logged? && (layout != config.login_layout)
54
- end
55
-
56
- def unauthorized_but_logged
57
- not_authorized unless logged?
58
- end
59
-
60
42
  def path(path_id, params = {})
61
43
  app.routes.path path_id, params
62
44
  end
@@ -82,50 +64,12 @@ module Tzispa
82
64
  "#{canonical_root}#{app_path(app_name, path_id, params)}"
83
65
  end
84
66
 
85
- def layout_path(layout, params = {})
86
- is_default = app.default_layout? layout
87
- params = normalize_format(params.merge(layout: layout)) unless is_default
88
- app.routes.path layout, params
89
- end
90
-
91
- def app_layout_path(app_name, layout, params = {})
92
- is_default = app[app_name].default_layout? == layout
93
- params = normalize_format(params.merge(layout: layout)) unless is_default
94
- app[app_name].routes.path layout, params
95
- end
96
-
97
- def layout_canonical_url(layout, params = {})
98
- "#{canonical_root}#{layout_path(layout, params)}"
99
- end
100
-
101
- def app_layout_canonical_url(app_name, layout, params = {})
102
- "#{canonical_root}#{app_layout_path(app_name, layout, params)}"
103
- end
104
-
105
- def api(handler, verb, predicate = nil, sufix = nil, app_name = nil)
106
- if app_name
107
- app_canonical_url app_name, :api, handler: handler, verb: verb,
108
- predicate: predicate, sufix: sufix
109
- else
110
- canonical_url :api, handler: handler, verb: verb,
111
- predicate: predicate, sufix: sufix
112
- end
113
- end
114
-
115
- def sapi(handler, verb, predicate = nil, sufix = nil, app_name = nil)
116
- if app_name
117
- sign = sign_array [handler, verb, predicate], app[:app_name].config.salt
118
- app_canonical_url app_name, :sapi, sign: sign, handler: handler,
119
- verb: verb, predicate: predicate, sufix: sufix
120
- else
121
- sign = sign_array [handler, verb, predicate], app.config.salt
122
- canonical_url :sapi, sign: sign, handler: handler,
123
- verb: verb, predicate: predicate, sufix: sufix
124
- end
67
+ def error_log(ex, status = nil)
68
+ logger.error "E [#{request.ip}] #{request.request_method} #{request.fullpath} #{status || response.status}\n#{ex.backtrace.first}: #{ex.message} (#{ex.class})\n#{ex.backtrace.drop(1).map { |s| "\t#{s}" }.join("\n") }"
125
69
  end
126
70
 
127
- def path_sign?(sign, *args)
128
- sign == sign_array(args, config.salt)
71
+ def info_log(ex, status = nil)
72
+ logger.info "I [#{request.ip}] #{request.request_method} #{request.fullpath} #{status || response.status}\n#{ex.backtrace.first}: #{ex.message} (#{ex.class})\n#{ex.backtrace.drop(1).map { |s| "\t#{s}" }.join("\n") }"
129
73
  end
130
74
 
131
75
  private
@@ -14,11 +14,12 @@ module Tzispa
14
14
 
15
15
  attr_reader :router, :map_path, :app
16
16
 
17
- def initialize(app, root = nil)
17
+ def initialize(app, root = nil, ctl_module = nil)
18
18
  @router = HttpRouter.new
19
19
  @app = app
20
20
  @router.default Controller::HttpError.new(app, :error_404)
21
21
  @map_path = root unless root == '/'
22
+ @ctl_module = ctl_module || CONTROLLERS_BASE
22
23
  end
23
24
 
24
25
  def setup
@@ -26,6 +27,7 @@ module Tzispa
26
27
  contents = File.read(routes_definitions)
27
28
  instance_eval(contents, File.basename(routes_definitions), 0)
28
29
  end
30
+ self
29
31
  end
30
32
 
31
33
  def routes_definitions
@@ -50,25 +52,10 @@ module Tzispa
50
52
  yield if block_given?
51
53
  end
52
54
 
53
- def index(path, controller: nil, methods: nil)
54
- add :index, path, controller || 'layout:render!', methods: methods
55
- end
56
-
57
- def api(path, controller: nil, methods: nil)
58
- add :api, path, controller || 'api:dispatch!', methods: methods
59
- end
60
-
61
- def signed_api(path, controller: nil, methods: nil)
62
- add :sapi, path, controller || 'api:dispatch!', methods: methods
63
- end
64
-
65
- def layout(layout, path, controller: nil, methods: nil)
66
- add layout, path, controller || 'layout:render!', methods: methods,
67
- matching: { layout: layout.to_s }
68
- end
69
-
70
55
  private
71
56
 
57
+ attr_reader :ctl_module
58
+
72
59
  def add_route(route_id, path, to:, methods: nil, matching: nil)
73
60
  @router.add(path).tap do |rule|
74
61
  rule.name = route_id
@@ -81,19 +68,23 @@ module Tzispa
81
68
  def build_controller(controller)
82
69
  spec_control, callmethod = controller.to_s.split(':')
83
70
  mpath = spec_control.split('#')
84
- controller_class(mpath).new(app, callmethod)
71
+ if callmethod
72
+ controller_class(mpath).new(app, callmethod)
73
+ else
74
+ controller_class(mpath).new(app)
75
+ end
85
76
  end
86
77
 
87
78
  def controller_class(mpath)
88
79
  req_controller = mpath.pop
89
- cmodule = if mpath.count > 1
90
- require "#{app.path}/controller/#{req_controller}"
91
- mpath.collect!(&:capitalize).join('::')
92
- else
93
- require "tzispa/controller/#{req_controller}"
94
- CONTROLLERS_BASE
95
- end
96
- "#{cmodule}::#{req_controller.camelize}".constantize
80
+ cf_module = if mpath.count > 1
81
+ require "#{app.path}/controller/#{req_controller}"
82
+ mpath.collect!(&:capitalize).join('::')
83
+ else
84
+ require "#{ctl_module.underscore}/#{req_controller}"
85
+ ctl_module
86
+ end
87
+ "#{cf_module}::#{req_controller.camelize}".constantize
97
88
  end
98
89
  end
99
90
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tzispa
4
- VERSION = '0.7.6'
4
+ VERSION = '0.8.0'
5
5
  FRAMEWORK_NAME = 'Tzispa'
6
6
  GEM_NAME = 'tzispa'
7
7
  end
data/tzispa.gemspec CHANGED
@@ -15,22 +15,22 @@ Gem::Specification.new do |s|
15
15
  s.description = 'A sparkling web framework Rack based'
16
16
  s.licenses = ['MIT']
17
17
 
18
- s.required_ruby_version = '~> 2.3'
18
+ s.required_ruby_version = '~> 2.4'
19
19
 
20
20
  s.add_dependency 'bundler', '~> 1.14'
21
- s.add_dependency 'rack', '~> 2.0', '>= 2.0.1'
21
+ s.add_dependency 'rack', '~> 2.0', '>= 2.0.1'
22
22
  s.add_dependency 'i18n', '~> 0.8.0'
23
23
  s.add_dependency 'thor', '~> 0.19.0'
24
24
  s.add_dependency 'http_router', '~> 0.11.2'
25
- s.add_dependency 'tzispa_helpers', '~> 0.3'
25
+ s.add_dependency 'tzispa_helpers', '~> 0.3.4'
26
26
  s.add_dependency 'tzispa_utils', '~> 0.3'
27
- s.add_dependency 'tzispa_rig', '~> 0.5'
27
+ s.add_dependency 'tzispa_rig', '~> 0.5.8'
28
28
  s.add_dependency 'tzispa_data', '~> 0.4'
29
29
  s.add_dependency 'dotenv', '~> 2.2'
30
30
 
31
31
  s.add_development_dependency 'shotgun', '~> 0.9'
32
32
 
33
- s.files = Dir.glob('{lib,bin}/**/*') + %w(README.md CHANGELOG.md LICENSE tzispa.gemspec)
33
+ s.files = Dir.glob('{lib,bin}/**/*') + %w[README.md CHANGELOG.md LICENSE tzispa.gemspec]
34
34
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
35
35
  s.require_paths = ['lib']
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tzispa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.6
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Antonio Piñero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-17 00:00:00.000000000 Z
11
+ date: 2017-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '0.3'
95
+ version: 0.3.4
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '0.3'
102
+ version: 0.3.4
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: tzispa_utils
105
105
  requirement: !ruby/object:Gem::Requirement
@@ -120,14 +120,14 @@ dependencies:
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0.5'
123
+ version: 0.5.8
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.5'
130
+ version: 0.5.8
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: tzispa_data
133
133
  requirement: !ruby/object:Gem::Requirement
@@ -205,13 +205,17 @@ files:
205
205
  - lib/tzispa/config/db_config.rb
206
206
  - lib/tzispa/config/yaml.rb
207
207
  - lib/tzispa/context.rb
208
- - lib/tzispa/controller/api.rb
209
- - lib/tzispa/controller/auth_layout.rb
210
208
  - lib/tzispa/controller/base.rb
211
209
  - lib/tzispa/controller/exceptions.rb
210
+ - lib/tzispa/controller/http.rb
212
211
  - lib/tzispa/controller/http_error.rb
213
- - lib/tzispa/controller/layout.rb
214
212
  - lib/tzispa/domain.rb
213
+ - lib/tzispa/engine.rb
214
+ - lib/tzispa/engine/rig/api.rb
215
+ - lib/tzispa/engine/rig/auth_layout.rb
216
+ - lib/tzispa/engine/rig/context.rb
217
+ - lib/tzispa/engine/rig/layout.rb
218
+ - lib/tzispa/engine/rig/router.rb
215
219
  - lib/tzispa/env.rb
216
220
  - lib/tzispa/environment.rb
217
221
  - lib/tzispa/http/context.rb
@@ -234,7 +238,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
234
238
  requirements:
235
239
  - - "~>"
236
240
  - !ruby/object:Gem::Version
237
- version: '2.3'
241
+ version: '2.4'
238
242
  required_rubygems_version: !ruby/object:Gem::Requirement
239
243
  requirements:
240
244
  - - ">="
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
- require 'tzispa/domain'
5
- require 'tzispa/controller/base'
6
- require 'tzispa/controller/exceptions'
7
- require 'tzispa/helpers/response'
8
- require 'tzispa/utils/string'
9
-
10
- module Tzispa
11
- module Controller
12
-
13
- class ControllerException < StandardError; end
14
-
15
- class Api < Base
16
- using Tzispa::Utils::TzString
17
-
18
- include Tzispa::Helpers::Response
19
-
20
- def initialize(app, callmethod = :dispatch!)
21
- super(app, callmethod, false)
22
- end
23
-
24
- def dispatch!
25
- verb = context.router_params[:verb]
26
- predicate = context.router_params[:predicate]
27
- handler = prepare_handler
28
- handler.run! verb, predicate
29
- send(handler.type || :empty, handler)
30
- end
31
-
32
- def prepare_handler
33
- self.class.handler_class(request_method, domain, handler_name).new(context)
34
- end
35
-
36
- def domain
37
- _, domain_name = context.router_params[:handler].split('.').reverse
38
- domain_name ? Tzispa::Domain.new(name: domain_name) : context.app.domain
39
- end
40
-
41
- def handler_name
42
- context.router_params[:handler].split('.').last
43
- end
44
-
45
- def handler_redirect_url(url)
46
- if url && !url.strip.empty?
47
- url.start_with?('#') ? "#{request.referer}#{url}" : url
48
- else
49
- request.referer
50
- end
51
- end
52
-
53
- def empty(handler)
54
- api_response handler.status
55
- end
56
-
57
- def redirect(handler)
58
- api_flash(handler.message) if handler.error?
59
- context.redirect handler.redirect_url(handler.data), config.absolute_redirects, response
60
- end
61
-
62
- def html(handler)
63
- content = handler.data unless handler.error?
64
- api_response handler.status, content, :htm
65
- end
66
-
67
- def json(handler)
68
- content = handler.data.is_a?(::String) ? JSON.parse(handler.data) : handler.data.to_json
69
- api_response handler.status, content, :json
70
- end
71
-
72
- def text(handler)
73
- content = handler.data unless handler.error?
74
- api_response handler.status, content, :text
75
- end
76
-
77
- def download(handler)
78
- send_file handler.data[:path], handler.data
79
- end
80
-
81
- def api_flash(message)
82
- context.flash << message if config.sessions&.enabled
83
- end
84
-
85
- def api_response(status, content = nil, type = nil)
86
- content_type(type) if type
87
- response.body = content if content
88
- response.status = status if status
89
- end
90
-
91
- def request_method
92
- context.request_method.downcase
93
- end
94
-
95
- class << self
96
- def handler_class_name(handler_name)
97
- "#{handler_name.camelize}Handler"
98
- end
99
-
100
- def handler_class_file(domain, handler_name, request_method)
101
- "#{domain.path}/api/#{request_method}/#{handler_name}.rb"
102
- end
103
-
104
- def handler_namespace(domain, request_method)
105
- "#{domain.name.to_s.camelize}::Api::#{request_method.capitalize}"
106
- end
107
-
108
- def handler_class(request_method, domain, handler_name)
109
- domain.require "api/#{request_method}/#{handler_name}"
110
- "#{handler_namespace domain, request_method}::#{handler_class_name handler_name}"
111
- .constantize
112
- end
113
- end
114
- end
115
-
116
- end
117
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tzispa/controller/layout'
4
-
5
- module Tzispa
6
- module Controller
7
-
8
- class AuthLayout < Layout
9
- before :login_redirect
10
- end
11
-
12
- end
13
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tzispa_rig'
4
- require 'tzispa/controller/base'
5
- require 'tzispa/controller/exceptions'
6
- require 'tzispa/helpers/response'
7
-
8
- module Tzispa
9
- module Controller
10
- class Layout < Base
11
- include Tzispa::Helpers::Response
12
-
13
- def render!
14
- rig = Tzispa::Rig::Engine.layout name: layout_name,
15
- domain: application.domain,
16
- content_type: context.router_params[:format] || config.default_format
17
- response.body << rig.render(context)
18
- content_type rig.content_type
19
- end
20
-
21
- private
22
-
23
- def layout_name
24
- context.layout || config.default_layout
25
- end
26
- end
27
-
28
- end
29
- end