ixtlan-core 0.5.0 → 0.6.0

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