tzispa 0.5.10 → 0.5.11

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: 73281443ab56c5d37e05bccc7896d3af2acb3415
4
- data.tar.gz: '03076458d15ac0598119430311808949ad0c57e7'
3
+ metadata.gz: 9e70cadefd940ba6c29f9e922288ae5d6e26f806
4
+ data.tar.gz: 9d0803b6898b4f23d8117ee20c5854e13bca99ab
5
5
  SHA512:
6
- metadata.gz: 1ce98d4842005c2af213bd7a560c7b70cc4e8213f9ebc08a7c8909e77cc74817f936bff2eeccf637bce136c6afcde18f8640317788175f9042a0f57c7b94144e
7
- data.tar.gz: '079524201c5c1d25dc23ba1de6258eba590a4cd773a968674e07e98224cf2156dac28d3f52a69d756c17565e41910c7a97afe86694a8e68f9d5730e0558e8323'
6
+ metadata.gz: 83d6b14372cd570718a36f4a68f7480591923033c91046ece2d3c27742c9686872b69457e9534127385ba3ee0f23690cdcc614578be2dedf63c68bc1c851da17
7
+ data.tar.gz: e7ae49e10763e8bdcf4655a15c3ca68dad2651fba71b0e9d96245820a69b75b2cdcb92c9608202d8aea7dd17ea1ae562637f33889e20d1ba3e27a45260dffcee
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@ Tzispa
2
2
 
3
3
  General purpose web framework
4
4
 
5
+ ## v0.5.11
6
+ - moved app config files location
7
+ - moved app locales base dir
8
+ - api sign checking has been moved to handlers by helpers dsl
9
+ - api dispatch code improvement and fixes
10
+ - code reorganization to expose better interfaces
11
+
5
12
  ## v0.5.10
6
13
  - fix: check if the given layout is the default_layout in config before promote into the path params hash
7
14
  - add tmp folder in the project creation cli command
@@ -18,7 +25,7 @@ General purpose web framework
18
25
  - add path building methods for rig layouts in lib/tzispa/http/context.rb
19
26
 
20
27
  ## v0.5.7
21
- - add provides DSL method to specify allowe verbs in api handlers
28
+ - add provides DSL method to specify allowed verbs in api handlers
22
29
  - handler calling improvements in api the controller
23
30
 
24
31
  ## v0.5.6
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'forwardable'
4
4
  require 'json'
5
+ require 'tzispa/helpers/provider'
6
+ require 'tzispa/helpers/sign_requirer'
5
7
 
6
8
  module Tzispa
7
9
  module Api
@@ -12,13 +14,15 @@ module Tzispa
12
14
  super("Unknown verb: '#{s}' called in api handler '#{name}'")
13
15
  end
14
16
  end
17
+ class InvalidSign < ApiException; end
15
18
 
16
19
  class Handler
20
+ include Tzispa::Helpers::Provider
21
+ include Tzispa::Helpers::SignRequirer
17
22
  extend Forwardable
18
23
 
19
- def_delegators :@context, :request, :response, :app
20
-
21
- attr_reader :context, :status, :response_verb, :data
24
+ attr_reader :context, :response_verb, :data, :status
25
+ def_delegators :@context, :request, :response, :app, :repository, :config
22
26
 
23
27
  HANDLED_UNDEFINED = nil
24
28
  HANDLED_OK = 1
@@ -36,54 +40,53 @@ module Tzispa
36
40
  @context = context
37
41
  end
38
42
 
39
- def result(response_verb:, status: HANDLED_UNDEFINED, data: nil, detailed_error: nil)
40
- @status = status
43
+ def result(response_verb:, data: nil, status: nil, error: nil)
44
+ @status = status if status
41
45
  @response_verb = response_verb
42
46
  @data = data
43
- @detailed_error = detailed_error
47
+ @error = error
48
+ end
49
+
50
+ def result_json(data, status: nil)
51
+ result response_verb: :json, data: data.to_json, status: status
44
52
  end
45
53
 
46
- def result_json(status=HANDLED_UNDEFINED, data=nil, detailed_error=nil)
47
- result response_verb: :json, status: status, data: data.to_json, detailed_error: detailed_error
54
+ def result_download(data, status: nil)
55
+ result response_verb: :download, data: data, status: status
56
+ end
57
+
58
+ def not_found
59
+ result response_verb: :not_found
48
60
  end
49
61
 
50
62
  def message
51
- if @status.nil?
52
- nil
53
- elsif @status >= HANDLED_OK && @status <= HANDLED_ERROR
54
- HANDLED_MESSAGES[@status]
55
- elsif @status > HANDLED_ERROR && @status < HANDLED_RESULT
56
- error_message @status
57
- elsif @status > HANDLED_RESULT
58
- result_messages @status
59
- else
60
- nil
63
+ case ss = status.to_i
64
+ when ss >= HANDLED_OK && ss <= HANDLED_ERROR
65
+ HANDLED_MESSAGES[status]
66
+ when ss > HANDLED_ERROR && ss < HANDLED_RESULT
67
+ error_message status
68
+ when ss > HANDLED_RESULT
69
+ result_messages status
61
70
  end
