ditty 0.7.1 → 0.10.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/.env.test +2 -0
  3. data/.gitignore +3 -0
  4. data/.pryrc +2 -0
  5. data/.rubocop.yml +24 -8
  6. data/.travis.yml +4 -8
  7. data/CNAME +1 -0
  8. data/Dockerfile +18 -0
  9. data/Gemfile.ci +0 -15
  10. data/Rakefile +5 -4
  11. data/Readme.md +24 -2
  12. data/_config.yml +1 -0
  13. data/config.ru +4 -4
  14. data/ditty.gemspec +31 -20
  15. data/docs/CNAME +1 -0
  16. data/docs/_config.yml +1 -0
  17. data/docs/index.md +34 -0
  18. data/exe/ditty +2 -0
  19. data/lib/ditty.rb +30 -4
  20. data/lib/ditty/cli.rb +38 -5
  21. data/lib/ditty/components/ditty.rb +82 -0
  22. data/lib/ditty/controllers/application_controller.rb +267 -0
  23. data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +5 -7
  24. data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +56 -32
  25. data/lib/ditty/controllers/{component.rb → component_controller.rb} +35 -24
  26. data/lib/ditty/controllers/{main.rb → main_controller.rb} +7 -7
  27. data/lib/ditty/controllers/roles_controller.rb +23 -0
  28. data/lib/ditty/controllers/user_login_traits_controller.rb +46 -0
  29. data/lib/ditty/controllers/{users.rb → users_controller.rb} +17 -20
  30. data/lib/ditty/db.rb +9 -5
  31. data/lib/ditty/emails/base.rb +48 -34
  32. data/lib/ditty/generators/crud_generator.rb +114 -0
  33. data/lib/ditty/generators/migration_generator.rb +26 -0
  34. data/lib/ditty/generators/project_generator.rb +52 -0
  35. data/lib/ditty/helpers/authentication.rb +6 -5
  36. data/lib/ditty/helpers/component.rb +11 -2
  37. data/lib/ditty/helpers/pundit.rb +24 -8
  38. data/lib/ditty/helpers/response.rb +38 -15
  39. data/lib/ditty/helpers/views.rb +48 -6
  40. data/lib/ditty/listener.rb +44 -14
  41. data/lib/ditty/memcached.rb +8 -0
  42. data/lib/ditty/middleware/accept_extension.rb +4 -2
  43. data/lib/ditty/middleware/error_catchall.rb +4 -2
  44. data/lib/ditty/models/audit_log.rb +1 -0
  45. data/lib/ditty/models/base.rb +13 -0
  46. data/lib/ditty/models/identity.rb +10 -7
  47. data/lib/ditty/models/role.rb +2 -0
  48. data/lib/ditty/models/user.rb +40 -3
  49. data/lib/ditty/models/user_login_trait.rb +17 -0
  50. data/lib/ditty/policies/audit_log_policy.rb +6 -6
  51. data/lib/ditty/policies/role_policy.rb +3 -3
  52. data/lib/ditty/policies/user_login_trait_policy.rb +45 -0
  53. data/lib/ditty/policies/user_policy.rb +3 -3
  54. data/lib/ditty/rubocop.rb +3 -0
  55. data/lib/ditty/seed.rb +2 -0
  56. data/lib/ditty/services/authentication.rb +31 -15
  57. data/lib/ditty/services/email.rb +22 -12
  58. data/lib/ditty/services/logger.rb +30 -13
  59. data/lib/ditty/services/pagination_wrapper.rb +9 -5
  60. data/lib/ditty/services/settings.rb +19 -7
  61. data/lib/ditty/tasks/ditty.rake +127 -0
  62. data/lib/ditty/tasks/omniauth-ldap.rake +43 -0
  63. data/lib/ditty/templates/.gitignore +5 -0
  64. data/lib/ditty/templates/.rspec +2 -0
  65. data/lib/ditty/templates/.rubocop.yml +7 -0
  66. data/lib/ditty/templates/Rakefile +12 -0
  67. data/lib/ditty/templates/application.rb +12 -0
  68. data/lib/ditty/templates/config.ru +37 -0
  69. data/lib/ditty/templates/controller.rb.erb +64 -0
  70. data/lib/ditty/templates/env.example +4 -0
  71. data/lib/ditty/templates/lib/project.rb.erb +5 -0
  72. data/lib/ditty/templates/migration.rb.erb +7 -0
  73. data/lib/ditty/templates/model.rb.erb +26 -0
  74. data/lib/ditty/templates/pids/.empty_directory +0 -0
  75. data/lib/ditty/templates/policy.rb.erb +48 -0
  76. data/{public → lib/ditty/templates/public}/browserconfig.xml +0 -0
  77. data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
  78. data/lib/ditty/templates/public/css/styles.css +13 -0
  79. data/lib/ditty/templates/public/favicon.ico +0 -0
  80. data/{public → lib/ditty/templates/public}/images/apple-icon.png +0 -0
  81. data/{public → lib/ditty/templates/public}/images/favicon-16x16.png +0 -0
  82. data/{public → lib/ditty/templates/public}/images/favicon-32x32.png +0 -0
  83. data/{public → lib/ditty/templates/public}/images/launcher-icon-1x.png +0 -0
  84. data/{public → lib/ditty/templates/public}/images/launcher-icon-2x.png +0 -0
  85. data/{public → lib/ditty/templates/public}/images/launcher-icon-4x.png +0 -0
  86. data/{public → lib/ditty/templates/public}/images/mstile-150x150.png +0 -0
  87. data/{public → lib/ditty/templates/public}/images/safari-pinned-tab.svg +0 -0
  88. data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
  89. data/lib/ditty/templates/public/js/scripts.js +1 -0
  90. data/{public/manifest.json → lib/ditty/templates/public/manifest.json.erb} +2 -2
  91. data/lib/ditty/templates/settings.yml.erb +19 -0
  92. data/lib/ditty/templates/sidekiq.rb +18 -0
  93. data/lib/ditty/templates/sidekiq.yml +9 -0
  94. data/lib/ditty/templates/spec_helper.rb +43 -0
  95. data/lib/ditty/templates/type.rb.erb +21 -0
  96. data/lib/ditty/templates/views/display.haml.tt +20 -0
  97. data/lib/ditty/templates/views/edit.haml.tt +10 -0
  98. data/lib/ditty/templates/views/form.haml.tt +11 -0
  99. data/lib/ditty/templates/views/index.haml.tt +29 -0
  100. data/lib/ditty/templates/views/new.haml.tt +10 -0
  101. data/lib/ditty/version.rb +1 -1
  102. data/lib/rubocop/cop/ditty/call_services_directly.rb +42 -0
  103. data/migrate/20181209_add_user_login_traits.rb +16 -0
  104. data/migrate/20181209_extend_audit_log.rb +12 -0
  105. data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
  106. data/spec/ditty/api_spec.rb +51 -0
  107. data/spec/ditty/controllers/roles_spec.rb +67 -0
  108. data/spec/ditty/controllers/user_login_traits_spec.rb +72 -0
  109. data/spec/ditty/controllers/users_spec.rb +72 -0
  110. data/spec/ditty/emails/base_spec.rb +76 -0
  111. data/spec/ditty/emails/forgot_password_spec.rb +20 -0
  112. data/spec/ditty/helpers/component_spec.rb +85 -0
  113. data/spec/ditty/models/user_spec.rb +36 -0
  114. data/spec/ditty/services/email_spec.rb +36 -0
  115. data/spec/ditty/services/logger_spec.rb +68 -0
  116. data/spec/ditty/services/settings_spec.rb +63 -0
  117. data/spec/ditty_spec.rb +9 -0
  118. data/spec/factories.rb +46 -0
  119. data/spec/fixtures/logger.yml +17 -0
  120. data/spec/fixtures/section.yml +3 -0
  121. data/spec/fixtures/settings.yml +8 -0
  122. data/spec/spec_helper.rb +51 -0
  123. data/spec/support/api_shared_examples.rb +250 -0
  124. data/spec/support/crud_shared_examples.rb +145 -0
  125. data/views/403.haml +2 -0
  126. data/views/404.haml +2 -4
  127. data/views/500.haml +11 -0
  128. data/views/audit_logs/index.haml +32 -28
  129. data/views/auth/forgot_password.haml +32 -16
  130. data/views/auth/identity.haml +14 -13
  131. data/views/auth/ldap.haml +17 -0
  132. data/views/auth/login.haml +23 -17
  133. data/views/auth/register.haml +20 -18
  134. data/views/auth/register_identity.haml +27 -12
  135. data/views/auth/reset_password.haml +36 -19
  136. data/views/blank.haml +43 -0
  137. data/views/emails/forgot_password.haml +1 -1
  138. data/views/emails/layouts/action.haml +10 -6
  139. data/views/emails/layouts/alert.haml +2 -1
  140. data/views/emails/layouts/billing.haml +2 -1
  141. data/views/embedded.haml +17 -11
  142. data/views/error.haml +8 -3
  143. data/views/index.haml +1 -1
  144. data/views/layout.haml +45 -30
  145. data/views/partials/actions.haml +15 -14
  146. data/views/partials/content_tag.haml +0 -0
  147. data/views/partials/delete_form.haml +1 -1
  148. data/views/partials/filter_control.haml +2 -2
  149. data/views/partials/footer.haml +13 -5
  150. data/views/partials/form_control.haml +30 -19
  151. data/views/partials/form_tag.haml +1 -1
  152. data/views/partials/navitems.haml +42 -0
  153. data/views/partials/notifications.haml +12 -8
  154. data/views/partials/pager.haml +44 -25
  155. data/views/partials/search.haml +15 -11
  156. data/views/partials/sidebar.haml +15 -37
  157. data/views/partials/sort_ui.haml +2 -0
  158. data/views/partials/timespan_selector.haml +64 -0
  159. data/views/partials/topbar.haml +53 -0
  160. data/views/partials/user_associations.haml +32 -0
  161. data/views/quick_start.haml +23 -0
  162. data/views/roles/display.haml +27 -6
  163. data/views/roles/edit.haml +3 -3
  164. data/views/roles/form.haml +1 -0
  165. data/views/roles/index.haml +23 -14
  166. data/views/roles/new.haml +2 -2
  167. data/views/user_login_traits/display.haml +32 -0
  168. data/views/user_login_traits/edit.haml +10 -0
  169. data/views/user_login_traits/form.haml +5 -0
  170. data/views/user_login_traits/index.haml +28 -0
  171. data/views/user_login_traits/new.haml +10 -0
  172. data/views/users/display.haml +15 -16
  173. data/views/users/edit.haml +3 -3
  174. data/views/users/form.haml +0 -0
  175. data/views/users/index.haml +31 -24
  176. data/views/users/login_traits.haml +25 -0
  177. data/views/users/new.haml +2 -2
  178. data/views/users/profile.haml +17 -15
  179. data/views/users/user.haml +1 -1
  180. metadata +314 -76
  181. data/lib/ditty/components/app.rb +0 -77
  182. data/lib/ditty/controllers/application.rb +0 -175
  183. data/lib/ditty/controllers/roles.rb +0 -16
  184. data/lib/ditty/rake_tasks.rb +0 -102
  185. data/views/partials/navbar.haml +0 -23
