ixtlan-core 0.5.0 → 0.6.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.
@@ -9,7 +9,7 @@ module Ixtlan
9
9
  # Pragma: no-cache
10
10
  # Cache-control: no-cache, must-revalidate
11
11
  def no_caching(no_store = true)
12
- if cachable_response?
12
+ if cacheable_response?
13
13
  response.headers["Date"] = timestamp
14
14
  response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
15
15
  response.headers["Pragma"] = "no-cache"
@@ -21,7 +21,7 @@ module Ixtlan
21
21
  # Expires: Fri, 01 Jan 1990 00:00:00 GMT
22
22
  # Cache-control: private, max-age=<1dayInSeconds>
23
23
  def only_browser_can_cache(no_store = false, max_age_in_seconds = 0)
24
- if cachable_response?
24
+ if cacheable_response?
25
25
  response.headers["Date"] = timestamp
26
26
  response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 UTC"
27
27
  response.headers["Cache-Control"] = "private, max-age=#{max_age_in_seconds}" + (", no-store" if no_store).to_s
@@ -32,7 +32,7 @@ module Ixtlan
32
32
  # Expires: <ServerCurrentDate + 1month>
33
33
  # Cache-control: public, max-age=<1month>
34
34
  def allow_browser_and_proxy_to_cache(no_store = false, max_age_in_seconds = 0)
35
- if cachable_response?
35
+ if cacheable_response?
36
36
  now = Time.now
37
37
  response.headers["Date"] = timestamp(now)
38
38
  response.headers["Expires"] = timestamp(now + max_age_in_seconds)
@@ -40,9 +40,9 @@ module Ixtlan
40
40
  end
41
41
  end
42
42
 
43
- def cache_headers
44
- if(respond_to?(:current_user) && current_user)
45
- mode = self.class.instance_variable_get(:@_cache_mode)
43
+ def cache_headers(mode = nil)
44
+ if respond_to?(:current_user) && send(:current_user)
45
+ mode ||= self.class.instance_variable_get(:@_cache_headers)
46
46
  case mode
47
47
  when :private
48
48
  no_caching(self.class.instance_variable_get(:@no_store))
@@ -50,6 +50,7 @@ module Ixtlan
50
50
  only_browser_can_cache(self.class.instance_variable_get(:@no_store))
51
51
  when :public
52
52
  allow_browser_and_proxy_to_cache(self.class.instance_variable_get(:@no_store))
53
+ when :off
53
54
  else
54
55
  send mode if mode
55
56
  end
@@ -60,7 +61,7 @@ module Ixtlan
60
61
  base.class_eval do
61
62
  def self.cache_headers(mode = nil, no_store = true)
62
63
  if(mode)
63
- @_cache_mode = mode.to_sym
64
+ @_cache_headers = mode.to_sym
64
65
  end
65
66
  @no_store = no_store
66
67
  end
@@ -68,7 +69,7 @@ module Ixtlan
68
69
  end
69
70
 
70
71
  private
71
- def cachable_response?
72
+ def cacheable_response?
72
73
  request.method.to_s.downcase == "get" &&
73
74
  [200, 203, 206, 300, 301].member?(response.status)
74
75
  end
@@ -6,22 +6,27 @@ module Ixtlan
6
6
  base.class_eval do
7
7
  alias :render_old :render
8
8
  def render(*args, &block)
9
- cache_headers
10
- x_frame_headers
9
+ _extra_header(*args)
11
10
  render_old(*args, &block)
12
11
  end
13
12
  alias :send_file_old :send_file
14
13
  def send_file(*args)
15
- cache_headers
16
- x_frame_headers
14
+ _extra_header(*args)
17
15
  send_file_old(*args)
18
16
  end
19
17
  alias :send_data_old :send_data
20
18
  def send_data(*args)
21
- cache_headers
22
- x_frame_headers
19
+ _extra_header(*args)
23
20
  send_file_old(*args)
24
21
  end