62
71
  end
63
72
 
64
73
  def call(verb, predicate=nil)
65
- raise UnknownHandlerVerb.new(verb, self.class.name) unless self.class.provides? verb
66
- # allow compound predicates
74
+ raise UnknownHandlerVerb.new(verb, self.class.name) unless provides? verb
75
+ raise InvalidSign.new if sign_required? && !sign_valid?
76
+ # process compound predicates
67
77
  args = predicate ? predicate.split(',') : nil
68
78
  send verb, *args
69
79
  end
70
80
 
71
- def self.provides(*args)
72
- (@provides ||= Hash.new).tap { |prv|
73
- args&.each { |s|
74
- prv[s.to_sym] = s
75
- }
76
- }
81
+ def set_status(value)
82
+ @status = value
77
83
  end
78
84
 
79
- def self.provides?(verb)
80
- value = verb.to_sym
81
- @provides&.include?(value) && public_method_defined?(@provides[value])
82
- end
83
85
 
84
- def self.mapping(source, dest)
85
- @provides ||= Hash.new
86
- @provides[source] = dest
86
+ protected
87
+
88
+ def static_path_sign?
89
+ context.path_sign? context.router_params[:sign], context.router_params[:handler], context.router_params[:verb], context.router_params[:predicate]
87
90
  end
88
91
 
89
92
  private
@@ -93,7 +96,7 @@ module Tzispa
93
96
  end
94
97
 
95
98
  def error_message(status)
96
- "#{self.class::ERROR_MESSAGES[status]}#{': '+@detailed_error if @detailed_error}" if (defined?( self.class::ERROR_MESSAGES ) && self.class::ERROR_MESSAGES.is_a?(Hash))
99
+ "#{self.class::ERROR_MESSAGES[status]}#{': '+@error.to_s if @error}" if (defined?( self.class::ERROR_MESSAGES ) && self.class::ERROR_MESSAGES.is_a?(Hash))
97
100
  end
98
101
 
99
102
 
data/lib/tzispa/app.rb CHANGED
@@ -77,16 +77,14 @@ module Tzispa
77
77
  end
78
78
 
79
79
  def load!
