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,167 @@
|
|
1
|
+
module Mongoid::AuthorizedObject
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
field :owner_name,
|
6
|
+
type: String,
|
7
|
+
default: lambda{rad.user? ? rad.user.name : nil},
|
8
|
+
protected: true
|
9
|
+
attr_protected :owner
|
10
|
+
|
11
|
+
field :collaborators,
|
12
|
+
type: Array,
|
13
|
+
default: [],
|
14
|
+
protected: true
|
15
|
+
|
16
|
+
# Contains the role and all upper roles. So complex becouse we need it in indexes.
|
17
|
+
field :viewers,
|
18
|
+
type: Array,
|
19
|
+
default: lambda{(
|
20
|
+
(rad.user? ? ['manager', "user:#{rad.user.name}"] : ['manager']) +
|
21
|
+
Array.wrap(rad.config.default_viewers)
|
22
|
+
).uniq.sort},
|
23
|
+
protected: true
|
24
|
+
|
25
|
+
validates_presence_of :owner_name
|
26
|
+
validate :validate_viewers
|
27
|
+
validate :validate_collaborators
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Owner
|
32
|
+
#
|
33
|
+
def owner
|
34
|
+
return nil if owner_name.blank?
|
35
|
+
cache[:owner] ||= Models::User.by_name!(owner_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def owner= user
|
39
|
+
user.must_be.an Models::User
|
40
|
+
cache[:owner] = user
|
41
|
+
self.owner_name = user.name
|
42
|
+
user
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO3 update it later, MM uses public API to unmarshal object
|
46
|
+
# http://groups.google.com/group/mongomapper/browse_thread/thread/ab34457e0ba9c472#
|
47
|
+
def owner_name= name
|
48
|
+
owner_role = "user:#{name}"
|
49
|
+
old_owner_role = "user:#{owner_name}"
|
50
|
+
|
51
|
+
unless viewers.include? owner_role
|
52
|
+
viewers.delete old_owner_role
|
53
|
+
viewers << owner_role
|
54
|
+
viewers.sort!
|
55
|
+
end
|
56
|
+
|
57
|
+
# write_attribute :owner_name, name
|
58
|
+
super name
|
59
|
+
clear_cache
|
60
|
+
owner_name
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Viewers and Collaborators
|
65
|
+
#
|
66
|
+
def add_viewer role
|
67
|
+
role = role.to_s
|
68
|
+
should_be_valid_user_input_role role
|
69
|
+
|
70
|
+
return if viewers.include? role
|
71
|
+
|
72
|
+
roles = viewers
|
73
|
+
roles << role
|
74
|
+
roles = Role.denormalize_to_higher_roles roles
|
75
|
+
roles << 'manager' unless roles.include? 'manager'
|
76
|
+
self.viewers = roles.sort
|
77
|
+
viewers
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_viewer role
|
81
|
+
role = role.to_s
|
82
|
+
should_be_valid_user_input_role role
|
83
|
+
|
84
|
+
return unless viewers.include? role
|
85
|
+
|
86
|
+
roles = viewers
|
87
|
+
Role.denormalize_to_higher_roles([role]).each do |r|
|
88
|
+
roles.delete r
|
89
|
+
end
|
90
|
+
roles << 'manager' unless roles.include? 'manager'
|
91
|
+
self.viewers = roles.sort
|
92
|
+
|
93
|
+
remove_collaborator role
|
94
|
+
|
95
|
+
viewers
|
96
|
+
end
|
97
|
+
|
98
|
+
def minor_viewers
|
99
|
+
unless minor_viewers = cache[:minor_viewers]
|
100
|
+
viewers = self.viewers.clone
|
101
|
+
viewers.delete 'manager'
|
102
|
+
minor_viewers = Role.minor_roles viewers
|
103
|
+
cache[:minor_viewers] = minor_viewers
|
104
|
+
end
|
105
|
+
minor_viewers
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_collaborator role
|
109
|
+
role = role.to_s
|
110
|
+
should_be_valid_user_input_role role
|
111
|
+
return if collaborators.include? role
|
112
|
+
collaborators = self.collaborators.clone
|
113
|
+
collaborators << role
|
114
|
+
self.collaborators = collaborators
|
115
|
+
|
116
|
+
add_viewer role
|
117
|
+
|
118
|
+
collaborators
|
119
|
+
end
|
120
|
+
|
121
|
+
def remove_collaborator role
|
122
|
+
role = role.to_s
|
123
|
+
should_be_valid_user_input_role role
|
124
|
+
collaborators.delete role
|
125
|
+
collaborators
|
126
|
+
end
|
127
|
+
|
128
|
+
def normalized_collaborators
|
129
|
+
unless normalized_collaborators = cache[:normalized_collaborators]
|
130
|
+
normalized_collaborators = Role.denormalize_to_higher_roles collaborators
|
131
|
+
normalized_collaborators << "user:#{owner_name}"
|
132
|
+
normalized_collaborators.sort!
|
133
|
+
cache[:normalized_collaborators] = normalized_collaborators
|
134
|
+
end
|
135
|
+
normalized_collaborators
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
#
|
140
|
+
# Special Permissions
|
141
|
+
#
|
142
|
+
def able_view? user
|
143
|
+
user.roles.any?{|role| viewers.include? role}
|
144
|
+
end
|
145
|
+
|
146
|
+
def able_update? user
|
147
|
+
user.roles.any?{|role| normalized_collaborators.include? role}
|
148
|
+
end
|
149
|
+
|
150
|
+
protected
|
151
|
+
def should_be_valid_user_input_role role
|
152
|
+
role.must_not == 'manager'
|
153
|
+
role.must_not == "user:#{owner_name}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_viewers
|
157
|
+
viewers.must == viewers.uniq
|
158
|
+
|
159
|
+
viewers.must.include 'manager' # always
|
160
|
+
viewers.must.include "user:#{owner_name}"
|
161
|
+
end
|
162
|
+
|
163
|
+
def validate_collaborators
|
164
|
+
collaborators.must_not.include "user:#{owner_name}"
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# General
|
2
|
+
view: [] #anonymous, registered
|
3
|
+
|
4
|
+
# Administration
|
5
|
+
administration: [admin]
|
6
|
+
|
7
|
+
# Authorization
|
8
|
+
add_admin_role: []
|
9
|
+
add_custom_role: [manager]
|
10
|
+
add_manager_role: []
|
11
|
+
add_member_role: [manager]
|
12
|
+
remove_admin_role: []
|
13
|
+
remove_custom_role: [manager]
|
14
|
+
remove_manager_role: []
|
15
|
+
remove_member_role: [manager]
|
16
|
+
update_access: [manager, owner]
|
17
|
+
|
18
|
+
# User Management
|
19
|
+
update_profile: [owner]
|
20
|
+
|
21
|
+
# Items
|
22
|
+
create: [member]
|
23
|
+
# update: [manager, owner]
|
24
|
+
destroy: [manager, owner]
|
25
|
+
|
26
|
+
# Comments
|
27
|
+
create_comment: [registered]
|
28
|
+
update_comment: [manager, owner]
|
29
|
+
destroy_comment: [manager, owner]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'carrierwave/processing/mini_magick'
|
2
|
+
|
3
|
+
class Models::FileUploader < CarrierWave::Uploader::Base
|
4
|
+
include CarrierWave::MiniMagick
|
5
|
+
|
6
|
+
storage rad.config.fs_type
|
7
|
+
|
8
|
+
# def sanitize_regexp
|
9
|
+
# /[^[:word:]\.\-\+\s_]/i
|
10
|
+
# end
|
11
|
+
|
12
|
+
def file_path
|
13
|
+
"#{rad.config.fs_prefix}/system/#{model.class.model_name.underscore}/#{model.id}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def store_dir
|
17
|
+
"#{root}#{file_path}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def extension_white_list
|
21
|
+
[/.*/]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cache_dir; rad.config.fs_cache_path end
|
25
|
+
def root; rad.config.fs_path end
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
STRONG_NAME = /\A[a-z_][a-z_0-9]*\Z/
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class Role
|
2
|
+
ORDERED_ROLES = %w{manager member user}.freeze
|
3
|
+
SYSTEM_ROLES = %w{admin anonymous manager member owner registered user}.sort.freeze
|
4
|
+
PRESERVED_USER_NAMES = SYSTEM_ROLES
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def normalize_roles roles
|
9
|
+
ordinary_roles, ordered_roles = split roles
|
10
|
+
ordinary_roles << lower_role(ordered_roles)
|
11
|
+
ordinary_roles.sort
|
12
|
+
end
|
13
|
+
|
14
|
+
def denormalize_to_higher_roles roles
|
15
|
+
ordinary_roles, ordered_roles = split roles
|
16
|
+
ordinary_roles.push *higher_roles(lower_role(ordered_roles))
|
17
|
+
ordinary_roles.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
def denormalize_to_lower_roles roles
|
21
|
+
ordinary_roles, ordered_roles = split roles
|
22
|
+
ordinary_roles.push *lower_roles(higher_role(ordered_roles))
|
23
|
+
ordinary_roles.sort
|
24
|
+
end
|
25
|
+
|
26
|
+
def higher_role roles
|
27
|
+
ORDERED_ROLES.each do |role|
|
28
|
+
return role if roles.include? role
|
29
|
+
end
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def lower_role roles
|
34
|
+
ORDERED_ROLES.reverse.each do |role|
|
35
|
+
return role if roles.include? role
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def major_roles roles
|
41
|
+
major_roles = roles.select{|role| !SYSTEM_ROLES.include?(role)}
|
42
|
+
if higher_role = higher_role(roles)
|
43
|
+
major_roles << higher_role
|
44
|
+
end
|
45
|
+
major_roles.sort
|
46
|
+
end
|
47
|
+
|
48
|
+
def minor_roles roles
|
49
|
+
minor_roles = roles.select{|role| !SYSTEM_ROLES.include?(role)}
|
50
|
+
if lower_role = lower_role(roles)
|
51
|
+
minor_roles << lower_role
|
52
|
+
end
|
53
|
+
minor_roles.sort
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def split roles
|
58
|
+
ordinary_roles = []
|
59
|
+
ordered_roles = []
|
60
|
+
|
61
|
+
roles.collect do |role|
|
62
|
+
if ORDERED_ROLES.include? role
|
63
|
+
ordered_roles << role
|
64
|
+
else
|
65
|
+
ordinary_roles << role
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
[ordinary_roles, ordered_roles]
|
70
|
+
end
|
71
|
+
|
72
|
+
def lower_roles role
|
73
|
+
return [] if role.nil?
|
74
|
+
|
75
|
+
role.must_be.in ORDERED_ROLES
|
76
|
+
index = ORDERED_ROLES.index role
|
77
|
+
ORDERED_ROLES[index..-1]
|
78
|
+
end
|
79
|
+
|
80
|
+
def higher_roles role
|
81
|
+
return [] if role.nil?
|
82
|
+
|
83
|
+
role.must_be.in ORDERED_ROLES
|
84
|
+
index = ORDERED_ROLES.index role
|
85
|
+
ORDERED_ROLES[0..index]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# use database config if provided
|
2
|
+
if rad.models.config
|
3
|
+
b = lambda do
|
4
|
+
Mongoid.configure do |config|
|
5
|
+
config.logger = rad.logger
|
6
|
+
end
|
7
|
+
Mongoid.from_hash rad.models.config
|
8
|
+
end
|
9
|
+
|
10
|
+
# hiding MongoDB connecting messages
|
11
|
+
rad.logger.respond_to?(:silence) ? rad.logger.silence(&b) : b.call
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
%w(
|
16
|
+
micelaneous
|
17
|
+
role
|
18
|
+
authorized
|
19
|
+
authorized_object
|
20
|
+
file_uploader
|
21
|
+
attachments_uploader_helper
|
22
|
+
attachment_uploader
|
23
|
+
).each{|n| require "kit/models/#{n}"}
|
24
|
+
|
25
|
+
Mongoid::Document.class_eval do
|
26
|
+
include Mongoid::AttachmentsUploaderHelper
|
27
|
+
end
|
data/lib/kit/mongoid.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'mongoid_misc'
|
2
|
+
require 'carrierwave_ext'
|
3
|
+
require 'rad'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Attribute protection
|
7
|
+
#
|
8
|
+
Mongoid::Document.included do
|
9
|
+
attr_protected :id, :_id, :_type, :created_at, :updated_at
|
10
|
+
end
|
11
|
+
|
12
|
+
module Models
|
13
|
+
end
|
14
|
+
|
15
|
+
%w(
|
16
|
+
text_processor
|
17
|
+
rad_micelaneous
|
18
|
+
).each{|n| require "kit/mongoid/#{n}"}
|
19
|
+
|
20
|
+
(rad.extension(:mm_plugins){[]} + [Mongoid::RadMicelaneous]).each do |plugin|
|
21
|
+
Mongoid::Document.include plugin
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Mongoid::RadMicelaneous
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
delegate :t, to: I18n
|
5
|
+
|
6
|
+
def to_rson options = {}
|
7
|
+
with_errors = if options.include?('errors')
|
8
|
+
options.delete 'errors'
|
9
|
+
elsif options.include?(:errors)
|
10
|
+
options.delete :errors
|
11
|
+
else
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# standard MongoMaper as_json conversion
|
16
|
+
hash = as_json(options)
|
17
|
+
|
18
|
+
# MongoMaper fix
|
19
|
+
hash['id'] = hash.delete('_id').to_s if hash.include? '_id'
|
20
|
+
|
21
|
+
# adding errors
|
22
|
+
if with_errors
|
23
|
+
errors = {}
|
24
|
+
errors.each do |name, list|
|
25
|
+
errors[name.to_s] = list
|
26
|
+
end
|
27
|
+
hash['errors'] = errors unless errors.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
delegate :t, to: I18n
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Mongoid::TextProcessor
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def markup_field attr_name, opt = {}
|
6
|
+
attr_name = attr_name.to_s
|
7
|
+
opt = opt.to_openobject
|
8
|
+
original_attr_name = "original_#{attr_name}"
|
9
|
+
|
10
|
+
field original_attr_name, type: String, default: ''
|
11
|
+
field attr_name, type: String, protected: true, default: '' unless fields.include? attr_name
|
12
|
+
|
13
|
+
validates_presence_of attr_name, original_attr_name if opt.required?
|
14
|
+
|
15
|
+
alias_method "#{attr_name}_without_markup=", "#{attr_name}="
|
16
|
+
alias_method "#{original_attr_name}_without_markup=", "#{original_attr_name}="
|
17
|
+
|
18
|
+
define_method "#{attr_name}=" do |value|
|
19
|
+
send "#{original_attr_name}_without_markup=", value
|
20
|
+
send "#{attr_name}_without_markup=", value
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method "#{original_attr_name}=" do |value|
|
24
|
+
send "#{original_attr_name}_without_markup=", value
|
25
|
+
send "#{attr_name}_without_markup=", Rad::TextUtils.markup(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method "#{attr_name}_as_text" do
|
29
|
+
value = send(attr_name)
|
30
|
+
return "" if value.blank?
|
31
|
+
Nokogiri::XML(value).content
|
32
|
+
end
|
33
|
+
|
34
|
+
ce_method_name = "copy_errors_for_#{attr_name}"
|
35
|
+
define_method ce_method_name do
|
36
|
+
if !errors.include?(original_attr_name) and errors.include?(attr_name)
|
37
|
+
errors.add original_attr_name, errors[attr_name]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
after_validation ce_method_name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|