data/lib/ditty/cli.rb CHANGED
@@ -1,23 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # https://nandovieira.com/creating-generators-and-executables-with-thor
2
- require 'dotenv/load'
4
+ require 'dotenv/load' rescue LoadError # rubocop:disable Style/RescueModifier - Ignore dotenv/load errors
3
5
  require 'thor'
4
- require 'ditty'
5
- require 'ditty/rake_tasks'
6
6
  require 'rack'
7
7
  require 'rake'
8
+ require 'ditty/db' if ENV['DATABASE_URL']
9
+ require 'ditty/generators/crud_generator'
10
+ require 'ditty/generators/project_generator'
11
+ require 'ditty/generators/migration_generator'
12
+ require 'ditty/components/ditty'
13
+
14
+ # TODO: Component generator
15
+ # TODO: Add requires into application.rb
16
+ # TODO: Add requires into schema.rb
8
17
 
9
18
  module Ditty
10
19
  class CLI < Thor
11
20
  include Thor::Actions
12
21
 
22
+ register ::Ditty::Generators::CrudGenerator, 'crud', 'crud NAME', 'Generate a CRUD endpoint'
23
+
24
+ register ::Ditty::Generators::ProjectGenerator, 'init', 'init', 'Initialize a Ditty Project'
25
+
26
+ register ::Ditty::Generators::MigrationGenerator, 'migration', 'migration NAME', 'Create a new Sequel migration'
27
+
28
+ default_task :server
29
+
13
30
  desc 'server', 'Start the Ditty server'
