tzispa 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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