typus 0.9.17

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 +8 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +86 -0
  4. data/Rakefile +61 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/master_controller.rb +354 -0
  7. data/app/controllers/typus_controller.rb +128 -0
  8. data/app/helpers/admin/form_helper.rb +386 -0
  9. data/app/helpers/admin/master_helper.rb +104 -0
  10. data/app/helpers/admin/public_helper.rb +27 -0
  11. data/app/helpers/admin/sidebar_helper.rb +236 -0
  12. data/app/helpers/admin/table_helper.rb +227 -0
  13. data/app/helpers/typus_helper.rb +194 -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 +24 -0
  18. data/app/views/admin/resources/index.html.erb +23 -0
  19. data/app/views/admin/resources/new.html.erb +22 -0
  20. data/app/views/admin/resources/show.html.erb +18 -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 +73 -0
  24. data/app/views/layouts/typus.html.erb +29 -0
  25. data/app/views/typus/dashboard.html.erb +9 -0
  26. data/app/views/typus/recover_password.html.erb +7 -0
  27. data/app/views/typus/reset_password.html.erb +15 -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/typus/de.yml +109 -0
  32. data/config/locales/typus/es.yml +109 -0
  33. data/config/locales/typus/language.yml.template +113 -0
  34. data/config/locales/typus/pt-BR.yml +111 -0
  35. data/config/locales/typus/ru.yml +111 -0
  36. data/generators/typus/templates/config/initializers/typus.rb +33 -0
  37. data/generators/typus/templates/config/typus/README +51 -0
  38. data/generators/typus/templates/config/typus/application.yml +6 -0
  39. data/generators/typus/templates/config/typus/application_roles.yml +23 -0
  40. data/generators/typus/templates/config/typus/typus.yml +14 -0
  41. data/generators/typus/templates/config/typus/typus_roles.yml +2 -0
  42. data/generators/typus/templates/db/create_typus_users.rb +21 -0
  43. data/generators/typus/templates/public/images/admin/arrow_down.gif +0 -0
  44. data/generators/typus/templates/public/images/admin/arrow_up.gif +0 -0
  45. data/generators/typus/templates/public/images/admin/spinner.gif +0 -0
  46. data/generators/typus/templates/public/images/admin/status_false.gif +0 -0
  47. data/generators/typus/templates/public/images/admin/status_true.gif +0 -0
  48. data/generators/typus/templates/public/images/admin/trash.gif +0 -0
  49. data/generators/typus/templates/public/javascripts/admin/application.js +14 -0
  50. data/generators/typus/templates/public/stylesheets/admin/reset.css +68 -0
  51. data/generators/typus/templates/public/stylesheets/admin/screen.css +729 -0
  52. data/generators/typus/typus_generator.rb +122 -0
  53. data/generators/typus_update_schema_to_01/templates/config/typus.yml +14 -0
  54. data/generators/typus_update_schema_to_01/templates/migration.rb +11 -0
  55. data/generators/typus_update_schema_to_01/typus_update_schema_to_01_generator.rb +19 -0
  56. data/lib/typus.rb +122 -0
  57. data/lib/typus/active_record.rb +307 -0
  58. data/lib/typus/authentication.rb +142 -0
  59. data/lib/typus/configuration.rb +85 -0
  60. data/lib/typus/extensions/routes.rb +15 -0
  61. data/lib/typus/format.rb +55 -0
  62. data/lib/typus/generator.rb +81 -0
  63. data/lib/typus/hash.rb +8 -0
  64. data/lib/typus/locale.rb +17 -0
  65. data/lib/typus/object.rb +21 -0
  66. data/lib/typus/quick_edit.rb +40 -0
  67. data/lib/typus/reloader.rb +15 -0
  68. data/lib/typus/string.rb +11 -0
  69. data/lib/typus/templates/index.html.erb +11 -0
  70. data/lib/typus/templates/resource_controller.rb.erb +15 -0
  71. data/lib/typus/templates/resource_controller_test.rb.erb +10 -0
  72. data/lib/typus/templates/resources_controller.rb.erb +37 -0
  73. data/lib/typus/user.rb +134 -0
  74. data/lib/vendor/active_record.rb +15 -0
  75. data/lib/vendor/paginator.rb +143 -0
  76. data/rails/init.rb +3 -0
  77. data/tasks/typus_tasks.rake +32 -0
  78. data/test/config/broken/application.yml +68 -0
  79. data/test/config/broken/application_roles.yml +20 -0
  80. data/test/config/broken/empty.yml +0 -0
  81. data/test/config/broken/empty_roles.yml +0 -0
  82. data/test/config/broken/undefined.yml +3 -0
  83. data/test/config/broken/undefined_roles.yml +6 -0
  84. data/test/config/default/typus.yml +14 -0
  85. data/test/config/default/typus_roles.yml +2 -0
  86. data/test/config/empty/empty_01.yml +0 -0
  87. data/test/config/empty/empty_01_roles.yml +0 -0
  88. data/test/config/empty/empty_02.yml +0 -0
  89. data/test/config/empty/empty_02_roles.yml +0 -0
  90. data/test/config/locales/es.yml +10 -0
  91. data/test/config/ordered/001_roles.yml +2 -0
  92. data/test/config/ordered/002_roles.yml +2 -0
  93. data/test/config/unordered/app_one_roles.yml +2 -0
  94. data/test/config/unordered/app_two_roles.yml +2 -0
  95. data/test/config/working/application.yml +68 -0
  96. data/test/config/working/application_roles.yml +22 -0
  97. data/test/config/working/typus.yml +14 -0
  98. data/test/config/working/typus_roles.yml +2 -0
  99. data/test/fixtures/app/controllers/admin/assets_controller.rb +2 -0
  100. data/test/fixtures/app/controllers/admin/categories_controller.rb +2 -0
  101. data/test/fixtures/app/controllers/admin/comments_controller.rb +2 -0
  102. data/test/fixtures/app/controllers/admin/pages_controller.rb +2 -0
  103. data/test/fixtures/app/controllers/admin/posts_controller.rb +2 -0
  104. data/test/fixtures/app/controllers/admin/status_controller.rb +6 -0
  105. data/test/fixtures/app/controllers/admin/typus_users_controller.rb +2 -0
  106. data/test/fixtures/app/controllers/admin/watch_dog_controller.rb +6 -0
  107. data/test/fixtures/app/views/admin/comments/_edit.html.erb +1 -0
  108. data/test/fixtures/app/views/admin/comments/_index.html.erb +1 -0
  109. data/test/fixtures/app/views/admin/comments/_new.html.erb +1 -0
  110. data/test/fixtures/app/views/admin/comments/_show.html.erb +1 -0
  111. data/test/fixtures/app/views/admin/comments/_sidebar.html.erb +1 -0
  112. data/test/fixtures/app/views/admin/dashboard/_content.html.erb +1 -0
  113. data/test/fixtures/app/views/admin/dashboard/_sidebar.html.erb +1 -0
  114. data/test/fixtures/app/views/admin/resources/_sidebar.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 +120 -0
  127. data/test/functional/admin/master_controller_test.rb +5 -0
  128. data/test/functional/admin/posts_controller_test.rb +261 -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 +321 -0
  132. data/test/helper.rb +51 -0
  133. data/test/helpers/admin/form_helper_test.rb +337 -0
  134. data/test/helpers/admin/master_helper_test.rb +69 -0
  135. data/test/helpers/admin/public_helper_test.rb +26 -0
  136. data/test/helpers/admin/sidebar_helper_test.rb +335 -0
  137. data/test/helpers/admin/table_helper_test.rb +239 -0
  138. data/test/helpers/typus_helper_test.rb +117 -0
  139. data/test/lib/active_record_test.rb +382 -0
  140. data/test/lib/configuration_test.rb +94 -0
  141. data/test/lib/hash_test.rb +11 -0
  142. data/test/lib/routes_test.rb +71 -0
  143. data/test/lib/string_test.rb +25 -0
  144. data/test/lib/typus_test.rb +85 -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 +136 -0
  153. data/typus.gemspec +228 -0
  154. metadata +241 -0