14
31
  require './application' if File.exist?('application.rb')
32
+ require 'ditty/db' unless defined?(DB)
33
+ ::Ditty::Components.tasks
15
34
  def server
16
35
  # Ensure the token files are present
17
36
  Rake::Task['ditty:generate_tokens'].invoke
18
37
 
19
38
  # Prep Ditty
20
- Rake::Task['ditty:prep'].invoke
39
+ Rake::Task['ditty:prep:folders'].invoke
40
+ Rake::Task['ditty:prep:migrations'].invoke
21
41
 
22
42
  # Check the migrations
23
43
  Rake::Task['ditty:migrate:check'].invoke
@@ -34,11 +54,24 @@ module Ditty
34
54
  desc 'migrate', 'Run the Ditty migrations'
35
55
  def migrate
36
56
  # Prep Ditty
37
- Rake::Task['ditty:prep'].invoke
57
+ Rake::Task['ditty:prep:migrations'].invoke
38
58
 
39
59
  # Run the migrations
40
60
  Rake::Task['ditty:migrate:up'].invoke
41
61
  puts 'Ditty Migrations Executed'
62
+
63
+ Rake::Task['ditty:dump_schema'].invoke
64
+ puts 'Ditty DB Schema Dumped'
65
+ end
66
+
67
+ desc 'seed', 'Seed the predefined seeding data'
68
+ def seed
69
+ Rake::Task['ditty:seed'].invoke
70
+ end
71
+
72
+ desc 'console', 'Open a fully loaded console'
73
+ def console
74
+ Rake::Task['ditty:console'].invoke
42
75
  end