22
+ private
23
+ def _extra_header(*args)
24
+ opt = (args[0].is_a?(Hash) ? args[0] : args[1]) || {}
25
+ cache_headers(opt[:cache_headers])
26
+ x_frame_headers(opt[:x_frame_headers])
27
+ x_content_type_headers(opt[:x_content_type_headers])
28
+ x_xss_protection_headers(opt[:x_xss_protection_headers])
29
+ end
25
30
  end
26
31
  end
27
32
  end
@@ -1,6 +1,8 @@
1
1
  require 'ixtlan/core/extra_headers'
2
2
  require 'ixtlan/core/cache_headers'
3
3
  require 'ixtlan/core/x_frame_headers'
4
+ require 'ixtlan/core/x_content_type_headers'
5
+ require 'ixtlan/core/x_xss_protection_headers'
4
6
  require 'ixtlan/core/optimistic_active_record'
5
7
  require 'ixtlan/core/optimistic_data_mapper'
6
8
  require 'ixtlan/core/configuration_rack'
@@ -40,9 +42,8 @@ module Ixtlan
40
42
 
41
43
  config.before_configuration do |app|
42
44
  app.config.class.class_eval do
43
- attr_accessor :x_frame_headers
45
+ attr_accessor :x_frame_headers, :x_content_type_headers, :x_xss_protection_headers
44
46
  end
45
- app.config.x_frame_headers = :deny
46
47
  end
47
48
 
48
49
  config.before_initialize do |app|
@@ -55,6 +56,8 @@ module Ixtlan
55
56
  end
56
57
  ::ActionController::Base.send(:include, Ixtlan::Core::ExtraHeaders)
57
58
  ::ActionController::Base.send(:include, Ixtlan::Core::XFrameHeaders)
59
+ ::ActionController::Base.send(:include, Ixtlan::Core::XContentTypeHeaders)
60
+ ::ActionController::Base.send(:include, Ixtlan::Core::XXssProtectionHeaders)
58
61
  ::ActionController::Base.send(:include, Ixtlan::Core::CacheHeaders)
59
62
 
60
63
  app.config.middleware.use Ixtlan::Core::ConfigurationRack
@@ -0,0 +1,30 @@
1
+ module Ixtlan
2
+ module Core
3
+ module XContentTypeHeaders
4
+
5
+ protected
6
+
7
+ def x_content_type_headers(mode = nil)
8
+ case mode || self.class.instance_variable_get(:@_x_content_type_headers) || Rails.configuration.x_content_type_headers || :nosniff
9
+ when :nosniff
10
+ response.headers["X-Content-Type-Options"] = "nosniff"
11
+ when :off
12
+ else
13
+ warn "allowed values for x_content_type_headers are :nosniff, :off"
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.class_eval do
19
+ def self.x_content_type_headers(mode)
20
+ if(mode)
21
+ @_x_content_type_headers = mode.to_sym
22
+ else
23
+ @_x_content_type_headers = nil
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,22 +4,25 @@ module Ixtlan
4
4
 
5
5
  protected
6
6
 
7
- def x_frame_headers
8
- case self.class.instance_variable_get(:@_x_frame_mode) || Rails.configuration.x_frame_headers
7
+ def x_frame_headers(mode = nil)
8
+ case mode || self.class.instance_variable_get(:@_x_frame_headers) || Rails.configuration.x_frame_headers || :deny
9
9
  when :deny
10
- response.headers["X-FRAME-OPTIONS"] = "DENY"
10
+ response.headers["X-Frame-Options"] = "DENY"
11
11
  when :sameorigin
12
- response.headers["X-FRAME-OPTIONS"] = "SAMEORIGIN"
12
+ response.headers["X-Frame-Options"] = "SAMEORIGIN"
13
+ when :off
14
+ else
15
+ warn "allowed values for x_frame_headers are :deny, :sameorigin, :off"
13
16
  end
14
17
  end
15
-
18
+
16
19
  def self.included(base)
17
20
  base.class_eval do
18
21
  def self.x_frame_headers(mode)
19
22
  if(mode)
20
- @_x_frame_mode = mode.to_sym
23
+ @_x_frame_headers = mode.to_sym
21
24
  else
