rad_kit 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.
Files changed (66) hide show
  1. data/Rakefile +11 -0
  2. data/lib/components/kit.rb +16 -0
  3. data/lib/components/kit.yml +3 -0
  4. data/lib/components/models.rb +7 -0
  5. data/lib/kit/factories.rb +9 -0
  6. data/lib/kit/gems.rb +16 -0
  7. data/lib/kit/http_controller.rb +4 -0
  8. data/lib/kit/http_controller/authorized.rb +51 -0
  9. data/lib/kit/http_controller/localized.rb +13 -0
  10. data/lib/kit/kit.rb +29 -0
  11. data/lib/kit/models.rb +8 -0
  12. data/lib/kit/models/attachment_uploader.rb +15 -0
  13. data/lib/kit/models/attachments_uploader_helper.rb +79 -0
  14. data/lib/kit/models/authorized.rb +188 -0
  15. data/lib/kit/models/authorized_object.rb +167 -0
  16. data/lib/kit/models/default_permissions.yml +29 -0
  17. data/lib/kit/models/file_uploader.rb +26 -0
  18. data/lib/kit/models/micelaneous.rb +1 -0
  19. data/lib/kit/models/role.rb +88 -0
  20. data/lib/kit/models_after.rb +27 -0
  21. data/lib/kit/mongoid.rb +22 -0
  22. data/lib/kit/mongoid/rad_micelaneous.rb +36 -0
  23. data/lib/kit/mongoid/text_processor.rb +44 -0
  24. data/lib/kit/spec.rb +77 -0
  25. data/lib/kit/spec/items_controller_crud.rb +64 -0
  26. data/lib/kit/support.rb +14 -0
  27. data/lib/kit/support/string.rb +6 -0
  28. data/lib/kit/tasks.rb +18 -0
  29. data/lib/kit/text_utils.rb +43 -0
  30. data/lib/kit/text_utils/code_highlighter.rb +58 -0
  31. data/lib/kit/text_utils/custom_markdown.rb +90 -0
  32. data/lib/kit/text_utils/ensure_utf.rb +8 -0
  33. data/lib/kit/text_utils/github_flavoured_markdown.rb +32 -0
  34. data/lib/kit/text_utils/html_sanitizer.rb +89 -0
  35. data/lib/kit/text_utils/image_box.rb +35 -0
  36. data/lib/kit/text_utils/markup.rb +43 -0
  37. data/lib/kit/text_utils/processor.rb +25 -0
  38. data/lib/kit/text_utils/tag_shortcuts.rb +14 -0
  39. data/lib/kit/text_utils/truncate.rb +29 -0
  40. data/lib/kit/text_utils/truncator.rb +15 -0
  41. data/lib/kit/text_utils/urls.rb +13 -0
  42. data/readme.md +10 -0
  43. data/spec/controller/authorization_spec.rb +149 -0
  44. data/spec/controller/comments_spec.rb +54 -0
  45. data/spec/controller/items_spec.rb +45 -0
  46. data/spec/models/attachments_spec.rb +24 -0
  47. data/spec/models/attachments_spec/a.txt +1 -0
  48. data/spec/models/attachments_uploader_helper_spec.rb +108 -0
  49. data/spec/models/attachments_uploader_helper_spec/v1/a.txt +1 -0
  50. data/spec/models/attachments_uploader_helper_spec/v1/b.txt +1 -0
  51. data/spec/models/attachments_uploader_helper_spec/v2/a.txt +1 -0
  52. data/spec/models/authorization_spec.rb +77 -0
  53. data/spec/models/authorized_object_spec.rb +254 -0
  54. data/spec/models/comments_spec.rb +1 -0
  55. data/spec/models/item_spec.rb +51 -0
  56. data/spec/models/role_spec.rb +17 -0
  57. data/spec/models/tags_spec.rb +44 -0
  58. data/spec/models/uploader_spec.rb +37 -0
  59. data/spec/models/uploader_spec//321/204/320/260/320/270/314/206/320/273 /321/201 /320/277/321/200/320/276/320/261/320/265/320/273/320/260/320/274/320/270.txt" +1 -0
  60. data/spec/mongoid/basic_spec.rb +36 -0
  61. data/spec/spec_helper.rb +20 -0
  62. data/spec/spec_helper/controller.rb +9 -0
  63. data/spec/spec_helper/factories.rb +24 -0
  64. data/spec/spec_helper/user.rb +17 -0
  65. data/spec/utils/text_utils_spec.rb +280 -0
  66. metadata +232 -0