80
- Mutex.new.synchronize {
80
+ self.class.synchronize {
81
81
  load_locales
82
- @repository = Data::Repository.new(@config.repository.to_h).load! if @config.respond_to? :repository
83
- @engine = Rig::Engine.new(self, @config.template_cache.enabled, @config.template_cache.size)
84
- @logger = Logger.new("logs/#{@domain.name}.log", 'weekly')
85
- @logger.level = @config.respond_to?(:developing) && @config.developing ? Logger::DEBUG : Logger::INFO
86
- @domain.require_dir 'helpers'
87
- @domain.require_dir 'services'
88
- @domain.require_dir 'api'
89
- @domain.require_dir 'middleware'
82
+ @repository = Data::Repository.new(config.repository.to_h).load! if config.respond_to? :repository
83
+ @engine = Rig::Engine.new(self, config.template_cache.enabled, config.template_cache.size)
84
+ @logger = Logger.new("logs/#{domain.name}.log", config.logging.shift_age).tap { |log|
85
+ log.level = config.developing ? Logger::DEBUG : Logger::INFO
86
+ } if config.logging&.enabled
87
+ domain_requires
90
88
  @loaded = true
91
89
  }
92
90
  self
@@ -98,10 +96,17 @@ module Tzispa
98
96
 
99
97
  private
100
98
 
99
+ def domain_requires
100
+ domain.require_dir 'helpers'
101
+ domain.require_dir 'services'
102
+ domain.require_dir 'api'
103
+ domain.require_dir 'middleware'
104
+ end
105
+
101
106
  def load_locales
102
107
  if @config.respond_to?(:locales)
103
108
  I18n.load_path = Dir["config/locales/*.yml"]
104
- I18n.load_path += Dir["#{@domain.path}/config/locales/*.yml"]
109
+ I18n.load_path += Dir["#{@domain.path}/locales/*.yml"]
105
110
  end
106
111
  end
107
112
 
@@ -13,14 +13,13 @@ module Tzispa
13
13
 
14
14
  attr_reader :domain, :cfname
15
15
 
16
- def initialize(domain, configname=nil)
16
+ def initialize(domain)
17
17
  @domain = domain
18
- @cfname = configname || CONFIG_FILENAME
19
18
  @cftime = nil
20
19
  end
21
20
 
22
21
  def filename
23
- @filename ||= "#{domain.path}/config/#{cfname}.yml".freeze
22
+ @filename ||= "config/#{domain.name}.yml"
24
23
  end
25
24
 
26
25
  def load!
@@ -45,6 +44,7 @@ module Tzispa
45
44
  cfg['default_encoding'] = 'utf-8'
46
45
  cfg['auth_required'] = false
47
46
  cfg['salt'] = secret(24)
47
+ cfg['secret'] = secret(36)
48
48
  cfg['locales'] = Hash.new.tap { |loc|
49
49
  loc['preload'] = true
50
50
  loc['default'] = locale
@@ -17,13 +17,10 @@ module Tzispa
17
17
 
18
18
  include Tzispa::Helpers::Response
19
19
 
20
- attr_reader :handler
21
20
 
22
21
  def self.generate_handler(domain, name)
23
- @domain = domain
24
- @handler_name = name
25
22
  raise "The handler '#{name}' already exist" if File.exist?(handler_class_file)
26
- File.open(handler_class_file, "w") { |f|
23
+ File.open(handler_class_file(domain, name), "w") { |f|
27
24
  handler_code = TzString.new
28
25
  f.puts handler_code.indenter("require 'tzispa/api/handler'\n\n")
29
26
  level = 0
@@ -39,81 +36,76 @@ module Tzispa
39
36
  }
40
37
  end
41
38
 
42
-
43
39
  def dispatch!
44
- @handler_name, domain_name = context.router_params[:handler].split('.').reverse
45
- @domain = domain_name.nil? ? context.app.domain : Tzispa::Domain.new(name: domain_name)
46
- @verb = context.router_params[:verb]
47
- @predicate = context.router_params[:predicate]
48
- @handler = handler_class.new(context)
49
- handler.call @verb, @predicate
50
- context.flash << handler.message
51
- send handler.response_verb if handler.response_verb
40
+ handler_name, domain_name = context.router_params[:handler].split('.').reverse
41
+ domain = domain_name.nil? ? context.app.domain : Tzispa::Domain.new(name: domain_name)
42
+ verb = context.router_params[:verb]
43
+ predicate = context.router_params[:predicate]
44
+ handler = self.class.handler_class(domain, handler_name).new(context)
45
+ handler.call verb, predicate
46
+ send(handler.response_verb, handler) if handler.response_verb
52
47
  response.finish
53
48
  end
54
49
 
55
- def redirect
56
- url = if handler.data && !handler.data.strip.empty?
57
- handler.data.start_with?('#') ? "#{request.referer}#{handler.data}" : handler.data
50
+ def redirect(target)
51
+ url = if target.data && !target.data.strip.empty?
52
+ target.data.start_with?('#') ? "#{request.referer}#{target.data}" : target.data
58
53
  else
59
54
  request.referer
60
55
  end
56
+ context.flash << target.message if config.sessions&.enabled
61
57
  context.redirect url, config.absolute_redirects, response
62
58
  end
63
59
 
64
- def html
65
- response.body << handler.data
60
+ def html(content)
66
61
  content_type :htm
67
- set_action_headers
62
+ response.body << content.data
63
+ set_api_headers content.status
68
64
  end
69
65
 
70
- def json
71
- if handler.data.is_a?(::Hash)
72
- data = handler.data
73
- data[:__result_status] = handler.status
74
- data[:__result_message] = handler.message
75
- else
76
- data = JSON.parse(handler.data)
77
- end
78
- response.body << data.to_json
66
+ def json(content)
79
67
  content_type :json
80
- set_action_headers
68
+ data = ::Hash === content.data || ::Array === content.data ? content.data : JSON.parse(content.data)
69
+ response.body << data.to_json
70
+ set_api_headers content.status
81
71
  end
82
72
 
83
- def text
84
- response.body << handler.data
73
+ def text(content)
85
74
  content_type :text
86
- set_action_headers
75
+ response.body << content.data
76
+ set_api_headers content.status
87
77
  end
88
78
 
89
- def download
90
- send_file handler.data[:path], handler.data
79
+ def download(content)
80
+ send_file content.data[:path], content.data
91
81
  end
92
82
 
93
- def handler_class_name
94
- "#{TzString.camelize @handler_name}Handler"
95
- end
83
+ class << self
96
84
 
97
- def handler_class_file
98
- "#{@domain.path}/api/#{@handler_name}.rb"
99
- end
85
+ def handler_class_name(handler_name)
86
+ "#{TzString.camelize handler_name}Handler"
87
+ end
100
88
 
101
- def handler_namespace
102
- "#{TzString.camelize @domain.name }::Api"
103
- end
89
+ def handler_class_file(domain, handler_name)
90
+ "#{domain.path}/api/#{handler_name}.rb"
91
+ end
104
92
 
105
- def handler_class
106
- @domain.require "api/#{@handler_name}"
107
- TzString.constantize "#{handler_namespace}::#{handler_class_name}"
108
- end
93
+ def handler_namespace(domain)
94
+ "#{TzString.camelize domain.name }::Api"
95
+ end
109
96
 
97
+ def handler_class(domain, handler_name)
98
+ domain.require "api/#{handler_name}"
99
+ TzString.constantize "#{handler_namespace domain}::#{handler_class_name handler_name}"
100
+ end
110
101
 
111
- private
102
+ end
112
103
 
104
+ private
113
105
 
114
- def set_action_headers
115
- response['X-API'] = "#{context.router_params[:sign]}:#{context.router_params[:handler]}:#{context.router_params[:verb]}:#{context.router_params[:predicate]}"
116
- response['X-API-STATE'] = "#{handler.status}"
106
+ def set_api_headers(status)
107
+ response['X-API'] = "#{context.router_params[:handler]}:#{context.router_params[:verb]}:#{context.router_params[:predicate]}"
108
+ response['X-API-STATE'] = "#{status.to_i}"
117
109
  end
118
110
 
119
111
  end
@@ -5,25 +5,8 @@ require 'tzispa/helpers/security'
5
5
  module Tzispa
6
6
  module Controller
7
7
  class SignedApi < Api
8
-
9
- include Tzispa::Helpers::Security
10
-
11
-
12
- def dispatch!
13
- raise Error::InvalidSign.new unless sign?
14
- super
15
- end
16
-
17
- private
18
-
19
- def sign?
20
- context.router_params[:sign] == sign_array([
21
- context.router_params[:handler],
22
- context.router_params[:verb],
23
- context.router_params[:predicate]
24
- ],
25
- context.app.config.salt)
26
- end
8
+
9
+ # deprecated !!
27
10
 
28
11
  end
29
12
  end
@@ -125,6 +125,11 @@ module Tzispa
125
125
  end
126
126
  end
127
127
 
128
+ def path_sign?(sign, *args)
129
+ sign == sign_array(args, config.salt)
130
+ end
131
+
132
+
128
133
  end
129
134
 
130
135
  end
data/lib/tzispa/routes.rb CHANGED
@@ -55,7 +55,7 @@ module Tzispa
55
55
  end
56
56
 
57
57
  def route_rig_signed_api(path, controller: nil, methods: nil)
58
- routing :sapi, path, controller || 'signed_api:dispatch!', methods: methods
58
+ routing :sapi, path, controller || 'api:dispatch!', methods: methods
59
59
  end
60
60
 
61
61
  def route_rig_layout(layout, path, controller: nil, methods: nil)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tzispa
4
- VERSION = '0.5.10'
4
+ VERSION = '0.5.11'
5
5
  FRAMEWORK_NAME = 'Tzispa'
6
6
  GEM_NAME = 'tzispa'
7
7
  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.5.10
4
+ version: 0.5.11
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: 2016-10-27 00:00:00.000000000 Z
11
+ date: 2016-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -174,7 +174,6 @@ files:
174
174
  - lib/tzispa/controller/http_error.rb
175
175
  - lib/tzispa/controller/layout.rb
176
176
  - lib/tzispa/controller/signed_api.rb
177
- - lib/tzispa/data/entity.rb
178
177
  - lib/tzispa/domain.rb
179
178
  - lib/tzispa/http/context.rb
180
179
  - lib/tzispa/http/request.rb
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'tzispa/utils/string'
4
-
5
- module Tzispa
6
- module Data
7
- module Entity
8
-
9
- def self.included(base)
10
- base.extend(ClassMethods)
11
- end
12
-
13
- def entity!
14
- @__entity || @__entity = self.class.entity_class.new(self)
15
- end
16
-
17
- module ClassMethods
18
- def entity_class
19
- class_variable_defined?(:@@__entity_class) ?
20
- class_variable_get(:@@__entity_class) :
21
- class_variable_set(:@@__entity_class, TzString.constantize("#{self}Entity") )
22
- end
23
- end
24
-
25
- #unless model_class.respond_to?(:entity_class!)
26
- # model_class.send(:define_singleton_method, :entity_class) {
27
- # class_variable_defined?(:@@__entity_class) ?
28
- # class_variable_get(:@@__entity_class) :
29
- # class_variable_set(:@@__entity_class, TzString.constantize("#{self}Entity") )
30
- # }
31
- #end
32
- #model_class.send(:define_method, :entity!) {
33
- # instance_variable_defined?(:@__entity) ?
34
- # instance_variable_get(:@__entity) :
35
- # instance_variable_set(:@__entity, self.class.entity_class!.new(self))
36
- #}
37
-
38
- end
39
- end
40
- end