fesplugas-typus 0.9.0

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 (154) hide show
  1. data/.gitignore +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +80 -0
  4. data/Rakefile +61 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/master_controller.rb +324 -0
  7. data/app/controllers/typus_controller.rb +127 -0
  8. data/app/helpers/admin/form_helper.rb +351 -0
  9. data/app/helpers/admin/master_helper.rb +99 -0
  10. data/app/helpers/admin/public_helper.rb +24 -0
  11. data/app/helpers/admin/sidebar_helper.rb +259 -0
  12. data/app/helpers/admin/table_helper.rb +227 -0
  13. data/app/helpers/typus_helper.rb +169 -0
  14. data/app/models/typus_mailer.rb +14 -0
  15. data/app/models/typus_user.rb +5 -0
  16. data/app/views/admin/dashboard/_sidebar.html.erb +9 -0
  17. data/app/views/admin/resources/edit.html.erb +29 -0
  18. data/app/views/admin/resources/index.html.erb +28 -0
  19. data/app/views/admin/resources/new.html.erb +27 -0
  20. data/app/views/admin/resources/show.html.erb +21 -0
  21. data/app/views/admin/shared/_footer.html.erb +1 -0
  22. data/app/views/admin/shared/_pagination.html.erb +28 -0
  23. data/app/views/layouts/admin.html.erb +72 -0
  24. data/app/views/layouts/typus.html.erb +29 -0
  25. data/app/views/typus/dashboard.html.erb +13 -0
  26. data/app/views/typus/recover_password.html.erb +7 -0
  27. data/app/views/typus/reset_password.html.erb +13 -0
  28. data/app/views/typus/sign_in.html.erb +9 -0
  29. data/app/views/typus/sign_up.html.erb +7 -0
  30. data/app/views/typus_mailer/reset_password_link.erb +11 -0
  31. data/config/locales/es.yml +106 -0
  32. data/config/locales/pt-BR.yml +108 -0
  33. data/config/locales/typus_hacks.yml +14 -0
  34. data/config/routes.rb +14 -0
  35. data/generators/typus/templates/config/initializers/typus.rb +27 -0
  36. data/generators/typus/templates/config/typus/application.yml +45 -0
  37. data/generators/typus/templates/config/typus/application_roles.yml +23 -0
  38. data/generators/typus/templates/config/typus/typus.yml +14 -0
  39. data/generators/typus/templates/config/typus/typus_roles.yml +2 -0
  40. data/generators/typus/templates/db/create_typus_users.rb +21 -0
  41. data/generators/typus/templates/public/images/admin/arrow_down.gif +0 -0
  42. data/generators/typus/templates/public/images/admin/arrow_up.gif +0 -0
  43. data/generators/typus/templates/public/images/admin/spinner.gif +0 -0
  44. data/generators/typus/templates/public/images/admin/status_false.gif +0 -0
  45. data/generators/typus/templates/public/images/admin/status_true.gif +0 -0
  46. data/generators/typus/templates/public/images/admin/trash.gif +0 -0
  47. data/generators/typus/templates/public/javascripts/admin/application.js +14 -0
  48. data/generators/typus/templates/public/stylesheets/admin/reset.css +68 -0
  49. data/generators/typus/templates/public/stylesheets/admin/screen.css +709 -0
  50. data/generators/typus/typus_generator.rb +141 -0
  51. data/generators/typus_update_schema_to_01/templates/config/typus.yml +14 -0
  52. data/generators/typus_update_schema_to_01/templates/migration.rb +11 -0
  53. data/generators/typus_update_schema_to_01/typus_update_schema_to_01_generator.rb +19 -0
  54. data/init.rb +19 -0
  55. data/lib/typus/active_record.rb +298 -0
  56. data/lib/typus/authentication.rb +155 -0
  57. data/lib/typus/configuration.rb +92 -0
  58. data/lib/typus/format.rb +56 -0
  59. data/lib/typus/generator.rb +173 -0
  60. data/lib/typus/hash.rb +10 -0
  61. data/lib/typus/locale.rb +17 -0
  62. data/lib/typus/object.rb +22 -0
  63. data/lib/typus/quick_edit.rb +33 -0
  64. data/lib/typus/reloader.rb +17 -0
  65. data/lib/typus/string.rb +11 -0
  66. data/lib/typus/user.rb +137 -0
  67. data/lib/typus.rb +133 -0
  68. data/lib/vendor/active_record.rb +15 -0
  69. data/lib/vendor/paginator.rb +143 -0
  70. data/tasks/typus_tasks.rake +26 -0
  71. data/test/config/broken/application.yml +68 -0
  72. data/test/config/broken/application_roles.yml +20 -0
  73. data/test/config/broken/empty.yml +0 -0
  74. data/test/config/broken/empty_roles.yml +0 -0
  75. data/test/config/broken/undefined.yml +3 -0
  76. data/test/config/broken/undefined_roles.yml +6 -0
  77. data/test/config/default/typus.yml +14 -0
  78. data/test/config/default/typus_roles.yml +2 -0
  79. data/test/config/empty/empty_01.yml +0 -0
  80. data/test/config/empty/empty_01_roles.yml +0 -0
  81. data/test/config/empty/empty_02.yml +0 -0
  82. data/test/config/empty/empty_02_roles.yml +0 -0
  83. data/test/config/locales/es.yml +10 -0
  84. data/test/config/ordered/001_roles.yml +2 -0
  85. data/test/config/ordered/002_roles.yml +2 -0
  86. data/test/config/unordered/app_one_roles.yml +2 -0
  87. data/test/config/unordered/app_two_roles.yml +2 -0
  88. data/test/config/working/application.yml +67 -0
  89. data/test/config/working/application_roles.yml +22 -0
  90. data/test/config/working/typus.yml +14 -0
  91. data/test/config/working/typus_roles.yml +2 -0
  92. data/test/fixtures/app/controllers/admin/assets_controller.rb +2 -0
  93. data/test/fixtures/app/controllers/admin/categories_controller.rb +2 -0
  94. data/test/fixtures/app/controllers/admin/comments_controller.rb +2 -0
  95. data/test/fixtures/app/controllers/admin/pages_controller.rb +2 -0
  96. data/test/fixtures/app/controllers/admin/posts_controller.rb +2 -0
  97. data/test/fixtures/app/controllers/admin/status_controller.rb +6 -0
  98. data/test/fixtures/app/controllers/admin/typus_users_controller.rb +2 -0
  99. data/test/fixtures/app/controllers/admin/watch_dog_controller.rb +6 -0
  100. data/test/fixtures/app/views/admin/comments/_edit_bottom.html.erb +1 -0
  101. data/test/fixtures/app/views/admin/comments/_edit_sidebar.html.erb +1 -0
  102. data/test/fixtures/app/views/admin/comments/_edit_top.html.erb +1 -0
  103. data/test/fixtures/app/views/admin/comments/_index_bottom.html.erb +1 -0
  104. data/test/fixtures/app/views/admin/comments/_index_sidebar.html.erb +1 -0
  105. data/test/fixtures/app/views/admin/comments/_index_top.html.erb +1 -0
  106. data/test/fixtures/app/views/admin/comments/_new_bottom.html.erb +1 -0
  107. data/test/fixtures/app/views/admin/comments/_new_sidebar.html.erb +1 -0
  108. data/test/fixtures/app/views/admin/comments/_new_top.html.erb +1 -0
  109. data/test/fixtures/app/views/admin/comments/_show_bottom.html.erb +1 -0
  110. data/test/fixtures/app/views/admin/comments/_show_sidebar.html.erb +1 -0
  111. data/test/fixtures/app/views/admin/comments/_show_top.html.erb +1 -0
  112. data/test/fixtures/app/views/admin/dashboard/_bottom.html.erb +1 -0
  113. data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
  114. data/test/fixtures/app/views/admin/dashboard/_top.html.erb +1 -0
  115. data/test/fixtures/app/views/admin/shared/_footer.html.erb +1 -0
  116. data/test/fixtures/app/views/admin/status/index.html.erb +1 -0
  117. data/test/fixtures/app/views/admin/templates/_datepicker.html.erb +1 -0
  118. data/test/fixtures/assets.yml +11 -0
  119. data/test/fixtures/categories.yml +14 -0
  120. data/test/fixtures/comments.yml +27 -0
  121. data/test/fixtures/pages.yml +41 -0
  122. data/test/fixtures/posts.yml +37 -0
  123. data/test/fixtures/typus_users.yml +54 -0
  124. data/test/functional/admin/assets_controller_test.rb +57 -0
  125. data/test/functional/admin/categories_controller_test.rb +106 -0
  126. data/test/functional/admin/comments_controller_test.rb +121 -0
  127. data/test/functional/admin/master_controller_test.rb +5 -0
  128. data/test/functional/admin/posts_controller_test.rb +278 -0
  129. data/test/functional/admin/status_controller_test.rb +43 -0
  130. data/test/functional/admin/typus_users_controller_test.rb +239 -0
  131. data/test/functional/typus_controller_test.rb +315 -0
  132. data/test/helper.rb +51 -0
  133. data/test/helpers/admin/form_helper_test.rb +316 -0
  134. data/test/helpers/admin/master_helper_test.rb +65 -0
  135. data/test/helpers/admin/public_helper_test.rb +22 -0
  136. data/test/helpers/admin/sidebar_helper_test.rb +351 -0
  137. data/test/helpers/admin/table_helper_test.rb +255 -0
  138. data/test/helpers/typus_helper_test.rb +106 -0
  139. data/test/lib/active_record_test.rb +372 -0
  140. data/test/lib/configuration_test.rb +91 -0
  141. data/test/lib/hash_test.rb +11 -0
  142. data/test/lib/routes_test.rb +82 -0
  143. data/test/lib/string_test.rb +25 -0
  144. data/test/lib/typus_test.rb +105 -0
  145. data/test/models.rb +51 -0
  146. data/test/schema.rb +64 -0
  147. data/test/unit/typus_mailer_test.rb +33 -0
  148. data/test/unit/typus_test.rb +17 -0
  149. data/test/unit/typus_user_roles_test.rb +90 -0
  150. data/test/unit/typus_user_test.rb +177 -0
  151. data/test/vendor/active_record_test.rb +18 -0
  152. data/test/vendor/paginator_test.rb +138 -0
  153. data/typus.gemspec +225 -0
  154. metadata +241 -0