@@ -0,0 +1,35 @@
1
+ class Rad::TextUtils::ImageBox < Rad::TextUtils::Processor
2
+ # !![img] => [![img_thumb]][img]
3
+ def process markdown, env
4
+ img_urls = {}
5
+ markdown = markdown.gsub(/!!\[(.+?)\]/) do
6
+ img_key = $1 || ''
7
+ if url = markdown.scan(/\[#{img_key}\]:\s*([^\s]+)$/).first.try(:first)
8
+ unless url =~ /\.[^\.]+\.[^\.]+$/ # image.png
9
+ thumb_img_key = "#{img_key}_thumb"
10
+
11
+ # building url with thumb (foo.png => foo.thumb.png)
12
+ img_urls[thumb_img_key] = url.sub(/\.([^\.]+)$/){".thumb.#{$1}"}
13
+
14
+ "[![][#{thumb_img_key}]][#{img_key}]"
15
+ else # image.(icon|thumb|...).png
16
+ img_key_full = "#{img_key}_full"
17
+
18
+ # building url with thumb (foo.png => foo.thumb.png)
19
+ img_urls[img_key_full] = url.sub(/\.([^\.]+)\.([^\.]+)$/){".#{$2}"}
20
+
21
+ "[![][#{img_key}]][#{img_key_full}]"
22
+ end
23
+ else
24
+ $& || ''
25
+ end
26
+ end
27
+
28
+ unless img_urls.blank?
29
+ markdown << "\n"
30
+ markdown << img_urls.to_a.collect{|k, v| "[#{k}]: #{v}"}.join("\n")
31
+ end
32
+
33
+ call_next markdown, env
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ class Rad::TextUtils::Markup < Rad::TextUtils::Processor
2
+
3
+ def initialize processor = nil
4
+ super
5
+
6
+ @markup = build_from(
7
+ Rad::TextUtils::EnsureUtf,
8
+ Rad::TextUtils::HtmlSanitizer,
9
+
10
+ Rad::TextUtils::CodeHighlighter,
11
+
12
+ Rad::TextUtils::CustomMarkdown,
13
+
14
+ Rad::TextUtils::Urls,
15
+ Rad::TextUtils::TagShortcuts
16
+ )
17
+
18
+ @html = build_from(
19
+ Rad::TextUtils::EnsureUtf,
20
+ Rad::TextUtils::HtmlSanitizer,
21
+ Rad::TextUtils::CodeHighlighter
22
+ )
23
+ end
24
+
25
+ def process text, env
26
+ return text if text.blank?
27
+
28
+ if text =~ /\A\[html\]/i
29
+ text = text.sub(/\A\[html\][\s\n\r]*/i, '')
30
+ chain = @html
31
+ else
32
+ chain = @markup
33
+ end
34
+
35
+ text = chain.process text, env
36
+
37
+ unless text.encoding == Encoding::UTF_8
38
+ raise "something wrong happens, invalid encoding (#{text.encoding} instead of utf-8)!"
39
+ end
40
+
41
+ call_next text, env
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ class Rad::TextUtils::Processor
2
+ def initialize next_processor = nil
3
+ @next_processor = next_processor
4
+ end
5
+
6
+ protected
7
+ def call_next data, env
8
+ if @next_processor
9
+ @next_processor.process data, env
10
+ else
11
+ data
12
+ end
13
+ end
14
+
15
+ def build_from *processors
16
+ processors.reverse.inject nil do |next_processor, meta|
17
+ klass, args = if meta.is_a? Array
18
+ [meta[0], meta[1..-1]]
19
+ else
20
+ [meta, []]
21
+ end
22
+ klass.new next_processor, *args
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ class Rad::TextUtils::TagShortcuts < Rad::TextUtils::Processor
2
+ TAGS = {
3
+ /\[clear\]/ => lambda{|match| "<div class='clear'></div>"},
4
+ /\[space\]/ => lambda{|match| "<div class='space'></div>"}
5
+ }
6
+
7
+ def process markdown, env
8
+ TAGS.each do |k, v|
9
+ markdown.gsub!(k, &v)
10
+ end
11
+
12
+ call_next markdown, env
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ class Rad::TextUtils::Truncate < Rad::TextUtils::Processor
2
+ def initialize processor, length
3
+ super(processor)
4
+ @length = length
5
+ end
6
+
7
+ def process str_or_html, env
8
+ str_or_html ||= ""
9
+
10
+ # Strip from HTML tags
11
+ str_or_html = str_or_html.gsub("<br", " <br").gsub("<p", " <p") # to preserve space in place of <> html elements
12
+ doc = Nokogiri::XML("<div class='root'>#{str_or_html}</div>")
13
+ str = doc.css('.root').first.content
14
+
15
+ str = str.gsub(/\s+/, ' ')
16
+
17
+ # Truncate with no broken words
18
+ str = if str.length >= @length
19
+ shortened = str[0, @length]
20
+ splitted = shortened.split(/\s/)
21
+ words = splitted.length
22
+ splitted[0, words-1].join(" ") + ' ...'
23
+ else
24
+ str
25
+ end
26
+
27
+ call_next str, env
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ class Rad::TextUtils::Truncator < Rad::TextUtils::Processor
2
+ def initialize processor, length
3
+ super(processor)
4
+
5
+ @chain = build_from(
6
+ Rad::TextUtils::EnsureUtf,
7
+ [Rad::TextUtils::Truncate, length]
8
+ )
9
+ end
10
+
11
+ def process text_or_html, env
12
+ text_or_html = @chain.process text_or_html, env
13
+ call_next text_or_html, env
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class Rad::TextUtils::Urls < Rad::TextUtils::Processor
2
+ # Creates <a> tags for all urls.
3
+ # IMPORTANT: make sure you've used #urls_to_images method first
4
+ # if you wanted all images urls to become <img> tags.
5
+ def process html, env
6
+ # becouse it finds only one url in such string "http://some_domain.com http://some_domain.com" we need to aply it twice
7
+ regexp, sub = /(\s|^|\A|\n|\t|\r)(http:\/\/.*?)([,.])?(\s|$|\n|\Z|\t|\r|<)/, '\1<a href="\2">\2</a>\3\4'
8
+ html = html.gsub regexp, sub
9
+ html.gsub regexp, sub
10
+
11
+ call_next html, env
12
+ end
13
+ end
data/readme.md ADDED
@@ -0,0 +1,10 @@
1
+ # Rapid Application Development Kit for Rad Framework
2
+
3
+ [add docs]
4
+
5
+ # Low
6
+
7
+ - WYSIWYG from WordPress/GitHub
8
+ - remove unused locale tokens
9
+
10
+ # TODO
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Authorizations" do
4
+ with_controllers
5
+
6
+ isolate :config
7
+
8
+ before :all do
9
+ @permissions = {
10
+ 'call_controller_level' => [],
11
+ 'call_business_logic_level' => [],
12
+ 'call_with_owner' => []
13
+ }
14
+
15
+ class ::AuthorizationController
16
+ inherit Rad::Controller::Http
17
+
18
+ inherit Rad::Controller::Http::Authorized
19
+
20
+ require_permission :call_controller_level, only: :controller_level
21
+
22
+ def unprotected
23
+ render_ok
24
+ end
25
+
26
+ def controller_level
27
+ render_ok
28
+ end
29
+
30
+ def business_logic_level
31
+ require_permission :call_business_logic_level
32
+ render_ok
33
+ end
34
+
35
+ def with_owner
36
+ require_permission :call_with_owner, owned_object
37
+ render_ok
38
+ end
39
+
40
+ def with_owner_controller_level
41
+ render_ok
42
+ end
43
+ require_permission :call_with_owner, only: :with_owner_controller_level do
44
+ owned_object
45
+ end
46
+
47
+ protected
48
+ def owned_object
49
+ @@owned_object
50
+ end
51
+
52
+ def self.owned_object= o
53
+ @@owned_object = o
54
+ end
55
+ end
56
+
57
+ rad.router.configure do |c|
58
+ c.resource :authorization_controllers, class_name: 'AuthorizationController'
59
+ end
60
+
61
+ I18n.locale = :en
62
+ end
63
+
64
+ after :all do
65
+ remove_constants %w(AuthorizationController)
66
+ end
67
+
68
+ before do
69
+ AuthorizationController.owned_object = nil
70
+
71
+ rad.config.permissions = @permissions
72
+
73
+ @user = Models::User.new
74
+ rad.user = @user
75
+ end
76
+
77
+ def raise_authorization_error
78
+ raise_error(UserError, /Access Denied/)
79
+ end
80
+
81
+ it "should allow to call unprotected methods" do
82
+ call('/authorization_controllers/unprotected')
83
+ response.body.should == "ok"
84
+ end
85
+
86
+ it "should allow declarative authorization at controller level" do
87
+ @user.stub!(:can?).and_return(false)
88
+ lambda{
89
+ call '/authorization_controllers/controller_level'
90
+ }.should raise_authorization_error
91
+ # response.should be_redirect
92
+
93
+ @user.stub!(:can?).and_return(true)
94
+ call '/authorization_controllers/controller_level'
95
+ response.body.should == "ok"
96
+ end
97
+
98
+ it "should allow declarative authorization at business logic level" do
99
+ @user.stub!(:can?).and_return(false)
100
+ lambda{
101
+ call '/authorization_controllers/business_logic_level'
102
+ }.should raise_authorization_error
103
+ # response.should be_redirect
104
+
105
+ @user.stub!(:can?).and_return(true)
106
+ call '/authorization_controllers/business_logic_level'
107
+ response.body.should == "ok"
108
+ end
109
+
110
+ it "should use owner if provided" do
111
+ @user.stub!(:can?){false}
112
+ lambda{
113
+ call '/authorization_controllers/with_owner'
114
+ }.should raise_authorization_error
115
+ # response.should be_redirect
116
+
117
+
118
+ o = Object.new
119
+ o.stub!(:owner_name){@user.name}
120
+ AuthorizationController.owned_object = o
121
+
122
+ @user.stub!(:can?) do |operation, object|
123
+ object and object.owner_name == @user.name
124
+ end
125
+
126
+ call '/authorization_controllers/with_owner'
127
+ response.body.should == "ok"
128
+ end
129
+
130
+ it "should use owner if provided (action level)" do
131
+ @user.stub!(:can?){false}
132
+ lambda{
133
+ call '/authorization_controllers/with_owner_controller_level'
134
+ }.should raise_authorization_error
135
+ # response.should be_redirect
136
+
137
+
138
+ o = Object.new
139
+ o.stub!(:owner_name){@user.name}
140
+ AuthorizationController.owned_object = o
141
+
142
+ @user.stub!(:can?) do |operation, object|
143
+ object and object.owner_name == @user.name
144
+ end
145
+
146
+ call '/authorization_controllers/with_owner_controller_level'
147
+ response.body.should == "ok"
148
+ end
149
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Comments" do
4
+ with_controllers
5
+ set_controller Controllers::Comments
6
+ login_as :user
7
+
8
+ before do
9
+ @item = Factory.create :item
10
+ end
11
+
12
+ def create_comment original_text = 'text'
13
+ Factory.create :comment, item: @item, owner: @user
14
+ end
15
+
16
+ it "should display new dialog" do
17
+ call :new, format: 'js', item_id: @item.to_param
18
+ response.should be_ok
19
+ end
20
+
21
+ it "should create Comment" do
22
+ comment_attributes = Factory.attributes_for :comment
23
+ pcall :create, format: 'js', item_id: @item.to_param, model: comment_attributes
24
+ response.should be_ok
25
+
26
+ Models::Comment.count.should == 1
27
+ comment = Models::Comment.first
28
+ comment.original_text.should == comment_attributes[:original_text]
29
+ comment.owner.should == @user
30
+ comment.item.should == @item
31
+ end
32
+
33
+ it "should display edit dialog" do
34
+ comment = create_comment
35
+ call :edit, format: 'js', id: comment.to_param
36
+ response.should be_ok
37
+ end
38
+
39
+ it "should update Comment" do
40
+ comment = create_comment
41
+ new_attributes = {original_text: 'new text'}
42
+ pcall :update, format: 'js', id: comment.to_param, model: new_attributes
43
+ response.should be_ok
44
+
45
+ comment.reload
46
+ comment.original_text.should == 'new text'
47
+ end
48
+
49
+ it "should delete Comment" do
50
+ comment = create_comment
51
+ pcall :destroy, format: 'js', id: comment.to_param
52
+ Models::Comment.count.should == 0
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Items" do
4
+ with_controllers
5
+ login_as :manager, name: 'auser'
6
+
7
+ describe "Basic" do
8
+ set_controller Controllers::Items
9
+
10
+ it "should update layout" do
11
+ @item = Factory.create :item
12
+ @item.layout.should == nil
13
+
14
+ pcall :layout, id: @item.to_param, value: 'home', format: 'js'
15
+ response.should be_ok
16
+
17
+ @item.reload
18
+ @item.layout.should == 'home'
19
+ end
20
+
21
+ it 'viewers, add_roles' do
22
+ @item = Factory.create :item
23
+ @item.viewers.should == %w{manager user:auser}
24
+ @item.owner_name.should == @user.name
25
+
26
+ pcall :viewers, id: @item.to_param, add_roles: 'user', format: 'js'
27
+ response.should be_ok
28
+
29
+ @item.reload
30
+ @item.viewers.should == %w{manager member user user:auser}
31
+ end
32
+
33
+ it "should redirect to /items if no default_url specified" do
34
+ call :redirect
35
+ response.should redirect_to(rad.router.default_url)
36
+ end
37
+
38
+ it "should display :all"
39
+ # do
40
+ # call :all
41
+ # response.should be_ok
42
+ # end
43
+
44
+ end
45
+ end