22
- @_x_frame_mode = nil
25
+ @_x_frame_headers = nil
23
26
  end
24
27
  end
25
28
  end
@@ -0,0 +1,32 @@
1
+ module Ixtlan
2
+ module Core
3
+ module XXssProtectionHeaders
4
+
5
+ protected
6
+
7
+ def x_xss_protection_headers(mode = nil)
8
+ case mode || self.class.instance_variable_get(:@_x_xss_protection_headers) || Rails.configuration.x_xss_protection_headers || :block
9
+ when :disabled
10
+ response.headers["X-XSS-Protection"] = "0"
11
+ when :block
12
+ response.headers["X-XSS-Protection"] = "1; mode=block"
13
+ when :off
14
+ else
15
+ warn "allowed values for x_xss_protection_headers are :nocheck, :block, :off"
16
+ end
17
+ end
18
+
19
+ def self.included(base)
20
+ base.class_eval do
21
+ def self.x_xss_protection_headers(mode)
22
+ if(mode)
23
+ @_x_xss_protection_headers = mode.to_sym
24
+ else
25
+ @_x_xss_protection_headers = nil
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ require 'controller'
2
+
3
+
4
+ class MyControllerWithUser < ControllerWithUser
5
+ cache_headers :private
6
+ end
7
+
8
+ [:render, :send_file, :send_data].each do |method|
9
+ describe "cache-headers using controller method #{method}" do
10
+ context "with simple controller" do
11
+ subject { ControllerWithUser.new(Object.new) }
12
+
13
+ it 'should use default' do
14
+ subject.send method, :inline => "asd"
15
+ subject.response.headers.should == {"X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
16
+ end
17
+ it 'should use given option' do
18
+ subject.send method, :inline => "asd", :cache_headers => :protected
19
+ subject.response.headers.delete("Date").should_not be_nil
20
+ subject.response.headers.delete("Expires").should_not be_nil
21
+ subject.response.headers.should == {"Cache-Control"=>"private, max-age=0", "X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
22
+ end
23
+ end
24
+
25
+ context "with controller with header configuration" do
26
+ subject { MyControllerWithUser.new(Object.new) }
27
+
28
+ it 'should use configuration' do
29
+ subject.send method, :inline => "asd"
30
+ subject.response.headers.delete("Date").should_not be_nil
31
+ subject.response.headers.delete("Expires").should_not be_nil
32
+ subject.response.headers.should == {"Pragma"=>"no-cache", "Cache-Control"=>"no-cache, must-revalidate, no-store", "X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
33
+ end
34
+ it 'should use given option' do
35
+ subject.send method, :inline => "asd", :cache_headers => :public
36
+ subject.response.headers.delete("Date").should_not be_nil
37
+ subject.response.headers.delete("Expires").should_not be_nil
38
+ subject.response.headers.should == {"Cache-Control"=>"public, max-age=0, no-store", "X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
39
+ end
40
+ end
41
+
42
+ context "with simple controller without user" do
43
+ subject { MyControllerWithUser.new }
44
+
45
+ it 'should use default' do
46
+ subject.send method, :inline => "asd"
47
+ subject.response.headers.should == {"X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,78 @@
1
+ require 'ixtlan/core/extra_headers'
2
+ require 'ixtlan/core/cache_headers'
3
+ require 'ixtlan/core/x_frame_headers'
4
+ require 'ixtlan/core/x_content_type_headers'
5
+ require 'ixtlan/core/x_xss_protection_headers'
6
+
7
+ class Controller
8
+
9
+ def render(*args, &block)
10
+ @render = args if args.size > 0
11
+ @render
12
+ end
13
+ def send_file(*args, &block)
14
+ @send_file = args if args.size > 0
15
+ @send_file
16
+ end
17
+ def send_data(*args, &block)
18
+ @send_data = args if args.size > 0
19
+ @send_data
20
+ end
21
+
22
+ include Ixtlan::Core::ExtraHeaders
23
+ include Ixtlan::Core::XFrameHeaders
24
+ include Ixtlan::Core::XContentTypeHeaders
25
+ include Ixtlan::Core::XXssProtectionHeaders
26
+ include Ixtlan::Core::CacheHeaders
27
+
28
+ def response
29
+ unless @response
30
+ @response = Object.new
31
+
32
+ def @response.headers
33
+ @headers ||= {}
34
+ end
35
+ def @response.status(st = nil)
36
+ @status = st if st
37
+ @status
38
+ end
39
+ end
40
+ @response
41
+ end
42
+
43
+ def request
44
+ unless @request
45
+ @request = Object.new
46
+ def @request.method(m = nil)
47
+ @method = m if m
48
+ @method
49
+ end
50
+ end
51
+ @request
52
+ end
53
+
54
+ end
55
+
56
+ class ControllerWithUser < Controller
57
+
58
+ def initialize(user = nil, status = 200, method = :get)
59
+ @user = user
60
+ request.method method
61
+ response.status status
62
+ end
63
+ def current_user
64
+ @user
65
+ end
66
+
67
+ end
68
+
69
+ class Rails
70
+
71
+ class Config
72
+ attr_accessor :x_content_type_headers, :x_frame_headers , :x_xss_protection_headers, :cache_headers
73
+ end
74
+
75
+ def self.configuration
76
+ @config ||= Config.new
77
+ end
78
+ end
@@ -0,0 +1,74 @@
1
+ require 'controller'
2
+
3
+ shared_examples 'a X-Headers' do
4
+
5
+ it 'should be able to switch off' do
6
+ subject.send method, :inline => "asd", :x_frame_headers => :off, :x_content_type_headers => :off, :x_xss_protection_headers => :off
7
+ subject.response.headers.should == {}
8
+ end
9
+
10
+ end
11
+
12
+ class MyController < Controller
13
+ x_frame_headers :sameorigin
14
+ x_content_type_headers :off
15
+ x_xss_protection_headers :disabled
16
+ end
17
+
18
+ [:render, :send_file, :send_data].each do |method|
19
+ describe "x-headers using controller method #{method}" do
20
+ context "with simple controller" do
21
+ before do
22
+ Rails.configuration.x_frame_headers = nil
23
+ Rails.configuration.x_content_type_headers = nil
24
+ Rails.configuration.x_xss_protection_headers = nil
25
+ end
26
+ subject { Controller.new }
27
+
28
+ it 'should use default' do
29
+ subject.send method, :inline => "asd"
30
+ subject.response.headers.should == {"X-Frame-Options"=>"DENY", "X-Content-Type-Options"=>"nosniff", "X-XSS-Protection"=>"1; mode=block"}
31
+ end
32
+
33
+ it_behaves_like "a X-Headers" do
34
+ let(:method) { method }
35
+ end
36
+ end
37
+
38
+ context "with controller with header configuration" do
39
+ before do
40
+ Rails.configuration.x_frame_headers = nil
41
+ Rails.configuration.x_content_type_headers = nil
42
+ Rails.configuration.x_xss_protection_headers = nil
43
+ end
44
+ subject { MyController.new }
45
+
46
+ it 'should use configuration' do
47
+ subject.send method, :inline => "asd"
48
+ subject.response.headers.should == {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"0"}
49
+ end
50
+
51
+ it_behaves_like "a X-Headers" do
52
+ let(:method) { method }
53
+ end
54
+ end
55
+
56
+ context "with simple controller with rails configuration" do
57
+ before do
58
+ Rails.configuration.x_frame_headers = :sameorigin
59
+ Rails.configuration.x_content_type_headers = :off
60
+ Rails.configuration.x_xss_protection_headers = :disabled
61
+ end
62
+ subject { Controller.new }
63
+
64
+ it 'should use configuration' do
65
+ subject.send method, :inline => "asd"
66
+ subject.response.headers.should == {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"0"}
67
+ end
68
+
69
+ it_behaves_like "a X-Headers" do
70
+ let(:method) { method }
71
+ end
72
+ end
73
+ end
74
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ixtlan-core
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.0
5
+ version: 0.6.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - mkristian
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-06 00:00:00 +05:30
13
+ date: 2011-09-05 00:00:00 +05:30
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -28,50 +28,61 @@ dependencies:
28
28
  type: :runtime
29
29
  version_requirements: *id001
30
30
  - !ruby/object:Gem::Dependency
31
- name: rails
31
+ name: ixtlan-generators
32
32
  prerelease: false
33
33
  requirement: &id002 !ruby/object:Gem::Requirement
34
34
  none: false
35
35
  requirements:
36
36
  - - "="
37
37
  - !ruby/object:Gem::Version
38
- version: 3.0.9
38
+ version: 0.1.0
39
39
  type: :development
40
40
  version_requirements: *id002
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rails
43
43
  prerelease: false
44
44
  requirement: &id003 !ruby/object:Gem::Requirement
45
45
  none: false
46
46
  requirements:
47
47
  - - "="
48
48
  - !ruby/object:Gem::Version
49
- version: 2.6.0
49
+ version: 3.0.9
50
50
  type: :development
51
51
  version_requirements: *id003
52
52
  - !ruby/object:Gem::Dependency
53
- name: cucumber
53
+ name: rspec
54
54
  prerelease: false
55
55
  requirement: &id004 !ruby/object:Gem::Requirement
56
56
  none: false
57
57
  requirements:
58
58
  - - "="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.9.4
60
+ version: 2.6.0
61
61
  type: :development
62
62
  version_requirements: *id004
63
63
  - !ruby/object:Gem::Dependency
64
- name: ruby-maven
64
+ name: cucumber
65
65
  prerelease: false
66
66
  requirement: &id005 !ruby/object:Gem::Requirement
67
67
  none: false
68
68
  requirements:
69
69
  - - "="
70
70
  - !ruby/object:Gem::Version
71
- version: 0.8.3.0.3.0.28.3
71
+ version: 0.9.4
72
72
  type: :development
73
73
  version_requirements: *id005
74
- description: base for some gems related to protect privacy and increase security along some other utils
74
+ - !ruby/object:Gem::Dependency
75
+ name: ruby-maven
76
+ prerelease: false
77
+ requirement: &id006 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - "="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.8.3.0.3.0.28.3
83
+ type: :development
84
+ version_requirements: *id006
85
+ description: cache header control, dynamic configuration, and optimistic find on model via updated_at timestamp
75
86
  email:
76
87
  - m.kristian@web.de
77
88
  executables: []
@@ -115,10 +126,15 @@ files:
115
126
  - lib/ixtlan/core/configuration_rack.rb
116
127
  - lib/ixtlan/core/optimistic_active_record.rb
117
128
  - lib/ixtlan/core/extra_headers.rb
129
+ - lib/ixtlan/core/x_content_type_headers.rb
118
130
  - lib/ixtlan/core/cache_headers.rb
131
+ - lib/ixtlan/core/x_xss_protection_headers.rb
119
132
  - lib/ixtlan/core/railtie.rb
120
133
  - lib/ixtlan/core/configuration_manager.rb
121
134
  - lib/ixtlan/core/controllers/configuration_controller.rb
135
+ - spec/controller.rb
136
+ - spec/cache_headers_spec.rb
137
+ - spec/x_headers_spec.rb
122
138
  - spec/configuration_manager_spec.rb
123
139
  has_rdoc: true
124
140
  homepage: http://github.com/mkristian/ixtlan-core
@@ -127,7 +143,7 @@ licenses:
127
143
  post_install_message:
128
144
  rdoc_options:
129
145
  - --main
130
- - README.textile
146
+ - README.md
131
147
  require_paths:
132
148
  - lib
133
149
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -148,6 +164,8 @@ rubyforge_project:
148
164
  rubygems_version: 1.5.1
149
165
  signing_key:
150
166
  specification_version: 3
151
- summary: cache header control, dynamic configuration, and rails generator templates
167
+ summary: cache header control, dynamic configuration, and optimistic find on model via updated_at timestamp
152
168
  test_files:
169
+ - spec/cache_headers_spec.rb
170
+ - spec/x_headers_spec.rb
153
171
  - spec/configuration_manager_spec.rb