rad_ext 0.0.1

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.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rake_ext'
2
+
3
+ project(
4
+ name: "rad_ext",
5
+ gem: true,
6
+ summary: "Extensions for Rad Framework",
7
+
8
+ bin: 'bin',
9
+
10
+ author: "Alexey Petrushin",
11
+ homepage: "http://github.com/alexeypetrushin/rad_ext"
12
+ )
@@ -0,0 +1,22 @@
1
+ class Abstract
2
+ def initialize dir
3
+ @dir = File.expand_path(dir)
4
+ end
5
+
6
+ # def config options = {}
7
+ # rad.config.merge_config! "#{dir}/config/config.yml", options
8
+ # end
9
+
10
+ def routes
11
+ routes_file = "#{dir}/config/routes.rb"
12
+ load routes_file if File.exist? routes_file
13
+ end
14
+
15
+ def locales
16
+ I18n.load_path += Dir["#{dir}/config/locales/**/*.{rb,yml}"]
17
+ I18n.load_path += Dir["#{dir}/config/locales/*.{rb,yml}"]
18
+ end
19
+
20
+ protected
21
+ attr_reader :dir #, :after_config, :after_environment
22
+ end
@@ -0,0 +1,2 @@
1
+ class Runtime < Abstract
2
+ end
@@ -0,0 +1,32 @@
1
+ class Web < Abstract
2
+ def asset_paths *relative_paths
3
+ relative_paths = relative_paths.first if relative_paths.first.is_a? Array
4
+ relative_paths.each do |relative_path|
5
+ path = "#{dir}/#{relative_path}"
6
+ rad.assets.paths << path unless rad.assets.paths.include? path
7
+ end
8
+ end
9
+
10
+ def load_paths *relative_paths
11
+ relative_paths = relative_paths.first if relative_paths.first.is_a? Array
12
+ relative_paths.each do |relative_path|
13
+ path = "#{dir}/#{relative_path}"
14
+ $LOAD_PATH << path unless $LOAD_PATH.include? path
15
+ end
16
+ end
17
+
18
+ def template_paths *relative_paths
19
+ rad.template
20
+
21
+ relative_paths = relative_paths.first if relative_paths.first.is_a? Array
22
+ relative_paths.each do |relative_path|
23
+ path = "#{dir}/#{relative_path}"
24
+ rad.template.paths << path unless rad.template.paths.include? path
25
+ end
26
+ end
27
+
28
+ def autoload_paths *relative_paths
29
+ relative_paths = relative_paths.first if relative_paths.first.is_a? Array
30
+ relative_paths.each{|d| autoload_dir "#{dir}/#{d}", true}
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module ForgeryProtector
2
+ BROWSER_GENERATED_TYPES = %w(
3
+ text/html
4
+ text/plain
5
+ application/x-www-form-urlencoded
6
+ multipart/form-data
7
+ ).to_set
8
+
9
+ BROWSER_GENERATED_FORMATS = %w(html js)
10
+
11
+ protected
12
+ def protect_from_forgery
13
+ request = workspace.request
14
+ if request.session
15
+ sat = request.session['authenticity_token']
16
+ content_type = request.content_type
17
+ format = workspace.params.format
18
+
19
+ allow = (
20
+ request.get? or
21
+ (content_type.present? and !BROWSER_GENERATED_TYPES.include?(content_type.downcase)) or
22
+ (format.present? and !BROWSER_GENERATED_FORMATS.include?(format)) or
23
+ (sat.present? and sat == params.authenticity_token)
24
+ )
25
+
26
+ raise "invalid authenticity token!" unless allow
27
+
28
+ @authenticity_token = sat
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ # Sets format for :js as :html and wraps body into <textarea>
2
+ # Forms with files can be submitted by ajax only via iframe, and it requires
3
+ # the response have 'html' encoding and be wrapped into <textarea>
4
+ class AjaxHelper < Conveyors::Processor
5
+ def call
6
+ response = workspace.response.must_be.defined
7
+ request = workspace.request.must_be.defined
8
+
9
+ next_processor.call
10
+
11
+ if workspace.params? and workspace.params.format == 'js' and !request.xhr?
12
+ response.content_type = Mime['html']
13
+ workspace.content = "<textarea>#{workspace.content}</textarea>"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # enshure domain has no www. except if there's custom subdomain
2
+ class EnsureNoWww < Conveyors::Processor
3
+ def call
4
+ workspace.params.must_be.defined
5
+ if workspace.params.format == 'html' and url_with_www?
6
+ redirect_without_www
7
+ else
8
+ next_processor.call
9
+ end
10
+ end
11
+
12
+ protected
13
+ def uri
14
+ @uri ||= Uri.parse workspace.request.url
15
+ end
16
+
17
+ def url_with_www?
18
+ uri.host =~ /^www\./
19
+ end
20
+
21
+ def redirect_without_www
22
+ uri.host = uri.host.sub(/^www\./, '')
23
+ url = uri.to_s
24
+
25
+ response = workspace.response
26
+ response.status = 301
27
+ response.headers['Location'] = url
28
+ response.body = %(<html><body>You are being <a href="#{url.html_escape}">redirected</a>.</body></html>)
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ # %w(
2
+ # abstract
3
+ # runtime
4
+ # web
5
+ # ).each{|f| require "rad_ext/configurators/#{f}"}
6
+
7
+ class Micon::Core
8
+ def configure configurator_name, dir, &block
9
+ configurator_class = "Rad::Configurators::#{configurator_name.to_s.classify}".constantize
10
+ configurator = configurator_class.new dir
11
+ block.call configurator if block
12
+ end
13
+ end
@@ -0,0 +1,62 @@
1
+ # {
2
+ # :'ru' => {
3
+ # pluralize: lambda { |n|
4
+ # # Правило плюрализации для русского языка, взято из CLDR, http://unicode.org/cldr/
5
+ # #
6
+ # #
7
+ # # Russian language pluralization rules, taken from CLDR project, http://unicode.org/cldr/
8
+ # #
9
+ # # one -> n mod 10 is 1 and n mod 100 is not 11;
10
+ # # few -> n mod 10 in 2..4 and n mod 100 not in 12..14;
11
+ # # many -> n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14;
12
+ # # other -> everything else
13
+ # #
14
+ # # Пример
15
+ # #
16
+ # # :one = 1, 21, 31, 41, 51, 61...
17
+ # # :few = 2-4, 22-24, 32-34...
18
+ # # :many = 0, 5-20, 25-30, 35-40...
19
+ # # :other = 1.31, 2.31, 5.31...
20
+ # modulo10 = n.modulo(10)
21
+ # modulo100 = n.modulo(100)
22
+ #
23
+ # if modulo10 == 1 && modulo100 != 11
24
+ # :one
25
+ # elsif (modulo10 == 2 || modulo10 == 3 || modulo10 == 4) && !(modulo100 == 12 || modulo100 == 13 || modulo100 == 14)
26
+ # :few
27
+ # elsif modulo10 == 0 || (modulo10 == 5 || modulo10 == 6 || modulo10 == 7 || modulo10 == 8 || modulo10 == 9) || (modulo100 == 11 || modulo100 == 12 || modulo100 == 13 || modulo100 == 14)
28
+ # :many
29
+ # else
30
+ # :other
31
+ # end
32
+ # }
33
+ # }
34
+ # }
35
+
36
+ {
37
+ ru: {
38
+ i18n: {
39
+ plural: {
40
+ rule: lambda{|n|
41
+ # Правило плюрализации для русского языка, взято из CLDR, http://unicode.org/cldr/
42
+ #
43
+ #
44
+ # Russian language pluralization rules, taken from CLDR project, http://unicode.org/cldr/
45
+ #
46
+ # one -> n mod 10 is 1 and n mod 100 is not 11;
47
+ # few -> n mod 10 in 2..4 and n mod 100 not in 12..14;
48
+ # many -> n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14;
49
+ # other -> everything else
50
+ #
51
+ # Пример
52
+ #
53
+ # :one = 1, 21, 31, 41, 51, 61...
54
+ # :few = 2-4, 22-24, 32-34...
55
+ # :many = 0, 5-20, 25-30, 35-40...
56
+ # :other = 1.31, 2.31, 5.31...
57
+ n % 10 == 1 && n % 100 != 11 ? :one : [2, 3, 4].include?(n % 10) && ![12, 13, 14].include?(n % 100) ? :few : n % 10 == 0 || [5, 6, 7, 8, 9].include?(n % 10) || [11, 12, 13, 14].include?(n % 100) ? :many : :other
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,16 @@
1
+ # Hack, ActiveSupport currently uses differrent version
2
+ # gem 'i18n', '>= 0.4.1'
3
+ # require 'i18n'
4
+
5
+ require "i18n/backend/pluralization"
6
+ I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
7
+
8
+ I18n.load_path += Dir["#{__FILE__.dirname}/i18n/locales/*/*.{rb,yml}"]
9
+
10
+
11
+ #
12
+ # Helpers for Rad
13
+ #
14
+ [Rad::Controller::Abstract, Rad::Controller::Context].each do |klass|
15
+ klass.delegate :t, to: I18n
16
+ end
@@ -0,0 +1,16 @@
1
+ Rad::Controller::Abstract::ClassMethods.class_eval do
2
+ def prepare_model aclass, opt = {}
3
+ opt = opt.symbolize_keys
4
+ id = opt.delete(:id) || :id
5
+ variable = opt.delete(:variable) || aclass.alias.underscore
6
+
7
+ finder = opt.delete(:finder) || :find!
8
+
9
+ method = "prepare_#{variable}"
10
+ define_method method do
11
+ model = aclass.send finder, params[id]
12
+ instance_variable_set "@#{variable}", model
13
+ end
14
+ before method, opt
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ class UserError < StandardError
2
+ end
3
+
4
+ Object.class_eval do
5
+ def raise_user_error msg
6
+ raise UserError, msg
7
+ end
8
+
9
+ def self.raise_user_error msg
10
+ raise UserError, msg
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ require 'rad'
2
+
3
+ %w(
4
+ i18n
5
+ prepare_model
6
+ user_error
7
+ ).each{|f| require "rad_ext/extensions/#{f}"}
@@ -0,0 +1,7 @@
1
+ gem 'i18n', '0.5.0'
2
+
3
+
4
+ if respond_to? :fake_gem
5
+ fake_gem 'rad_core'
6
+ fake_gem 'rad_assets'
7
+ end
@@ -0,0 +1,70 @@
1
+ #
2
+ # Router
3
+ #
4
+ rad.router.routers = [
5
+ [:alias_router, Rad::Router::AliasRouter.new],
6
+ [:basic_router, Rad::Router::BasicRouter.new],
7
+ [:restful_router, Rad::Router::RestfulRouter.new],
8
+ [:object_router, Rad::Router::ObjectRouter.new]
9
+ ]
10
+
11
+
12
+ #
13
+ # Conveyors
14
+ #
15
+ rad.conveyors.web do |web|
16
+ # conveyor
17
+ web.use Rad::Conveyors::Processors::ConveyorLogger
18
+
19
+ # http
20
+ web.use Rad::Http::Processors::HttpWriter
21
+ web.use Rad::Http::Processors::PrepareParams
22
+ web.use Rad::Http::Processors::EvaluateFormat
23
+ web.use Rad::Http::Processors::HttpLogger
24
+
25
+ # forgery protection
26
+ web.use Rad::Processors::PrepareAutenticityToken
27
+
28
+ # ensure no www
29
+ web.use Rad::Processors::EnsureNoWww
30
+
31
+ # ajax
32
+ web.use Rad::Processors::AjaxHelper
33
+
34
+ # html
35
+ # web.use ScopedParams
36
+ web.use Rad::Html::Processors::PrepareFlash
37
+
38
+ # controller
39
+ web.use Rad::Controller::Processors::ControllerErrorHandling
40
+
41
+ # router
42
+ web.use Rad::Router::Processors::Router, :class, :method_name
43
+
44
+ # controller
45
+ web.use Rad::Controller::Processors::ControllerLogger
46
+ web.use Rad::Controller::Processors::ControllerCaller
47
+
48
+ web.build!
49
+ end
50
+
51
+
52
+ #
53
+ # RackAdapter
54
+ #
55
+ rad.http.initialize_rack do |builder|
56
+ # CommonLogger, ShowExceptions, Lint
57
+ builder.use Rack::Lint if rad.development?
58
+
59
+ # Static Files
60
+ if rad.http.static? and rad.http.public_path and rad.development?
61
+ filters = /^\/.*?\/static\/|^\/static\/|\/favicon/
62
+ builder.use Rad::Assets::StaticFiles, filters
63
+ end
64
+
65
+ # use Rack::Session::Cookie, key: 'rack.session', domain: 'foo.com', path: '/', expire_after: 2592000, secret: 'change_me'
66
+ builder.use Rack::Session::Cookie, rad.http.session.stringify_keys if rad.http.session
67
+
68
+ # builder.use Rack::CommonLogger
69
+ builder.use Rack::MethodOverride
70
+ end
@@ -0,0 +1,56 @@
1
+ #
2
+ # Processor
3
+ #
4
+ class Rad::Processors::PrepareAutenticityToken < Rad::Conveyors::Processor
5
+ def call
6
+ if rad.http.session
7
+ request = workspace.request.must_be.defined
8
+ params = workspace.params.must_be.defined
9
+
10
+ token = request.session['authenticity_token']
11
+
12
+ if token.blank? and request.get? and
13
+ token = generate_authenticity_token
14
+ request.session['authenticity_token'] = token
15
+ end
16
+ end
17
+
18
+ next_processor.call
19
+ end
20
+
21
+
22
+ protected
23
+ def generate_authenticity_token
24
+ ActiveSupport::SecureRandom.base64(32)
25
+ end
26
+ end
27
+
28
+
29
+ #
30
+ # Controller
31
+ #
32
+ Rad::Controller::Http.include Rad::Controller::ForgeryProtector
33
+
34
+ Rad::Controller::Http::ClassMethods.class_eval do
35
+ def protect_from_forgery options = {}
36
+ before :protect_from_forgery, options
37
+ end
38
+ end
39
+
40
+
41
+ #
42
+ # View
43
+ #
44
+ Rad::Html::FormHelper.class_eval do
45
+ def authenticity_token
46
+ @authenticity_token
47
+ end
48
+
49
+ alias_method :form_tag_without_at, :form_tag
50
+ def form_tag *args, &b
51
+ form_tag_without_at *args do
52
+ concat(hidden_field_tag('authenticity_token', authenticity_token) + "\n") if authenticity_token
53
+ b.call if b
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ %w(
2
+ configurators
3
+ extensions
4
+ protect_from_forgery
5
+ ).each{|f| require "rad_ext/#{f}"}
@@ -0,0 +1,4 @@
1
+ module Rad::Controller::ForgeryProtector
2
+ def protect_from_forgery; end
3
+ end
4
+
@@ -0,0 +1,18 @@
1
+ require 'rake_ext'
2
+ require 'ruby_ext'
3
+
4
+ task :environment do
5
+ require 'rad'
6
+ rad.mode = ENV['m'] || ENV['mode'] || ENV['env'] || ENV['environment'] || :development
7
+ rad.runtime_path = File.expand_path '.'
8
+
9
+ require 'rad_ext'
10
+ rad.web
11
+
12
+ require 'rad_ext/utils/cli_helper'
13
+
14
+ Rad::CliHelper.use_runtime_path!
15
+
16
+ load "./init.rb"
17
+ rad.environment
18
+ end
@@ -0,0 +1,34 @@
1
+ module Rad::CliHelper
2
+ RUNTIME_DIR = 'runtime'
3
+
4
+ class << self
5
+ inject logger: :logger
6
+
7
+ def run_console
8
+ prepare_running_environment
9
+
10
+ require 'irb'
11
+ IRB.start
12
+ end
13
+
14
+ def run_server
15
+ app = prepare_running_environment
16
+
17
+ rad.http.run app, rad.http.host, rad.http.port
18
+ end
19
+
20
+ def use_runtime_path!
21
+ runtime_path = "./#{RUNTIME_DIR}"
22
+ Dir.chdir runtime_path if Dir.exist? runtime_path
23
+ end
24
+
25
+ protected
26
+ def prepare_running_environment
27
+ use_runtime_path!
28
+
29
+ require 'rack'
30
+ app, options = Rack::Builder.parse_file 'config.ru'
31
+ app
32
+ end
33
+ end
34
+ end
data/lib/rad_ext.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rad'
2
+ require 'rad_ext/gems'
3
+
4
+ lib_dir = __FILE__.dirname
5
+ autoload_dir lib_dir
6
+
7
+ rad.must_not.include :web
8
+ rad.register :web, depends_on: [:html, :router, :controller, :http] do
9
+ require 'rad/core_web/_require'
10
+ require 'rad_ext/require'
11
+
12
+ load 'rad_ext/profiles/web_ext.rb'
13
+ load 'rad/profiles/mailer.rb'
14
+
15
+ rad.assets
16
+
17
+ true
18
+ end
data/readme.md ADDED
@@ -0,0 +1,12 @@
1
+ # Extensions for the Rad framework.
2
+
3
+ - face - tools for rapid interface creation.
4
+ - common_interface - common user interface for Rad.
5
+ - rad_ext - additions and extensions of the Rad.
6
+ - rad_js - JS plugin for the Rad.
7
+ - rad - Rapid Application Development tool built upon of the Rad.
8
+
9
+ Please go to specs for docs.
10
+
11
+ P.S.
12
+ All these components will be in standalone gems, but right now it's simpler for me to hold all of them in one place.
@@ -0,0 +1,5 @@
1
+ en:
2
+ name: "Name"
3
+ comments:
4
+ one: "%{count} comment"
5
+ many: "%{count} comments"
@@ -0,0 +1,7 @@
1
+ ru:
2
+ name: "Имя"
3
+ comments_count:
4
+ one: "%{count} комментарий"
5
+ few: "%{count} комментария"
6
+ many: "%{count} комментариев"
7
+ other: "%{count} комментариев"
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper_with_rad"
4
+
5
+ describe 'I18n' do
6
+ before :all do
7
+ rad.web
8
+ rad.reset :conveyors
9
+
10
+ I18n.load_path += Dir["#{spec_dir}/locales/*/*.{rb,yml}"]
11
+ end
12
+
13
+ def t *args
14
+ I18n.t *args
15
+ end
16
+
17
+ it "basic" do
18
+ I18n.locale = 'en'
19
+ t(:name).should == "Name"
20
+ t(:name).is_a?(String).should be_true
21
+
22
+ I18n.locale = 'ru'
23
+ t(:name).should == "Имя"
24
+ end
25
+
26
+ it "pluggable pluralization" do
27
+ I18n.locale = 'ru'
28
+ t(:comments_count, count: 1).should == "1 комментарий"
29
+ t(:comments_count, count: 2).should == "2 комментария"
30
+ t(:comments_count, count: 5).should == "5 комментариев"
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ require "spec_helper_with_rad"
2
+
3
+ describe "User Error" do
4
+ rad.web
5
+ rad.reset :conveyors
6
+ isolate :conveyors, before: :all
7
+
8
+ before :all do
9
+ load 'spec_helper/web_profile.rb'
10
+
11
+ class ::SomeModel
12
+ def self.find! id
13
+ id.should == 'some id'
14
+ SomeModel.new
15
+ end
16
+ end
17
+ end
18
+ after :all do
19
+ remove_constants %w(SomeModel ControllerSpec)
20
+ end
21
+
22
+ it "user error" do
23
+ class ::ControllerSpec
24
+ inherit Rad::Controller::Http
25
+
26
+ prepare_model SomeModel, id: :some_model, variable: 'some_model'
27
+
28
+ def action
29
+ @some_model.should_not == nil
30
+ render inline: 'ok'
31
+ end
32
+ end
33
+
34
+ ccall(ControllerSpec, :action, some_model: 'some id').should == 'ok'
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ require "spec_helper_with_rad"
2
+
3
+ describe "User Error" do
4
+ rad.web
5
+ rad.reset :conveyors
6
+
7
+ isolate :conveyors, before: :all
8
+
9
+ before(:all){load 'spec_helper/web_profile.rb'}
10
+
11
+ after :all do
12
+ remove_constants %w(UserErrorSpec)
13
+ end
14
+
15
+ it "user error" do
16
+ class ::UserErrorSpec
17
+ inherit Rad::Controller::Http
18
+
19
+ def call
20
+ raise_user_error "some error"
21
+ end
22
+
23
+ protected
24
+ def catch_user_error
25
+ begin
26
+ yield
27
+ rescue UserError => ue
28
+ render inline: "Catched #{ue.message}"
29
+ end
30
+ end
31
+ around :catch_user_error
32
+ end
33
+
34
+ ccall(UserErrorSpec, :call).should == "Catched some error"
35
+ end
36
+ end
@@ -0,0 +1,188 @@
1
+ require "spec_helper_with_rad"
2
+
3
+ describe "Forgery protection" do
4
+ rad.web
5
+ rad.reset :conveyors
6
+
7
+ with_prepare_params
8
+
9
+ isolate :conveyors
10
+
11
+ before :all do
12
+ class ForgerySpecHelper < Rad::Conveyors::Processor
13
+ def call
14
+ block = workspace.check_forgery.before_request
15
+ block.call workspace if block
16
+ workspace.before_request_done = true
17
+
18
+ next_processor.call
19
+
20
+ block = workspace.check_forgery.after_request
21
+ block.call workspace if block
22
+ workspace.after_request_done = true
23
+ end
24
+ end
25
+
26
+ rad.conveyors.web do |web|
27
+ web.use Rad::Http::Processors::PrepareParams
28
+ web.use Rad::Http::Processors::EvaluateFormat
29
+ web.use ForgerySpecHelper
30
+ web.use Rad::Processors::PrepareAutenticityToken
31
+ web.use Rad::Controller::Processors::ControllerCaller
32
+ end
33
+
34
+ class ::AnRemote
35
+ inherit Rad::Controller::Http
36
+
37
+ protect_from_forgery only: :protected_method
38
+
39
+ def protected_method
40
+ render inline: 'protected result'
41
+ end
42
+
43
+ def method_without_protection
44
+ render inline: 'result'
45
+ end
46
+
47
+ def dumb_method; end
48
+ end
49
+ end
50
+
51
+ after :all do
52
+ rad.reset :conveyors
53
+ remove_constants %w(AnRemote ForgerySpecHelper)
54
+ end
55
+
56
+ before do
57
+ rad.http.stub(:session).and_return({'key' => 'session_id'})
58
+ end
59
+
60
+ def check_forgery opt
61
+ workspace = nil
62
+
63
+ result = rad.http.call(rad.http.mock_environment, check_forgery: opt.to_openobject) do |c|
64
+ c.call
65
+ workspace = rad[:workspace]
66
+ end
67
+
68
+ workspace.before_request_done.should be_true
69
+ workspace.after_request_done.should be_true
70
+ workspace
71
+ end
72
+
73
+ it "should set :authenticity_token only for :get and 'html' request" do
74
+ check_forgery(
75
+ before_request: lambda{|workspace|
76
+ workspace.env['REQUEST_METHOD'] = 'GET'
77
+ workspace.env['CONTENT_TYPE'] = 'text/html'
78
+ workspace.class = AnRemote
79
+ workspace.method_name = :dumb_method
80
+ },
81
+ after_request: lambda{|workspace|
82
+ workspace.request.session['authenticity_token'].should_not be_blank
83
+ }
84
+ )
85
+
86
+ # post
87
+ check_forgery(
88
+ before_request: lambda{|workspace|
89
+ workspace.env['REQUEST_METHOD'] = 'POST'
90
+ workspace.env['CONTENT_TYPE'] = 'text/html'
91
+ workspace.class = AnRemote
92
+ workspace.method_name = :dumb_method
93
+ },
94
+ after_request: lambda{|workspace|
95
+ workspace.request.session['authenticity_token'].should be_blank
96
+ }
97
+ )
98
+ end
99
+
100
+ it "should check any non :get request with browser's formats for :authenticity_token" do
101
+ lambda{
102
+ check_forgery(
103
+ before_request: lambda{|workspace|
104
+ workspace.env['REQUEST_METHOD'] = 'POST'
105
+ workspace.env['CONTENT_TYPE'] = 'text/html'
106
+ workspace.class = AnRemote
107
+ workspace.method_name = 'protected_method'
108
+ }
109
+ )
110
+ }.should raise_error(/invalid authenticity token/)
111
+ end
112
+
113
+ it "should pass request with correct authenticity_token" do
114
+ check_forgery(
115
+ before_request: lambda{|workspace|
116
+ workspace.env['REQUEST_METHOD'] = 'POST'
117
+ workspace.env['CONTENT_TYPE'] = 'text/html'
118
+ workspace.request.session['authenticity_token'] = 'secure token'
119
+ workspace.params['authenticity_token'] = 'secure token'
120
+ workspace.class = AnRemote
121
+ workspace.method_name = 'protected_method'
122
+ },
123
+ after_request: lambda{|workspace|
124
+ workspace.content.should == "protected result"
125
+ }
126
+ )
127
+ end
128
+
129
+ it "should not check request with non-browser content type" do
130
+ check_forgery(
131
+ before_request: lambda{|workspace|
132
+ workspace.env['REQUEST_METHOD'] = 'POST'
133
+ workspace.env['CONTENT_TYPE'] = 'non-browser-format'
134
+ workspace.class = AnRemote
135
+ workspace.method_name = 'protected_method'
136
+ },
137
+ after_request: lambda{|workspace|
138
+ workspace.content.should == "protected result"
139
+ }
140
+ )
141
+ end
142
+
143
+ it "should not check request with non-browser format" do
144
+ check_forgery(
145
+ before_request: lambda{|workspace|
146
+ workspace.env['REQUEST_METHOD'] = 'POST'
147
+ workspace.env['CONTENT_TYPE'] = 'text/html'
148
+ workspace.params['format'] = 'json'
149
+ workspace.class = AnRemote
150
+ workspace.method_name = 'protected_method'
151
+ },
152
+ after_request: lambda{|workspace|
153
+ workspace.content.should == "protected result"
154
+ }
155
+ )
156
+ end
157
+
158
+ it "should not protect non protected methods" do
159
+ check_forgery(
160
+ before_request: lambda{|workspace|
161
+ workspace.env['REQUEST_METHOD'] = 'POST'
162
+ workspace.env['CONTENT_TYPE'] = 'text/html'
163
+ workspace.class = AnRemote
164
+ workspace.method_name = 'method_without_protection'
165
+ },
166
+ after_request: lambda{|workspace|
167
+ workspace.content.should == "result"
168
+ }
169
+ )
170
+ end
171
+
172
+ # it "OUTDATED should use :session_authenticity_token from params (for flash support)" do
173
+ # check_forgery(
174
+ # before_request: lambda{|workspace|
175
+ # workspace.env['REQUEST_METHOD'] = 'POST'
176
+ # workspace.params.format = 'text/html'
177
+ # # workspace.params['session_authenticity_token'] = 'secure token'
178
+ # workspace.params['authenticity_token'] = 'secure token'
179
+ # workspace.class = AnRemote
180
+ # workspace.method_name = 'protected_method'
181
+ # },
182
+ # after_request: lambda{|workspace|
183
+ # workspace.content.should == "protected result"
184
+ # }
185
+ # )
186
+ # end
187
+
188
+ end
@@ -0,0 +1,3 @@
1
+ rad.conveyors.web do |web|
2
+ web.use Rad::Controller::Processors::ControllerCaller
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'rspec_ext'
2
+ require 'rad_ext'
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ require 'rad'
4
+ require 'rad/spec'
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rad_ext
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alexey Petrushin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-04 00:00:00.000000000 +04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: i18n
17
+ requirement: &2956510 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - =
21
+ - !ruby/object:Gem::Version
22
+ version: 0.5.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2956510
26
+ - !ruby/object:Gem::Dependency
27
+ name: rad_core
28
+ requirement: &2956210 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2956210
37
+ - !ruby/object:Gem::Dependency
38
+ name: rad_assets
39
+ requirement: &2955960 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *2955960
48
+ description:
49
+ email:
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - Rakefile
55
+ - readme.md
56
+ - lib/rad/configurators/abstract.rb
57
+ - lib/rad/configurators/runtime.rb
58
+ - lib/rad/configurators/web.rb
59
+ - lib/rad/controller/forgery_protector.rb
60
+ - lib/rad/processors/ajax_helper.rb
61
+ - lib/rad/processors/ensure_no_www.rb
62
+ - lib/rad_ext/configurators.rb
63
+ - lib/rad_ext/extensions/i18n/locales/ru/pluralization.rb
64
+ - lib/rad_ext/extensions/i18n.rb
65
+ - lib/rad_ext/extensions/prepare_model.rb
66
+ - lib/rad_ext/extensions/user_error.rb
67
+ - lib/rad_ext/extensions.rb
68
+ - lib/rad_ext/gems.rb
69
+ - lib/rad_ext/profiles/web_ext.rb
70
+ - lib/rad_ext/protect_from_forgery.rb
71
+ - lib/rad_ext/require.rb
72
+ - lib/rad_ext/spec.rb
73
+ - lib/rad_ext/tasks.rb
74
+ - lib/rad_ext/utils/cli_helper.rb
75
+ - lib/rad_ext.rb
76
+ - spec/extensions/i18n_spec/locales/en/general.yml
77
+ - spec/extensions/i18n_spec/locales/ru/general.yml
78
+ - spec/extensions/i18n_spec.rb
79
+ - spec/extensions/prepare_model_spec.rb
80
+ - spec/extensions/user_error_spec.rb
81
+ - spec/processors/protect_from_forgery_spec.rb
82
+ - spec/spec_helper/web_profile.rb
83
+ - spec/spec_helper.rb
84
+ - spec/spec_helper_with_rad.rb
85
+ has_rdoc: true
86
+ homepage: http://github.com/alexeypetrushin/rad_ext
87
+ licenses: []
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.5.1
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Extensions for Rad Framework
110
+ test_files: []