43
76
  end
44
77
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ditty'
4
+ require 'ditty/services/settings'
5
+
6
+ module Ditty
7
+ class Ditty
8
+ def self.load
9
+ controllers = File.expand_path('../controllers', __dir__)
10
+ Dir.glob("#{controllers}/*.rb").sort.each { |f| require f }
11
+
12
+ require 'ditty/models/user'
13
+ require 'ditty/models/role'
14
+ require 'ditty/models/identity'
15
+ require 'ditty/models/audit_log'
16
+ require 'ditty/models/user_login_trait'
17
+ end
18
+
19
+ def self.configure(_container)
20
+ require 'ditty/db' unless defined? ::DB
21
+ require 'ditty/listener'
22
+ end
23
+
24
+ def self.migrations
25
+ File.expand_path('../../../migrate', __dir__)
26
+ end
27
+
28
+ def self.view_folder
29
+ File.expand_path('../../../views', __dir__)
30
+ end
31
+
32
+ def self.routes
33
+ load
34
+ {
35
+ '/' => ::Ditty::MainController,
36
+ '/auth' => ::Ditty::AuthController,
37
+ '/users' => ::Ditty::UsersController,
38
+ '/roles' => ::Ditty::RolesController,
39
+ '/audit-logs' => ::Ditty::AuditLogsController,
40
+ '/login-traits' => ::Ditty::UserLoginTraitsController
41
+ }
42
+ end
43
+
44
+ def self.navigation(_request)
45
+ load
46
+
47
+ [
48
+ {
49
+ group: 'User Management',
50
+ order: 50,
51
+ icon: 'lock',
52
+ target: ::Ditty::User,
53
+ items: [
54
+ { order: 10, link: '/users/', text: 'Users', target: ::Ditty::User, icon: 'user' },
55
+ { order: 20, link: '/roles/', text: 'Roles', target: ::Ditty::Role, icon: 'check-square' },
56
+ { order: 30, link: '/audit-logs/', text: 'Audit Logs', target: ::Ditty::AuditLog, icon: 'history' },
57
+ { order: 40, link: '/login-traits/', text: 'User Login Traits', target: ::Ditty::UserLoginTrait,
58
+ icon: 'list' }
59
+ ]
60
+ }
61
+ ]
62
+ end
63
+
64
+ def self.seeder
65
+ proc do
66
+ load
67
+
68
+ sa = ::Ditty::Role.find_or_create(name: 'super_admin')
69
+ admin = ::Ditty::Role.find_or_create(name: 'admin') { |e| e.parent = sa }
70
+ ::Ditty::Role.find_or_create(name: 'user') { |e| e.parent = admin }
71
+ end
72
+ end
73
+
74
+ def self.tasks
75
+ Kernel.load 'ditty/tasks/ditty.rake'
76
+ auth_settings = ::Ditty::Services::Settings[:authentication] || {}
77
+ Kernel.load 'ditty/tasks/omniauth-ldap.rake' if auth_settings.key?(:ldap)
78
+ end
79
+ end
80
+ end
81
+
82
+ Ditty::Components.register_component(:ditty, Ditty::Ditty)
@@ -0,0 +1,267 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'browser/browser'
4
+ require 'wisper'
5
+ require 'oga'
6
+ require 'sinatra/base'
7
+ require 'sinatra/flash'
8
+ require 'sinatra/param'
9
+ require 'sinatra/respond_with'
10
+ require 'ditty/helpers/views'
11
+ require 'ditty/helpers/pundit'
12
+ require 'ditty/helpers/authentication'
13
+ require 'ditty/services/logger'
14
+ require 'active_support'
15
+ require 'active_support/inflector'
16
+ require 'rack/contrib'
17
+ require 'rack/csrf'
18
+
19
+ module Ditty
20
+ class ApplicationController < Sinatra::Base
21
+ include ActiveSupport::Inflector
22
+
23
+ set :root, ENV['APP_ROOT'] || ::File.expand_path("#{::File.dirname(__FILE__)}/../../../")
24
+ set :map_path, nil
25
+ set :view_location, nil
26
+ set :view_folder, nil
27
+ set :base_path, nil
28
+ set :model_class, nil
29
+ set :raise_sinatra_param_exceptions, true
30
+ set track_actions: false
31
+
32
+ # The order here is important, since Wisper has a deprecated method respond_with method
33
+ helpers Wisper::Publisher
34
+ helpers Helpers::Pundit, Helpers::Views, Helpers::Authentication
35
+ helpers Sinatra::Param
36
+
37
+ register Sinatra::Flash, Sinatra::RespondWith
38
+
39
+ use Rack::Csrf, raise: ENV['APP_ENV'] == 'development' unless ENV['APP_ENV'] == 'test'
40
+ use Rack::JSONBodyParser
41
+ use Rack::MethodOverride
42
+ use Rack::NestedParams
43
+
44
+ helpers do
45
+ def logger
46
+ ::Ditty::Services::Logger
47
+ end
48
+
49
+ def base_path
50
+ settings.base_path || "#{settings.map_path}/#{dasherize(view_location)}"
51
+ end
52
+
53
+ def view_location
54
+ return settings.view_location if settings.view_location
55
+
56
+ loc = demodulize(settings.model_class || self.class)
57
+ pluralize(underscore(loc.gsub(/Controller\Z/, '')))
58
+ end
59
+
60
+ def browser
61
+ Browser.new(request.user_agent, accept_language: request.env['HTTP_ACCEPT_LANGUAGE'])
62
+ end
63
+
64
+ def config(name, default = '')
65
+ ::Ditty::Services::Settings[name] || default
66
+ end
67
+ end
68
+
69
+ def view_folders
70
+ folders = ['./views']
71
+ folders << settings.view_folder if settings.view_folder
72
+ folders << ::Ditty::Ditty.view_folder
73
+ end
74
+
75
+ def find_template(views, name, engine, &block)
76
+ # Backwards compatability
77
+ if settings.view_folder.nil? && self.class.name.split('::').first != 'Ditty'
78
+ return super(views, name, engine, &block)
79
+ end
80
+
81
+ view_folders.each do |folder|
82
+ super(folder, name, engine, &block) # Root
83
+ end
84
+ raise ::Ditty::TemplateNotFoundError, "Could not find template `#{name}`"
85
+ end
86
+
87
+ configure :production do
88
+ disable :show_exceptions
89
+ set :dump_errors, false
90
+ end
91
+
92
+ configure :development do
93
+ set :show_exceptions, :after_handler
94
+ end
95
+
96
+ configure :production, :development do
97
+ disable :logging
98
+ use Rack::CommonLogger, ::Ditty::Services::Logger
99
+ end
100
+
101
+ not_found do
102
+ respond_to do |format|
103
+ status 404
104
+ format.html do
105
+ haml :'404', locals: { title: '4 oh 4' }, layout: layout
106
+ end
107
+ format.json do
108
+ if response.body.empty?
109
+ json code: 404, errors: ['Not Found']
110
+ else
111
+ [404, response.body]
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ error Helpers::NotAuthenticated, ::Pundit::NotAuthorizedError do
118
+ # TODO: Check if this is logged / tracked
119
+ if authenticated?
120
+ respond_to do |format|
121
+ status 403
122
+ format.html do
123
+ flash.now[:danger] = 'Cannot perform that action at the moment.'
124
+ haml :'403', locals: { title: 'Forbidden' }, layout: layout
125
+ end
126
+ format.json do
127
+ json code: 403, errors: ['Forbidden']
128
+ end
129
+ end
130
+ else
131
+ respond_to do |format|
132
+ format.html do
133
+ flash[:warning] = 'Please log in first.'
134
+ redirect with_layout("#{settings.map_path}/auth/login")
135
+ end
136
+ format.json do
137
+ status 401
138
+ json code: 401, errors: ['Not Authenticated']
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ error ::Sinatra::Param::InvalidParameterError do
145
+ respond_to do |format|
146
+ status 400
147
+ format.html do
148
+ flash.now[:danger] = env['sinatra.error'].message
149
+ haml :'400', locals: { title: '4 oh oh' }, layout: layout
150
+ end
151
+ format.json do
152
+ json code: 400, errors: { env['sinatra.error'].param => env['sinatra.error'].message },
153
+ full_errors: [env['sinatra.error'].message]
154
+ end
155
+ end
156
+ end
157
+
158
+ error ::Sequel::NoMatchingRow do
159
+ respond_to do |format|
160
+ status 404
161
+ format.html do
162
+ haml :'404', locals: { title: '4 oh 4' }, layout: layout
163
+ end
164
+ format.json do
165
+ if response.body.empty?
166
+ json code: 404, errors: ['Not Found']
167
+ else
168
+ [404, response.body]
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ error ::Sequel::ValidationFailed do
175
+ respond_to do |format|
176
+ entity = env['sinatra.error'].model
177
+ errors = env['sinatra.error'].errors
178
+ status 400
179
+ format.html do
180
+ action = entity.id ? :edit : :new
181
+ haml :"#{view_location}/#{action}", locals: { entity: entity, title: heading(action) }, layout: layout
182
+ end
183
+ format.json do
184
+ json code: 400, errors: errors, full_errors: errors.full_messages
185
+ end
186
+ end
187
+ end
188
+
189
+ error ::Sequel::ForeignKeyConstraintViolation do
190
+ error = env['sinatra.error']
191
+ broadcast(:application_error, error)
192
+ logger.error error
193
+ respond_to do |format|
194
+ status 400
195
+ format.html do
196
+ haml :error, locals: { title: 'Something went wrong', error: error }, layout: layout
197
+ end
198
+ format.json do
199
+ json code: 400, errors: ['Invalid Relation Specified']
200
+ end
201
+ end
202
+ end
203
+
204
+ error ::Ditty::TemplateNotFoundError do
205
+ # TODO: Display a better error message
206
+ error = env['sinatra.error']
207
+ broadcast(:application_error, error)
208
+ logger.error error
209
+ respond_to do |format|
210
+ status 500
211
+ format.html do
212
+ haml :error, locals: { title: 'Template not found', error: error }, layout: layout
213
+ end
214
+ end
215
+ end
216
+
217
+ error do
218
+ error = env['sinatra.error']
219
+ broadcast(:application_error, error)
220
+ logger.error error
221
+ respond_to do |format|
222
+ status 500
223
+ format.html do
224
+ haml :error, locals: { title: 'Something went wrong', error: error }, layout: layout
225
+ end
226
+ format.json do
227
+ json code: 500, errors: ['Something went wrong']
228
+ end
229
+ end
230
+ end
231
+
232
+ before(/.*/) do
233
+ logger.info "Running with #{self.class} - #{request.path_info}"
234
+ if /.*\.json\Z/.match?(request.path)
235
+ content_type :json
236
+ request.path_info = request.path_info.gsub(/.json$/, '')
237
+ elsif /.*\.csv\Z/.match?(request.path)
238
+ content_type :csv
239
+ request.path_info = request.path_info.gsub(/.csv$/, '')
240
+ elsif request.env['ACCEPT']
241
+ content_type request.env['ACCEPT']
242
+ elsif request.accept.count.eql?(1) && request.accept.first.to_s.eql?('*/*')
243
+ content_type(:json)
244
+ end
245
+ end
246
+
247
+ after do
248
+ return if params[:layout].nil?
249
+ return unless response.body.respond_to?(:map)
250
+
251
+ begin
252
+ orig = response.body
253
+ response.body = response.body.map do |resp|
254
+ document = Oga.parse_html(resp)
255
+ document.css('a').each do |elm|
256
+ unless (href = elm.get('href')).nil?
257
+ elm.set 'href', with_layout(href)
258
+ end
259
+ end
260
+ document.to_xml
261
+ end
262
+ rescue StandardError => _e
263
+ orig
264
+ end
265
+ end
266
+ end
267
+ end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ditty/controllers/component'
3
+ require 'ditty/controllers/component_controller'
4
4
  require 'ditty/models/audit_log'
5
5
  require 'ditty/policies/audit_log_policy'
6
6
 
7
7
  module Ditty
8
- class AuditLogs < Ditty::Component
8
+ class AuditLogsController < ::Ditty::ComponentController
9
9
  set model_class: AuditLog
10
10
 
11
+ SEARCHABLE = %i[details platform device browser ip_address].freeze
11
12
  FILTERS = [
12
13
  { name: :user, field: 'user.email' },
13
14
  { name: :action }
@@ -23,12 +24,9 @@ module Ditty
23
24
  end
24
25
  end
25
26
 
26
- def find_template(views, name, engine, &block)
27
- super(views, name, engine, &block) # Root
28
- super(::Ditty::App.view_folder, name, engine, &block) # Ditty
29
- end
30
-
31
27
  def list
28
+ return super if params[:sort]
29
+
32
30
  super.order(:created_at).reverse
33
31
  end
34
32