@@ -0,0 +1,141 @@
1
+ class TypusGenerator < Rails::Generator::Base
2
+
3
+ def manifest
4
+
5
+ record do |m|
6
+
7
+ ##
8
+ # Default name for our application.
9
+ #
10
+
11
+ application = Rails.root.basename
12
+
13
+ ##
14
+ # To create <tt>application.yml</tt> and <tt>application_roles.yml</tt> detect
15
+ # available AR models on the application.
16
+ #
17
+
18
+ models = Dir["#{Rails.root}/app/models/*.rb"].collect { |x| File.basename(x) }
19
+ ar_models = []
20
+
21
+ models.each do |model|
22
+ class_name = model.sub(/\.rb$/,'').classify
23
+ begin
24
+ klass = class_name.constantize
25
+ ar_models << klass if klass.superclass.equal?(ActiveRecord::Base)
26
+ rescue Exception => error
27
+ puts "=> [typus] #{error.message} on '#{class_name}'."
28
+ end
29
+ end
30
+
31
+ ##
32
+ # Configuration files
33
+ #
34
+
35
+ config_folder = Typus::Configuration.options[:config_folder]
36
+ folder = "#{Rails.root}/#{config_folder}"
37
+ Dir.mkdir(folder) unless File.directory?(folder)
38
+
39
+ configuration = { :base => '', :roles => '' }
40
+
41
+ ar_models.each do |model|
42
+
43
+ # By default we don't want to show in our lists text fields and created_at
44
+ # and updated_at attributes.
45
+ list = model.columns.reject { |c| c.sql_type == 'text' || %w( created_at updated_at ).include?(c.name) }.map(&:name)
46
+
47
+ # By default we don't want to show in our forms created_at and updated_at
48
+ # attributes.
49
+ form = model.columns.reject { |c| %w( id created_at updated_at ).include?(c.name) }.map(&:name)
50
+
51
+ # By default we want to show all model columns in the show action.
52
+ show = model.columns.map(&:name)
53
+
54
+ # Detect relationships using reflection and remove the _id part from
55
+ # attributes when relationships is defined in ActiveRecord.
56
+ list.each do |i|
57
+ if i.include?('_id')
58
+ assoc_name = model.reflect_on_association(i.gsub(/_id/, '').to_sym).macro rescue nil
59
+ i.gsub!(/_id/, '') if assoc_name == :belongs_to
60
+ end
61
+ end
62
+
63
+ # Detect relationships using reflection.
64
+ relationships = [ :belongs_to, :has_and_belongs_to_many, :has_many, :has_one ].map do |relationship|
65
+ model.reflect_on_all_associations(relationship).map { |i| i.name.to_s }
66
+ end.flatten.sort
67
+
68
+ configuration[:base] << <<-CODE
69
+ #{model}:
70
+ fields:
71
+ list: #{list.join(', ')}
72
+ form: #{form.join(', ')}
73
+ show: #{show.join(', ')}
74
+ relationship:
75
+ options:
76
+ auto_generated:
77
+ read_only:
78
+ selectors:
79
+ actions:
80
+ index:
81
+ edit:
82
+ export:
83
+ order_by:
84
+ relationships: #{relationships.join(', ')}
85
+ filters:
86
+ search:
87
+ application: #{application}
88
+ description:
89
+
90
+ CODE
91
+
92
+ configuration[:roles] << <<-CODE
93
+ #{model}: create, read, update, delete
94
+ CODE
95
+
96
+ end
97
+
98
+ Dir["#{Typus.root}/generators/typus/templates/config/typus/*"].each do |f|
99
+ base = File.basename(f)
100
+ m.template "config/typus/#{base}", "#{config_folder}/#{base}",
101
+ :assigns => { :configuration => configuration }
102
+ end
103
+
104
+ ##
105
+ # Initializers
106
+ #
107
+
108
+ m.template 'config/initializers/typus.rb', 'config/initializers/typus.rb',
109
+ :assigns => { :application => application }
110
+
111
+ ##
112
+ # Public folders
113
+ #
114
+
115
+ [ "#{Rails.root}/public/stylesheets/admin",
116
+ "#{Rails.root}/public/javascripts/admin",
117
+ "#{Rails.root}/public/images/admin" ].each do |folder|
118
+ Dir.mkdir(folder) unless File.directory?(folder)
119
+ end
120
+
121
+ m.file 'public/stylesheets/admin/screen.css', 'public/stylesheets/admin/screen.css'
122
+ m.file 'public/stylesheets/admin/reset.css', 'public/stylesheets/admin/reset.css'
123
+ m.file 'public/javascripts/admin/application.js', 'public/javascripts/admin/application.js'
124
+
125
+ Dir["#{Typus.root}/generators/typus/templates/public/images/admin/*"].each do |f|
126
+ base = File.basename(f)
127
+ m.file "public/images/admin/#{base}", "public/images/admin/#{base}"
128
+ end
129
+
130
+ ##
131
+ # Migration file
132
+ #
133
+
134
+ m.migration_template 'db/create_typus_users.rb', 'db/migrate',
135
+ { :migration_file_name => 'create_typus_users' }
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,14 @@
1
+ TypusUser:
2
+ fields:
3
+ list: email, role, status
4
+ form: first_name, last_name, role, email, password, password_confirmation
5
+ options:
6
+ selectors: role
7
+ booleans:
8
+ status: Active, Inactive
9
+ filters: status, role
10
+ search: first_name, last_name, email, role
11
+ application: Typus
12
+ description: System Users Administration
13
+ options:
14
+ icon_on_boolean: false
@@ -0,0 +1,11 @@
1
+ class UpdateTypusSchemaTo01 < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ rename_column :typus_users, :roles, :role
5
+ end
6
+
7
+ def self.down
8
+ rename_column :typus_users, :role, :roles
9
+ end
10
+
11
+ end
@@ -0,0 +1,19 @@
1
+ class TypusUpdateSchemaTo01Generator < Rails::Generator::Base
2
+
3
+ def manifest
4
+
5
+ record do |m|
6
+
7
+ config_folder = Typus::Configuration.options[:config_folder]
8
+ Dir["#{Typus.root}/generators/typus_update_schema_to_01/templates/config/*"].each do |f|
9
+ base = File.basename(f)
10
+ m.template "config/#{base}", "#{config_folder}/#{base}"
11
+ end
12
+
13
+ m.migration_template 'migration.rb', 'db/migrate', { :migration_file_name => 'update_typus_schema_to_01' }
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
data/init.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'typus'
2
+ require 'sha1'
3
+
4
+ if Typus.testing?
5
+ Typus::Configuration.options[:config_folder] = 'vendor/plugins/typus/test/config/working'
6
+ end
7
+
8
+ ##
9
+ # Typus.enable and run the generator unless we are testing the plugin.
10
+ # Do not Typus.enable or generate files if we are running a rails
11
+ # generator.
12
+ #
13
+
14
+ scripts = %w( script/generate script/destroy )
15
+
16
+ unless scripts.include?($0)
17
+ Typus.enable
18
+ Typus.generator unless Typus.testing?
19
+ end
@@ -0,0 +1,298 @@
1
+ module Typus
2
+
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ ##
10
+ # Return model fields as a OrderedHash
11
+ #
12
+ def model_fields
13
+ hash = ActiveSupport::OrderedHash.new
14
+ columns.map { |u| hash[u.name.to_sym] = u.type.to_sym }
15
+ return hash
16
+ end
17
+
18
+ def model_relationships
19
+ hash = ActiveSupport::OrderedHash.new
20
+ reflect_on_all_associations.map { |i| hash[i.name] = i.macro }
21
+ return hash
22
+ end
23
+
24
+ ##
25
+ # Form and list fields
26
+ #
27
+ def typus_fields_for(filter)
28
+
29
+ fields_with_type = ActiveSupport::OrderedHash.new
30
+
31
+ begin
32
+ fields = Typus::Configuration.config[name]['fields'][filter.to_s]
33
+ fields = fields.split(', ').collect { |f| f.to_sym }
34
+ rescue
35
+ return [] if filter == 'list'
36
+ filter = 'list'
37
+ retry
38
+ end
39
+
40
+ begin
41
+
42
+ fields.each do |field|
43
+
44
+ attribute_type = model_fields[field]
45
+
46
+ # Custom field_type depending on the attribute name.
47
+ case field.to_s
48
+ when 'parent_id': attribute_type = :tree
49
+ when /file_name/: attribute_type = :file
50
+ when /password/: attribute_type = :password
51
+ when 'position': attribute_type = :position
52
+ when /\?/: attribute_type = :boolean
53
+ end
54
+
55
+ if reflect_on_association(field)
56
+ attribute_type = reflect_on_association(field).macro
57
+ end
58
+
59
+ if typus_field_options_for(:selectors).include?(field)
60
+ attribute_type = :selector
61
+ end
62
+
63
+ # And finally insert the field and the attribute_type
64
+ # into the fields_with_type ordered hash.
65
+ fields_with_type[field.to_s] = attribute_type
66
+
67
+ end
68
+
69
+ rescue
70
+ fields = Typus::Configuration.config[name]['fields']['list'].split(', ')
71
+ retry
72
+ end
73
+
74
+ return fields_with_type
75
+
76
+ end
77
+
78
+ ##
79
+ # Typus sidebar filters.
80
+ #
81
+ def typus_filters
82
+
83
+ fields_with_type = ActiveSupport::OrderedHash.new
84
+
85
+ data = Typus::Configuration.config[name]['filters']
86
+ return [] unless data
87
+ fields = data.split(', ').collect { |i| i.to_sym }
88
+
89
+ fields.each do |field|
90
+ attribute_type = model_fields[field.to_sym]
91
+ if reflect_on_association(field.to_sym)
92
+ attribute_type = reflect_on_association(field.to_sym).macro
93
+ end
94
+ fields_with_type[field.to_s] = attribute_type
95
+ end
96
+
97
+ return fields_with_type
98
+
99
+ end
100
+
101
+ ##
102
+ # Extended actions for this model on Typus.
103
+ #
104
+ def typus_actions_for(filter)
105
+ Typus::Configuration.config[name]['actions'][filter.to_s].split(', ')
106
+ rescue
107
+ []
108
+ end
109
+
110
+ ##
111
+ # Used for +search+, +relationships+
112
+ #
113
+ def typus_defaults_for(filter)
114
+ data = Typus::Configuration.config[name][filter.to_s]
115
+ return (!data.nil?) ? data.split(', ') : []
116
+ end
117
+
118
+ ##
119
+ #
120
+ #
121
+ def typus_field_options_for(filter)
122
+ Typus::Configuration.config[name]['fields']['options'][filter.to_s].split(', ').collect { |i| i.to_sym }
123
+ rescue
124
+ []
125
+ end
126
+
127
+ ##
128
+ # We should be able to overwrite options by model.
129
+ #
130
+ def typus_options_for(filter)
131
+
132
+ data = Typus::Configuration.config[name]
133
+ unless data['options'].nil?
134
+ value = data['options'][filter.to_s] unless data['options'][filter.to_s].nil?
135
+ end
136
+
137
+ return (!value.nil?) ? value : Typus::Configuration.options[filter.to_sym]
138
+
139
+ end
140
+
141
+ def typus_export_formats
142
+ data = Typus::Configuration.config[name]
143
+ !data['export'].nil? ? data['export'].split(', ') : []
144
+ end
145
+
146
+ ##
147
+ # Used for order_by
148
+ #
149
+ def typus_order_by
150
+
151
+ fields = typus_defaults_for(:order_by)
152
+ return "#{table_name}.id ASC" if fields.empty?
153
+
154
+ order = fields.map do |field|
155
+ (field.include?('-')) ? "#{table_name}.#{field.delete('-')} DESC" : "#{table_name}.#{field} ASC"
156
+ end.join(', ')
157
+
158
+ return order
159
+
160
+ end
161
+
162
+ ##
163
+ # We are able to define our own booleans.
164
+ #
165
+ def typus_boolean(attribute = :default)
166
+
167
+ boolean = Typus::Configuration.config[name]['fields']['options']['booleans'][attribute.to_s] rescue nil
168
+ boolean = 'true, false' if boolean.nil?
169
+
170
+ hash = ActiveSupport::OrderedHash.new
171
+
172
+ if boolean.kind_of?(Array)
173
+ hash[:true] = boolean.first.humanize
174
+ hash[:false] = boolean.last.humanize
175
+ else
176
+ hash[:true] = boolean.split(', ').first.humanize
177
+ hash[:false] = boolean.split(', ').last.humanize
178
+ end
179
+
180
+ return hash
181
+
182
+ end
183
+
184
+ ##
185
+ # We are able to define how to display dates on Typus
186
+ #
187
+ def typus_date_format(attribute = :default)
188
+ date_format = Typus::Configuration.config[name]['fields']['options']['date_formats'][attribute.to_s] rescue nil
189
+ date_format = :db if date_format.nil?
190
+ return date_format.to_sym
191
+ end
192
+
193
+ ##
194
+ # We are able to define which template to use to render the attribute
195
+ # within the form
196
+ #
197
+ def typus_template(attribute)
198
+ Typus::Configuration.config[name]['fields']['options']['templates'][attribute.to_s]
199
+ rescue
200
+ nil
201
+ end
202
+
203
+ ##
204
+ # Build conditions
205
+ #
206
+ def build_conditions(params)
207
+
208
+ conditions, joins = merge_conditions, []
209
+
210
+ query_params = params.dup
211
+ %w( action controller ).each { |param| query_params.delete(param) }
212
+
213
+ # If a search is performed.
214
+ if query_params[:search]
215
+ search = typus_defaults_for(:search).map do |s|
216
+ ["LOWER(#{s}) LIKE '%#{query_params[:search].downcase}%'"]
217
+ end
218
+ conditions = merge_conditions(conditions, search.join(' OR '))
219
+ end
220
+
221
+ query_params.each do |key, value|
222
+
223
+ filter_type = model_fields[key.to_sym] || model_relationships[key.to_sym]
224
+
225
+ ##
226
+ # Sidebar filters:
227
+ #
228
+ # - Booleans: true, false
229
+ # - Datetime: today, past_7_days, this_month, this_year
230
+ # - Integer & String: *_id and "selectors" (P.ej. category_id)
231
+ #
232
+ case filter_type
233
+ when :boolean
234
+ condition = { key => (value == 'true') ? true : false }
235
+ conditions = merge_conditions(conditions, condition)
236
+ when :datetime
237
+ interval = case value
238
+ when 'today': Time.today..Time.today.tomorrow
239
+ when 'past_7_days': 6.days.ago.midnight..Time.today.tomorrow
240
+ when 'this_month': Time.today.last_month..Time.today.tomorrow
241
+ when 'this_year': Time.today.last_year..Time.today.tomorrow
242
+ end
243
+ condition = ["#{key} BETWEEN ? AND ?", interval.first.to_s(:db), interval.last.to_s(:db)]
244
+ conditions = merge_conditions(conditions, condition)
245
+ when :integer, :string
246
+ condition = { key => value }
247
+ conditions = merge_conditions(conditions, condition)
248
+ when :has_and_belongs_to_many
249
+ condition = { key => { :id => value } }
250
+ conditions = merge_conditions(conditions, condition)
251
+ joins << key.to_sym
252
+ end
253
+
254
+ end
255
+
256
+ return conditions, joins
257
+
258
+ end
259
+
260
+ end
261
+
262
+ module InstanceMethods
263
+
264
+ def previous_and_next(condition = {}, klass = self.class)
265
+
266
+ previous_conditions = "id < #{id}"
267
+ next_conditions = "id > #{id}"
268
+
269
+ if !condition.empty?
270
+ conditions, joins = klass.build_conditions(condition)
271
+ previous_conditions += " AND #{conditions}"
272
+ next_conditions += " AND #{conditions}"
273
+ end
274
+
275
+ previous_ = klass.find :first,
276
+ :select => [:id],
277
+ :order => "id DESC",
278
+ :conditions => previous_conditions
279
+
280
+ next_ = klass.find :first,
281
+ :select => [:id],
282
+ :order => "id ASC",
283
+ :conditions => next_conditions
284
+
285
+ return previous_, next_
286
+
287
+ end
288
+
289
+ def typus_name
290
+ respond_to?(:name) ? name : "#{self.class}##{id}"
291
+ end
292
+
293
+ end
294
+
295
+ end
296
+
297
+ ActiveRecord::Base.send :include, Typus
298
+ ActiveRecord::Base.send :include, Typus::InstanceMethods
@@ -0,0 +1,155 @@
1
+ module Typus
2
+
3
+ module Authentication
4
+
5
+ protected
6
+
7
+ ##
8
+ # Require login checks if the user is logged on Typus, otherwise
9
+ # is sent to the sign in page with a :back_to param to return where
10
+ # she tried to go.
11
+ #
12
+ # Use this for demo!
13
+ #
14
+ # session[:typus_user_id] = Typus.user_class.find(:first)
15
+ #
16
+ def require_login
17
+ if session[:typus_user_id]
18
+ set_current_user
19
+ else
20
+ back_to = (request.env['REQUEST_URI'] == '/admin') ? nil : request.env['REQUEST_URI']
21
+ redirect_to admin_sign_in_path(:back_to => back_to)
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Return the current user.
27
+ #
28
+ # NOTE: If role does not longer exist on the system the user will
29
+ # be signed out from Typus.
30
+ #
31
+ def set_current_user
32
+
33
+ @current_user = Typus.user_class.find(session[:typus_user_id])
34
+
35
+ unless @current_user.respond_to?(:role)
36
+ raise _("Run 'script/generate typus_update_schema_to_01 -f && rake db:migrate' to update database schema.")
37
+ end
38
+
39
+ unless Typus::Configuration.roles.keys.include?(@current_user.role)
40
+ raise _("Role does no longer exists.")
41
+ end
42
+
43
+ unless @current_user.status
44
+ back_to = (request.env['REQUEST_URI'] == '/admin') ? nil : request.env['REQUEST_URI']
45
+ raise _("Typus user has been disabled.")
46
+ end
47
+
48
+ rescue Exception => error
49
+ flash[:notice] = error.message
50
+ session[:typus_user_id] = nil
51
+ redirect_to admin_sign_in_path(:back_to => back_to)
52
+ end
53
+
54
+ ##
55
+ # Action is available on:
56
+ #
57
+ # edit, update, toggle and destroy
58
+ #
59
+ def check_if_user_can_perform_action_on_user
60
+
61
+ return unless @item.kind_of?(Typus.user_class)
62
+
63
+ current_user = (@current_user == @item)
64
+
65
+ message = case params[:action]
66
+ when 'edit'
67
+
68
+ # Only admin and owner of Typus User can edit.
69
+ if !@current_user.is_root? && !current_user
70
+ _("As you're not the admin or the owner of this record you cannot edit it.")
71
+ end
72
+
73
+ when 'update'
74
+
75
+ # current_user cannot change her role.
76
+ if current_user && !(@item.role == params[:item][:role])
77
+ _("You can't change your role.")
78
+ end
79
+
80
+ when 'toggle'
81
+
82
+ # Only admin can toggle typus user status, but not herself.
83
+ if @current_user.is_root? && current_user
84
+ _("You can't toggle your status.")
85
+ elsif !@current_user.is_root?
86
+ _("You're not allowed to toggle status.")
87
+ end
88
+
89
+ when 'destroy'
90
+
91
+ # Admin can remove anything except herself.
92
+ if @current_user.is_root? && current_user
93
+ _("You can't remove yourself.")
94
+ elsif !@current_user.is_root?
95
+ _("You're not allowed to remove Typus Users.")
96
+ end
97
+
98
+ end
99
+
100
+ if message
101
+ flash[:notice] = message
102
+ redirect_to :back rescue redirect_to admin_dashboard_path
103
+ end
104
+
105
+ end
106
+
107
+ ##
108
+ # This method checks if the user can perform the requested action.
109
+ # It works on models, so its available on the admin_controller.
110
+ #
111
+ def check_if_user_can_perform_action_on_resource
112
+
113
+ message = case params[:action]
114
+ when 'index', 'show'
115
+ _("{{current_user_role}} can't display items.",
116
+ :current_user_role => @current_user.role.capitalize)
117
+ when 'edit', 'update', 'position', 'toggle', 'relate', 'unrelate'
118
+ when 'destroy'
119
+ _("{{current_user_role}} can't delete this item.",
120
+ :current_user_role => @current_user.role.capitalize)
121
+ else
122
+ _("{{current_user_role}} can't perform action ({{action}}).",
123
+ :current_user_role => @current_user.role.capitalize,
124
+ :action => params[:action])
125
+ end
126
+
127
+ unless @current_user.can_perform?(@resource[:class], params[:action])
128
+ flash[:notice] = message || _("{{current_user_role}} can't perform action. ({{action}}).",
129
+ :current_user_role => @current_user.role.capitalize,
130
+ :action => params[:action])
131
+ redirect_to :back rescue redirect_to admin_dashboard_path
132
+ end
133
+
134
+ end
135
+
136
+ ##
137
+ # This method checks if the user can perform the requested action.
138
+ # It works on resources, which are not models, so its available on
139
+ # the typus_controller.
140
+ #
141
+ def check_if_user_can_perform_action_on_resource_without_model
142
+ controller = params[:controller].split('/').last
143
+ action = params[:action]
144
+ unless @current_user.can_perform?(controller.camelize, action, { :special => true })
145
+ flash[:notice] = _("{{current_user_role}} can't go to {{action}} on {{controller}}.",
146
+ :current_user_role => @current_user.role.capitalize,
147
+ :action => action,
148
+ :controller => controller.humanize.downcase)
149
+ redirect_to :back rescue redirect_to admin_dashboard_path
150
+ end
151
+ end
152
+
153
+ end
154
+
155
+ end