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,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
@@ -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