@@ -0,0 +1,15 @@
1
+ module Typus
2
+
3
+ module Reloader
4
+
5
+ # Reload config and roles when app is running in development.
6
+ def reload_config_et_roles
7
+ return if Rails.env.production?
8
+ logger.info "=> [typus] Configuration files have been reloaded."
9
+ Typus::Configuration.roles!
10
+ Typus::Configuration.config!
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+
3
+ def typus_actions_for(filter)
4
+ Typus::Configuration.config[self]['actions'][filter.to_s].split(', ') rescue []
5
+ end
6
+
7
+ def typus_defaults_for(filter)
8
+ Typus::Configuration.config[self][filter.to_s].split(', ') rescue []
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ <!-- Sidebar -->
2
+
3
+ <% content_for :sidebar do %>
4
+ <%= typus_block :location => 'dashboard', :partial => 'sidebar' %>
5
+ <% end %>
6
+
7
+ <!-- Content -->
8
+
9
+ <h2>Resource#index</h2>
10
+
11
+ <p>Find me in app/views/<%= params[:controller] %>/index.html.erb</p>
@@ -0,0 +1,15 @@
1
+ # Controller generated by Typus, use it to extend admin functionality.
2
+ class Admin::<%= resource %>Controller < TypusController
3
+
4
+ ##
5
+ # This controller was generated because you have defined a resource
6
+ # on <tt>config/typus/XXXXXX_roles.yml</tt> which is a tableless model.
7
+ #
8
+ # admin:
9
+ # <%= resource %>: index
10
+ #
11
+
12
+ def index
13
+ end
14
+
15
+ end
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+
3
+ class Admin::<%= model.pluralize %>ControllerTest < ActionController::TestCase
4
+
5
+ # Replace this with your real tests.
6
+ test "the truth" do
7
+ assert true
8
+ end
9
+
10
+ end
@@ -0,0 +1,37 @@
1
+ # Controller generated by Typus, use it to extend admin functionality.
2
+ class Admin::<%= model.pluralize %>Controller < Admin::MasterController
3
+
4
+ =begin
5
+
6
+ ##
7
+ # You can overwrite and extend Admin::MasterController with your methods.
8
+ #
9
+ # Actions have to be defined in <tt>config/typus/application.yml</tt>:
10
+ #
11
+ # <%= model %>:
12
+ # actions:
13
+ # index: custom_action
14
+ # edit: custom_action_for_an_item
15
+ #
16
+ # And you have to add permissions on <tt>config/typus/application_roles.yml</tt>
17
+ # to have access to them.
18
+ #
19
+ # admin:
20
+ # <%= model %>: create, read, update, destroy, custom_action
21
+ #
22
+ # editor:
23
+ # <%= model %>: create, read, update, custom_action_for_an_item
24
+ #
25
+
26
+ def index
27
+ end
28
+
29
+ def custom_action
30
+ end
31
+
32
+ def custom_action_for_an_item
33
+ end
34
+
35
+ =end
36
+
37
+ end
data/lib/typus/user.rb ADDED
@@ -0,0 +1,134 @@
1
+ module Typus
2
+
3
+ module EnableAsTypusUser
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def enable_as_typus_user
12
+
13
+ extend ClassMethodsMixin
14
+
15
+ attr_accessor :password
16
+
17
+ validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/
18
+ validates_presence_of :email
19
+ validates_uniqueness_of :email
20
+
21
+ validates_confirmation_of :password, :if => :password_required?
22
+ validates_length_of :password, :within => 8..40, :if => :password_required?
23
+ validates_presence_of :password, :if => :password_required?
24
+
25
+ validates_presence_of :role
26
+
27
+ before_save :initialize_salt, :encrypt_password, :initialize_token
28
+
29
+ include InstanceMethods
30
+
31
+ end
32
+
33
+ end
34
+
35
+ module ClassMethodsMixin
36
+
37
+ def role
38
+ Typus::Configuration.roles.keys.sort
39
+ end
40
+
41
+ def authenticate(email, password)
42
+ user = find_by_email_and_status(email, true)
43
+ user && user.authenticated?(password) ? user : nil
44
+ end
45
+
46
+ def generate(email, password, role = Typus::Configuration.options[:root], status = true)
47
+ new :email => email,
48
+ :password => password,
49
+ :password_confirmation => password,
50
+ :role => role,
51
+ :status => status
52
+ end
53
+
54
+ end
55
+
56
+ module InstanceMethods
57
+
58
+ def name
59
+ (!first_name.empty? && !last_name.empty?) ? "#{first_name} #{last_name}" : email
60
+ end
61
+
62
+ def authenticated?(password)
63
+ crypted_password == encrypt(password)
64
+ end
65
+
66
+ def resources
67
+ Typus::Configuration.roles[role].compact
68
+ end
69
+
70
+ def can_perform?(resource, action, options = {})
71
+
72
+ if options[:special]
73
+ _action = action
74
+ else
75
+ _action = case action
76
+ when 'new', 'create' then 'create'
77
+ when 'index', 'show' then 'read'
78
+ when 'edit', 'update' then 'update'
79
+ when 'position' then 'update'
80
+ when 'toggle' then 'update'
81
+ when 'relate', 'unrelate' then 'update'
82
+ when 'destroy' then 'delete'
83
+ else
84
+ action
85
+ end
86
+ end
87
+
88
+ # OPTIMIZE: We should not use a rescue.
89
+ resources[resource.to_s].split(', ').include?(_action) rescue false
90
+
91
+ end
92
+
93
+ def is_root?
94
+ role == Typus::Configuration.options[:root]
95
+ end
96
+
97
+ protected
98
+
99
+ def generate_hash(string)
100
+ Digest::SHA1.hexdigest(string)
101
+ end
102
+
103
+ def encrypt_password
104
+ return if password.blank?
105
+ self.crypted_password = encrypt(password)
106
+ end
107
+
108
+ def encrypt(string)
109
+ generate_hash("--#{salt}--#{string}")
110
+ end
111
+
112
+ def initialize_salt
113
+ self.salt = generate_hash("--#{Time.now.utc.to_s}--#{email}--") if new_record?
114
+ end
115
+
116
+ def initialize_token
117
+ generate_token if new_record?
118
+ end
119
+
120
+ def generate_token
121
+ self.token = encrypt("--#{Time.now.utc.to_s}--#{password}--").first(12)
122
+ end
123
+
124
+ def password_required?
125
+ crypted_password.blank? || !password.blank?
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+
134
+ ActiveRecord::Base.send :include, Typus::EnableAsTypusUser
@@ -0,0 +1,15 @@
1
+ class ActiveRecord::Base
2
+
3
+ def to_dom(*args)
4
+
5
+ options = args.extract_options!
6
+ display_id = new_record? ? 'new' : id
7
+
8
+ [ options[:prefix],
9
+ self.class.name.underscore,
10
+ display_id,
11
+ options[:suffix] ].compact.join('_')
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,143 @@
1
+ require 'forwardable'
2
+
3
+ class Paginator
4
+
5
+ VERSION = '1.1.1'
6
+
7
+ include Enumerable
8
+
9
+ class ArgumentError < ::ArgumentError; end
10
+ class MissingCountError < ArgumentError; end
11
+ class MissingSelectError < ArgumentError; end
12
+
13
+ attr_reader :per_page, :count
14
+
15
+ # Instantiate a new Paginator object
16
+ #
17
+ # Provide:
18
+ # * A total count of the number of objects to paginate
19
+ # * The number of objects in each page
20
+ # * A block that returns the array of items
21
+ # * The block is passed the item offset
22
+ # (and the number of items to show per page, for
23
+ # convenience, if the arity is 2)
24
+ def initialize(count, per_page, &select)
25
+ @count, @per_page = count, per_page
26
+ unless select
27
+ raise MissingSelectError, "Must provide block to select data for each page"
28
+ end
29
+ @select = select
30
+ end
31
+
32
+ # Total number of pages
33
+ def number_of_pages
34
+ (@count / @per_page).to_i + (@count % @per_page > 0 ? 1 : 0)
35
+ end
36
+
37
+ # First page object
38
+ def first
39
+ page 1
40
+ end
41
+
42
+ # Last page object
43
+ def last
44
+ page number_of_pages
45
+ end
46
+
47
+ def each
48
+ 1.upto(number_of_pages) do |number|
49
+ yield page(number)
50
+ end
51
+ end
52
+
53
+ # Retrieve page object by number
54
+ def page(number)
55
+ number = (n = number.to_i) > 0 ? n : 1
56
+ Page.new(self, number, lambda {
57
+ offset = (number - 1) * @per_page
58
+ args = [offset]
59
+ args << @per_page if @select.arity == 2
60
+ @select.call(*args)
61
+ })
62
+ end
63
+
64
+ # Page object
65
+ #
66
+ # Retrieves items for a page and provides metadata about the position
67
+ # of the page in the paginator
68
+ class Page
69
+
70
+ include Enumerable
71
+
72
+ attr_reader :number, :pager
73
+
74
+ def initialize(pager, number, select) #:nodoc:
75
+ @pager, @number = pager, number
76
+ @offset = (number - 1) * pager.per_page
77
+ @select = select
78
+ end
79
+
80
+ # Retrieve the items for this page
81
+ # * Caches
82
+ def items
83
+ @items ||= @select.call
84
+ end
85
+
86
+ # Does this page have any items?
87
+ def empty?
88
+ items.empty?
89
+ end
90
+
91
+ # Checks to see if there's a page before this one
92
+ def prev?
93
+ @number > 1
94
+ end
95
+
96
+ # Get previous page (if possible)
97
+ def prev
98
+ @pager.page(@number - 1) if prev?
99
+ end
100
+
101
+ # Checks to see if there's a page after this one
102
+ def next?
103
+ @number < @pager.number_of_pages
104
+ end
105
+
106
+ # Get next page (if possible)
107
+ def next
108
+ @pager.page(@number + 1) if next?
109
+ end
110
+
111
+ # The "item number" of the first item on this page
112
+ def first_item_number
113
+ 1 + @offset
114
+ end
115
+
116
+ # The "item number" of the last item on this page
117
+ def last_item_number
118
+ if next?
119
+ @offset + @pager.per_page
120
+ else
121
+ @pager.count
122
+ end
123
+ end
124
+
125
+ def ==(other) #:nodoc:
126
+ @pager == other.pager && self.number == other.number
127
+ end
128
+
129
+ def each(&block)
130
+ items.each(&block)
131
+ end
132
+
133
+ def method_missing(meth, *args, &block) #:nodoc:
134
+ if @pager.respond_to?(meth)
135
+ @pager.__send__(meth, *args, &block)
136
+ else
137
+ super
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'typus'
2
+
3
+ Typus.boot!
@@ -0,0 +1,32 @@
1
+ namespace :typus do
2
+
3
+ desc 'Install acts_as_list, acts_as_tree and paperclip.'
4
+ task :misc do
5
+ plugins = [ 'git://github.com/thoughtbot/paperclip.git',
6
+ 'git://github.com/rails/acts_as_list.git',
7
+ 'git://github.com/rails/acts_as_tree.git' ]
8
+ system "script/plugin install #{plugins.join(' ')} --force"
9
+ end
10
+
11
+ desc 'Install ssl_requirement.'
12
+ task :ssl do
13
+ system "script/plugin install git://github.com/rails/ssl_requirement.git --force"
14
+ end
15
+
16
+ desc 'Install tiny_mce.'
17
+ task :tiny_mce do
18
+ system "script/plugin install git://github.com/kete/tiny_mce.git --force"
19
+ load File.join Rails.root, 'vendor', 'plugins', 'tiny_mce', 'tasks', 'tiny_mce.rake'
20
+ Rake::Task["tiny_mce:install"].invoke
21
+ end
22
+
23
+ desc 'List current roles.'
24
+ task :roles => :environment do
25
+ Typus::Configuration.roles.each do |role|
26
+ puts "\n#{role.first.capitalize} role has access to:"
27
+ role.last.each { |key, value| puts "- #{key}: #{value}" }
28
+ end
29
+ puts "\n"
30
+ end
31
+
32
+ end
@@ -0,0 +1,68 @@
1
+ Page:
2
+ fields:
3
+ # Body field is overwrited from a Page class method.
4
+ list: title, body, status
5
+ form: title, body, status
6
+ relationships:
7
+ has_many: assets
8
+ application: Site
9
+
10
+ Asset:
11
+ fields:
12
+ list: caption
13
+ form: caption
14
+ application: Site
15
+
16
+ Category:
17
+ fields:
18
+ list: name, position
19
+ form: name, permalink, position
20
+ order_by: position
21
+ module: Post
22
+
23
+ Post:
24
+ fields:
25
+ list: title, created_at, status
26
+ form: title, body, created_at, status
27
+ relationship: title, created_at
28
+ options:
29
+ selectors: status
30
+ read_only: permalink
31
+ auto_generated: created_at
32
+ date_formats:
33
+ created_at: post_short
34
+ relationships: assets, categories
35
+ actions:
36
+ index: cleanup
37
+ edit: send_as_newsletter, preview
38
+ filters: status, created_at, user, user_id
39
+ search: title
40
+ order_by: title, -created_at
41
+ application: Blog
42
+
43
+ User:
44
+ fields:
45
+ list: first_name, last_name, email
46
+
47
+ Comment:
48
+ fields:
49
+ list: email, post, post_id
50
+ form: email, post
51
+ filters: post
52
+ search: email, body
53
+ application: Blog
54
+
55
+ TypusUser:
56
+ fields:
57
+ list: first_name, last_name, email, role, status
58
+ form: first_name, last_name, email, role, password, password_confirmation
59
+ relationship: first_name, last_name, role, email, status
60
+ options:
61
+ selectors: role
62
+ booleans:
63
+ status: active, inactive
64
+ filters: status, role, unexisting
65
+ search: first_name, last_name, email, role
66
+ module: Typus
67
+ description: System Users Administration
68
+ application: Typus