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.
- data/Rakefile +11 -0
- data/lib/components/kit.rb +16 -0
- data/lib/components/kit.yml +3 -0
- data/lib/components/models.rb +7 -0
- data/lib/kit/factories.rb +9 -0
- data/lib/kit/gems.rb +16 -0
- data/lib/kit/http_controller.rb +4 -0
- data/lib/kit/http_controller/authorized.rb +51 -0
- data/lib/kit/http_controller/localized.rb +13 -0
- data/lib/kit/kit.rb +29 -0
- data/lib/kit/models.rb +8 -0
- data/lib/kit/models/attachment_uploader.rb +15 -0
- data/lib/kit/models/attachments_uploader_helper.rb +79 -0
- data/lib/kit/models/authorized.rb +188 -0
- data/lib/kit/models/authorized_object.rb +167 -0
- data/lib/kit/models/default_permissions.yml +29 -0
- data/lib/kit/models/file_uploader.rb +26 -0
- data/lib/kit/models/micelaneous.rb +1 -0
- data/lib/kit/models/role.rb +88 -0
- data/lib/kit/models_after.rb +27 -0
- data/lib/kit/mongoid.rb +22 -0
- data/lib/kit/mongoid/rad_micelaneous.rb +36 -0
- data/lib/kit/mongoid/text_processor.rb +44 -0
- data/lib/kit/spec.rb +77 -0
- data/lib/kit/spec/items_controller_crud.rb +64 -0
- data/lib/kit/support.rb +14 -0
- data/lib/kit/support/string.rb +6 -0
- data/lib/kit/tasks.rb +18 -0
- data/lib/kit/text_utils.rb +43 -0
- data/lib/kit/text_utils/code_highlighter.rb +58 -0
- data/lib/kit/text_utils/custom_markdown.rb +90 -0
- data/lib/kit/text_utils/ensure_utf.rb +8 -0
- data/lib/kit/text_utils/github_flavoured_markdown.rb +32 -0
- data/lib/kit/text_utils/html_sanitizer.rb +89 -0
- data/lib/kit/text_utils/image_box.rb +35 -0
- data/lib/kit/text_utils/markup.rb +43 -0
- data/lib/kit/text_utils/processor.rb +25 -0
- data/lib/kit/text_utils/tag_shortcuts.rb +14 -0
- data/lib/kit/text_utils/truncate.rb +29 -0
- data/lib/kit/text_utils/truncator.rb +15 -0
- data/lib/kit/text_utils/urls.rb +13 -0
- data/readme.md +10 -0
- data/spec/controller/authorization_spec.rb +149 -0
- data/spec/controller/comments_spec.rb +54 -0
- data/spec/controller/items_spec.rb +45 -0
- data/spec/models/attachments_spec.rb +24 -0
- data/spec/models/attachments_spec/a.txt +1 -0
- data/spec/models/attachments_uploader_helper_spec.rb +108 -0
- data/spec/models/attachments_uploader_helper_spec/v1/a.txt +1 -0
- data/spec/models/attachments_uploader_helper_spec/v1/b.txt +1 -0
- data/spec/models/attachments_uploader_helper_spec/v2/a.txt +1 -0
- data/spec/models/authorization_spec.rb +77 -0
- data/spec/models/authorized_object_spec.rb +254 -0
- data/spec/models/comments_spec.rb +1 -0
- data/spec/models/item_spec.rb +51 -0
- data/spec/models/role_spec.rb +17 -0
- data/spec/models/tags_spec.rb +44 -0
- data/spec/models/uploader_spec.rb +37 -0
- 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
- data/spec/mongoid/basic_spec.rb +36 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/spec_helper/controller.rb +9 -0
- data/spec/spec_helper/factories.rb +24 -0
- data/spec/spec_helper/user.rb +17 -0
- data/spec/utils/text_utils_spec.rb +280 -0
- 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,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
|