ditty 0.8.0 → 0.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.test +2 -0
- data/.gitignore +3 -0
- data/.pryrc +2 -0
- data/.rubocop.yml +23 -4
- data/.travis.yml +4 -8
- data/CNAME +1 -0
- data/Dockerfile +18 -0
- data/Gemfile.ci +0 -17
- data/Rakefile +2 -2
- data/_config.yml +1 -0
- data/config.ru +4 -4
- data/ditty.gemspec +28 -18
- data/docs/CNAME +1 -0
- data/docs/_config.yml +1 -0
- data/docs/index.md +34 -0
- data/exe/ditty +2 -0
- data/lib/ditty/cli.rb +41 -5
- data/lib/ditty/components/{app.rb → ditty.rb} +18 -16
- data/lib/ditty/controllers/{application.rb → application_controller.rb} +63 -34
- data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +4 -2
- data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +22 -18
- data/lib/ditty/controllers/{component.rb → component_controller.rb} +23 -20
- data/lib/ditty/controllers/{main.rb → main_controller.rb} +6 -2
- data/lib/ditty/controllers/roles_controller.rb +23 -0
- data/lib/ditty/controllers/user_login_traits_controller.rb +46 -0
- data/lib/ditty/controllers/{users.rb → users_controller.rb} +13 -11
- data/lib/ditty/db.rb +7 -5
- data/lib/ditty/emails/base.rb +37 -32
- data/lib/ditty/generators/crud_generator.rb +114 -0
- data/lib/ditty/generators/migration_generator.rb +26 -0
- data/lib/ditty/generators/project_generator.rb +52 -0
- data/lib/ditty/helpers/component.rb +2 -1
- data/lib/ditty/helpers/pundit.rb +24 -8
- data/lib/ditty/helpers/response.rb +15 -13
- data/lib/ditty/helpers/views.rb +28 -6
- data/lib/ditty/listener.rb +6 -4
- data/lib/ditty/memcached.rb +8 -0
- data/lib/ditty/middleware/accept_extension.rb +2 -2
- data/lib/ditty/middleware/error_catchall.rb +2 -2
- data/lib/ditty/models/base.rb +9 -0
- data/lib/ditty/models/identity.rb +11 -7
- data/lib/ditty/models/role.rb +1 -0
- data/lib/ditty/models/user.rb +23 -2
- data/lib/ditty/policies/role_policy.rb +1 -1
- data/lib/ditty/policies/user_login_trait_policy.rb +1 -1
- data/lib/ditty/policies/user_policy.rb +1 -1
- data/lib/ditty/services/authentication.rb +27 -16
- data/lib/ditty/services/email.rb +19 -15
- data/lib/ditty/services/logger.rb +26 -20
- data/lib/ditty/services/pagination_wrapper.rb +7 -5
- data/lib/ditty/services/settings.rb +7 -6
- data/lib/ditty/tasks/ditty.rake +19 -1
- data/lib/ditty/tasks/omniauth-ldap.rake +2 -2
- data/lib/ditty/templates/.gitignore +5 -0
- data/lib/ditty/templates/.rspec +2 -0
- data/lib/ditty/templates/.rubocop.yml +7 -0
- data/lib/ditty/templates/Rakefile +12 -0
- data/lib/ditty/templates/application.rb +12 -0
- data/lib/ditty/templates/config.ru +37 -0
- data/lib/ditty/templates/controller.rb.erb +64 -0
- data/lib/ditty/templates/env.example +4 -0
- data/lib/ditty/templates/lib/project.rb.erb +5 -0
- data/lib/ditty/templates/logs/.empty_directory +0 -0
- data/lib/ditty/templates/migration.rb.erb +7 -0
- data/lib/ditty/templates/model.rb.erb +26 -0
- data/lib/ditty/templates/pids/.empty_directory +0 -0
- data/lib/ditty/templates/policy.rb.erb +48 -0
- data/{public → lib/ditty/templates/public}/browserconfig.xml +0 -0
- data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
- data/lib/ditty/templates/public/css/styles.css +13 -0
- data/lib/ditty/templates/public/favicon.ico +0 -0
- data/{public → lib/ditty/templates/public}/images/apple-icon.png +0 -0
- data/{public → lib/ditty/templates/public}/images/favicon-16x16.png +0 -0
- data/{public → lib/ditty/templates/public}/images/favicon-32x32.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-1x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-2x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-4x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/mstile-150x150.png +0 -0
- data/{public → lib/ditty/templates/public}/images/safari-pinned-tab.svg +0 -0
- data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
- data/lib/ditty/templates/public/js/scripts.js +1 -0
- data/{public/manifest.json → lib/ditty/templates/public/manifest.json.erb} +2 -2
- data/lib/ditty/templates/settings.yml.erb +29 -0
- data/lib/ditty/templates/sidekiq.rb +18 -0
- data/lib/ditty/templates/sidekiq.yml +9 -0
- data/lib/ditty/templates/spec_helper.rb +43 -0
- data/lib/ditty/templates/type.rb.erb +21 -0
- data/lib/ditty/templates/views/display.haml.tt +20 -0
- data/lib/ditty/templates/views/edit.haml.tt +10 -0
- data/lib/ditty/templates/views/form.haml.tt +11 -0
- data/lib/ditty/templates/views/index.haml.tt +29 -0
- data/lib/ditty/templates/views/new.haml.tt +10 -0
- data/lib/ditty/version.rb +1 -1
- data/lib/ditty.rb +6 -4
- data/lib/rubocop/cop/ditty/call_services_directly.rb +2 -2
- data/migrate/20181209_add_user_login_traits.rb +4 -4
- data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
- data/spec/ditty/api_spec.rb +51 -0
- data/spec/ditty/controllers/roles_spec.rb +67 -0
- data/spec/ditty/controllers/user_login_traits_spec.rb +72 -0
- data/spec/ditty/controllers/users_spec.rb +72 -0
- data/spec/ditty/emails/base_spec.rb +76 -0
- data/spec/ditty/emails/forgot_password_spec.rb +20 -0
- data/spec/ditty/helpers/component_spec.rb +85 -0
- data/spec/ditty/models/user_spec.rb +36 -0
- data/spec/ditty/services/email_spec.rb +36 -0
- data/spec/ditty/services/logger_spec.rb +68 -0
- data/spec/ditty/services/settings_spec.rb +63 -0
- data/spec/ditty_spec.rb +9 -0
- data/spec/factories.rb +46 -0
- data/spec/fixtures/logger.yml +17 -0
- data/spec/fixtures/section.yml +3 -0
- data/spec/fixtures/settings.yml +8 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/api_shared_examples.rb +250 -0
- data/spec/support/crud_shared_examples.rb +145 -0
- data/views/403.haml +1 -1
- data/views/404.haml +2 -4
- data/views/500.haml +11 -0
- data/views/audit_logs/index.haml +32 -33
- data/views/auth/forgot_password.haml +32 -16
- data/views/auth/identity.haml +14 -13
- data/views/auth/ldap.haml +2 -2
- data/views/auth/login.haml +23 -17
- data/views/auth/register.haml +20 -18
- data/views/auth/register_identity.haml +27 -12
- data/views/auth/reset_password.haml +36 -19
- data/views/blank.haml +43 -0
- data/views/embedded.haml +17 -11
- data/views/index.haml +1 -1
- data/views/layout.haml +45 -30
- data/views/partials/actions.haml +15 -14
- data/views/partials/content_tag.haml +0 -0
- data/views/partials/delete_form.haml +1 -1
- data/views/partials/filter_control.haml +2 -2
- data/views/partials/footer.haml +6 -5
- data/views/partials/form_control.haml +19 -12
- data/views/partials/form_tag.haml +1 -1
- data/views/partials/navitems.haml +42 -0
- data/views/partials/notifications.haml +12 -8
- data/views/partials/pager.haml +44 -25
- data/views/partials/search.haml +15 -11
- data/views/partials/sidebar.haml +15 -37
- data/views/partials/sort_ui.haml +2 -0
- data/views/partials/topbar.haml +53 -0
- data/views/partials/user_associations.haml +32 -0
- data/views/quick_start.haml +23 -0
- data/views/roles/display.haml +27 -6
- data/views/roles/edit.haml +3 -3
- data/views/roles/form.haml +1 -0
- data/views/roles/index.haml +23 -16
- data/views/roles/new.haml +2 -2
- data/views/user_login_traits/display.haml +4 -4
- data/views/user_login_traits/edit.haml +3 -3
- data/views/user_login_traits/index.haml +23 -25
- data/views/user_login_traits/new.haml +2 -2
- data/views/users/display.haml +14 -15
- data/views/users/edit.haml +3 -3
- data/views/users/form.haml +0 -0
- data/views/users/index.haml +31 -24
- data/views/users/login_traits.haml +6 -8
- data/views/users/new.haml +2 -2
- data/views/users/profile.haml +15 -15
- data/views/users/user.haml +1 -1
- metadata +271 -63
- data/lib/ditty/controllers/roles.rb +0 -13
- data/lib/ditty/controllers/user_login_traits.rb +0 -18
- data/views/partials/navbar.haml +0 -22
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor/group'
|
4
|
+
require 'active_support/inflector'
|
5
|
+
|
6
|
+
module Ditty
|
7
|
+
module Generators
|
8
|
+
class ProjectGenerator < Thor::Group
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
attr_reader :name, :namespace, :folder
|
12
|
+
|
13
|
+
desc 'Initialize a new Ditty project in the current folder'
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@name = File.basename(Dir.getwd)
|
17
|
+
@folder = @name.underscore
|
18
|
+
@namespace = folder.classify
|
19
|
+
@name = @name.titleize
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.source_root
|
23
|
+
File.expand_path('../templates', __dir__)
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_startup_files
|
27
|
+
directory 'logs'
|
28
|
+
directory 'pids'
|
29
|
+
directory 'public'
|
30
|
+
directory '../../../views', 'views'
|
31
|
+
copy_file '.gitignore', './.gitignore'
|
32
|
+
copy_file 'env.example', './.env'
|
33
|
+
copy_file '.rubocop.yml', './.rubocop.yml'
|
34
|
+
copy_file '.rspec', './.rspec'
|
35
|
+
|
36
|
+
template 'lib/project.rb.erb', "lib/#{folder}.rb"
|
37
|
+
|
38
|
+
copy_file 'application.rb', './application.rb'
|
39
|
+
copy_file 'config.ru', './config.ru'
|
40
|
+
copy_file 'Rakefile', './Rakefile'
|
41
|
+
copy_file 'sidekiq.rb', './config/sidekiq.rb'
|
42
|
+
copy_file 'sidekiq.yml', './config/sidekiq.yml'
|
43
|
+
|
44
|
+
copy_file 'spec_helper.rb', './specs/spec_helper.rb'
|
45
|
+
copy_file '../../../spec/support/api_shared_examples.rb', './specs/support/api_shared_examples.rb'
|
46
|
+
copy_file '../../../spec/support/crud_shared_examples.rb', './specs/support/crud_shared_examples.rb'
|
47
|
+
|
48
|
+
template 'settings.yml.erb', './config/settings.yml'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -33,11 +33,12 @@ module Ditty
|
|
33
33
|
param :q, String
|
34
34
|
param :page, Integer, min: 1, default: 1
|
35
35
|
param :sort, String
|
36
|
-
param :order, String, in: %w[asc desc], transform: :downcase
|
36
|
+
param :order, String, in: %w[asc desc], transform: :downcase
|
37
37
|
# TODO: Can we dynamically validate the search / filter fields?
|
38
38
|
|
39
39
|
ds = dataset
|
40
40
|
ds = ds.dataset if ds.respond_to?(:dataset)
|
41
|
+
params[:order] ||= 'asc' if params[:sort]
|
41
42
|
return ds if params[:count] == 'all'
|
42
43
|
|
43
44
|
params[:count] = check_count
|
data/lib/ditty/helpers/pundit.rb
CHANGED
@@ -12,23 +12,39 @@ module Ditty
|
|
12
12
|
super
|
13
13
|
end
|
14
14
|
|
15
|
-
def permitted_attributes(record, action)
|
16
|
-
param_key = PolicyFinder.new(record).param_key
|
15
|
+
def permitted_attributes(record, action = nil)
|
17
16
|
policy = policy(record)
|
17
|
+
action ||= record.new? ? :create : :update
|
18
18
|
method_name = if policy.respond_to?("permitted_attributes_for_#{action}")
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
"permitted_attributes_for_#{action}"
|
20
|
+
else
|
21
|
+
'permitted_attributes'
|
22
|
+
end
|
23
|
+
policy.public_send(method_name)
|
24
|
+
end
|
23
25
|
|
24
|
-
|
26
|
+
def permitted_parameters(record, action = nil)
|
27
|
+
param_key = PolicyFinder.new(record).param_key
|
28
|
+
policy_fields = permitted_attributes(record, action)
|
25
29
|
request.params.fetch(param_key, {}).select do |key, _value|
|
26
30
|
policy_fields.include? key.to_sym
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
34
|
+
def permitted_response_attributes(record, method = :values)
|
35
|
+
policy = policy(record)
|
36
|
+
response = record.send(method)
|
37
|
+
|
38
|
+
return response unless policy.respond_to? :response_attributes
|
39
|
+
|
40
|
+
policy_fields = policy.response_attributes
|
41
|
+
response.select do |key, _value|
|
42
|
+
policy_fields.include? key.to_sym
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
30
46
|
def pundit_user
|
31
|
-
current_user
|
47
|
+
current_user unless current_user&.anonymous?
|
32
48
|
end
|
33
49
|
end
|
34
50
|
end
|
@@ -5,12 +5,12 @@ require 'csv'
|
|
5
5
|
module Ditty
|
6
6
|
module Helpers
|
7
7
|
module Response
|
8
|
-
def list_response(result)
|
8
|
+
def list_response(result, view: 'index')
|
9
9
|
respond_to do |format|
|
10
10
|
format.html do
|
11
11
|
actions = {}
|
12
12
|
actions["#{base_path}/new"] = "New #{heading}" if policy(settings.model_class).create?
|
13
|
-
haml :"#{view_location}
|
13
|
+
haml :"#{view_location}/#{view}",
|
14
14
|
locals: { list: result, title: heading(:list), actions: actions },
|
15
15
|
layout: layout
|
16
16
|
end
|
@@ -18,13 +18,14 @@ module Ditty
|
|
18
18
|
# TODO: Add links defined by actions (New #{heading})
|
19
19
|
total = result.respond_to?(:pagination_record_count) ? result.pagination_record_count : result.count
|
20
20
|
json(
|
21
|
-
'items' => result.all.map(
|
21
|
+
'items' => result.all.map { |e| permitted_response_attributes(e, :for_json) },
|
22
22
|
'page' => (params['page'] || 1).to_i,
|
23
23
|
'count' => result.count,
|
24
24
|
'total' => total
|
25
25
|
)
|
26
26
|
end
|
27
27
|
format.csv do
|
28
|
+
attachment "#{base_path}.csv"
|
28
29
|
CSV.generate do |csv|
|
29
30
|
csv << result.first.for_csv.keys
|
30
31
|
result.all.each do |r|
|
@@ -39,18 +40,18 @@ module Ditty
|
|
39
40
|
respond_to do |format|
|
40
41
|
format.html do
|
41
42
|
flash[:success] = "#{heading} Created"
|
42
|
-
redirect with_layout("#{base_path}/#{entity.
|
43
|
+
redirect with_layout(params[:redirect_to] || flash[:redirect_to] || "#{base_path}/#{entity.display_id}")
|
43
44
|
end
|
44
45
|
format.json do
|
45
46
|
content_type :json
|
46
|
-
redirect "#{base_path}/#{entity.
|
47
|
+
redirect "#{base_path}/#{entity.display_id}", 201
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
52
|
def actions(entity = nil)
|
52
53
|
actions = {}
|
53
|
-
actions["#{base_path}/#{entity.
|
54
|
+
actions["#{base_path}/#{entity.display_id}/edit"] = "Edit #{heading}" if entity && policy(entity).update?
|
54
55
|
actions["#{base_path}/new"] = "New #{heading}" if policy(settings.model_class).create?
|
55
56
|
actions
|
56
57
|
end
|
@@ -60,13 +61,15 @@ module Ditty
|
|
60
61
|
respond_to do |format|
|
61
62
|
format.html do
|
62
63
|
title = heading(:read) + (entity.respond_to?(:name) ? ": #{entity.name}" : '')
|
64
|
+
last_modified entity.updated_at if entity.respond_to?(:updated_at)
|
65
|
+
etag entity.etag if entity.respond_to?(:etag)
|
63
66
|
haml :"#{view_location}/display",
|
64
67
|
locals: { entity: entity, title: title, actions: actions },
|
65
68
|
layout: layout
|
66
69
|
end
|
67
70
|
format.json do
|
68
71
|
# TODO: Add links defined by actions (Edit #{heading})
|
69
|
-
json entity
|
72
|
+
json permitted_response_attributes(entity, :for_json)
|
70
73
|
end
|
71
74
|
format.csv do
|
72
75
|
CSV.generate do |csv|
|
@@ -82,11 +85,11 @@ module Ditty
|
|
82
85
|
format.html do
|
83
86
|
# TODO: Ability to customize the return path and message?
|
84
87
|
flash[:success] = "#{heading} Updated"
|
85
|
-
redirect with_layout("#{base_path}/#{entity.
|
88
|
+
redirect with_layout(params[:redirect_to] || flash[:redirect_to] || "#{base_path}/#{entity.display_id}")
|
86
89
|
end
|
87
90
|
format.json do
|
88
|
-
|
89
|
-
|
91
|
+
content_type :json
|
92
|
+
redirect "#{base_path}/#{entity.display_id}", 200, json(entity.for_json)
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
@@ -95,12 +98,11 @@ module Ditty
|
|
95
98
|
respond_to do |format|
|
96
99
|
format.html do
|
97
100
|
flash[:success] = "#{heading} Deleted"
|
98
|
-
redirect with_layout(base_path
|
101
|
+
redirect with_layout(params[:redirect_to] || flash[:redirect_to] || back || base_path)
|
99
102
|
end
|
100
103
|
format.json do
|
101
104
|
content_type :json
|
102
|
-
|
103
|
-
status 204
|
105
|
+
redirect base_path.to_s, 204
|
104
106
|
end
|
105
107
|
end
|
106
108
|
end
|
data/lib/ditty/helpers/views.rb
CHANGED
@@ -24,9 +24,11 @@ module Ditty
|
|
24
24
|
def form_control(name, model, opts = {})
|
25
25
|
label = opts.delete(:label) || name.to_s.titlecase
|
26
26
|
klass = opts.delete(:class) || 'form-control' unless opts[:type] == 'file'
|
27
|
+
klass = "#{klass} is-invalid" if model.errors[name]
|
27
28
|
group = opts.delete(:group) || model.class.to_s.demodulize.underscore
|
28
29
|
field = opts.delete(:field) || name
|
29
30
|
default = opts.delete(:default) || nil
|
31
|
+
help_text = opts.delete(:help_text) || nil
|
30
32
|
|
31
33
|
attributes = { type: 'text', id: name, name: "#{group}[#{name}]", class: klass }.merge(opts)
|
32
34
|
haml :'partials/form_control', locals: {
|
@@ -36,7 +38,8 @@ module Ditty
|
|
36
38
|
name: name,
|
37
39
|
group: group,
|
38
40
|
field: field,
|
39
|
-
default: default
|
41
|
+
default: default,
|
42
|
+
help_text: help_text
|
40
43
|
}
|
41
44
|
end
|
42
45
|
|
@@ -47,7 +50,8 @@ module Ditty
|
|
47
50
|
haml :'partials/filter_control', locals: {
|
48
51
|
name: filter[:name],
|
49
52
|
label: opts[:label] || filter[:name].to_s.titlecase,
|
50
|
-
options: send(meth)
|
53
|
+
options: send(meth),
|
54
|
+
total_filters: opts[:filters]
|
51
55
|
}
|
52
56
|
end
|
53
57
|
|
@@ -58,13 +62,13 @@ module Ditty
|
|
58
62
|
messages = flash(key).collect do |message|
|
59
63
|
" <div class='alert alert-#{message[0]} alert-dismissable' role='alert'>#{message[1]}</div>\n"
|
60
64
|
end
|
61
|
-
"<div id='#{id}'>\n
|
65
|
+
"<div id='#{id}'>\n#{messages.join}</div>"
|
62
66
|
end
|
63
67
|
|
64
68
|
def query_string(add = {})
|
65
69
|
qs = params.clone.merge(add)
|
66
70
|
qs.delete('captures')
|
67
|
-
Rack::Utils.build_query
|
71
|
+
Rack::Utils.build_query(qs.delete_if { |_k, v| v == '' })
|
68
72
|
end
|
69
73
|
|
70
74
|
def delete_form(entity, label = 'Delete')
|
@@ -90,7 +94,7 @@ module Ditty
|
|
90
94
|
def form_tag(url, options = {}, &block)
|
91
95
|
options[:form_verb] ||= :post
|
92
96
|
options[:attributes] ||= {}
|
93
|
-
options[:attributes] = {
|
97
|
+
options[:attributes] = { class: 'form-horizontal' }.merge options[:attributes]
|
94
98
|
options[:url] = options[:form_verb].to_sym == :get ? url : with_layout(url)
|
95
99
|
haml :'partials/form_tag', locals: options.merge(block: block)
|
96
100
|
end
|
@@ -98,7 +102,7 @@ module Ditty
|
|
98
102
|
def pagination(list, base_path, qp = {})
|
99
103
|
return unless list.respond_to?(:pagination_record_count) || list.respond_to?(:total_entries)
|
100
104
|
|
101
|
-
list = Ditty::Services::PaginationWrapper.new(list)
|
105
|
+
list = ::Ditty::Services::PaginationWrapper.new(list)
|
102
106
|
locals = {
|
103
107
|
first_link: "#{base_path}?" + query_string(qp.merge(page: 1)),
|
104
108
|
next_link: list.last_page? ? '#' : "#{base_path}?" + query_string(qp.merge(page: list.next_page)),
|
@@ -134,6 +138,24 @@ module Ditty
|
|
134
138
|
haml_tag :a, name, html_options
|
135
139
|
end
|
136
140
|
end
|
141
|
+
|
142
|
+
def sort_ui(field)
|
143
|
+
haml :'partials/sort_ui', locals: { field: field }
|
144
|
+
end
|
145
|
+
|
146
|
+
def sort_query(field)
|
147
|
+
query_string(
|
148
|
+
order: params[:sort] == field.to_s && params[:order] == 'asc' ? 'desc' : 'asc',
|
149
|
+
sort: field,
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
def sort_icon(field)
|
154
|
+
return 'fa-sort' unless params[:sort] == field.to_s
|
155
|
+
return 'fa-sort-up' if params[:order] == 'asc'
|
156
|
+
|
157
|
+
'fa-sort-down'
|
158
|
+
end
|
137
159
|
end
|
138
160
|
end
|
139
161
|
end
|
data/lib/ditty/listener.rb
CHANGED
@@ -17,7 +17,9 @@ module Ditty
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def method_missing(method, *args)
|
20
|
-
|
20
|
+
unless args[0].is_a?(Hash) && args[0][:target].is_a?(Sinatra::Base) && args[0][:target].settings.track_actions
|
21
|
+
return
|
22
|
+
end
|
21
23
|
|
22
24
|
log_action(
|
23
25
|
user_traits(args[0][:target]).merge(
|
@@ -64,12 +66,12 @@ module Ditty
|
|
64
66
|
def action_from(target, method)
|
65
67
|
return method unless method.to_s.start_with? 'component_'
|
66
68
|
|
67
|
-
target.class.to_s.demodulize.underscore
|
69
|
+
"#{target.class.to_s.demodulize.underscore}_#{method.to_s.gsub(/^component_/, '')}"
|
68
70
|
end
|
69
71
|
|
70
72
|
def log_action(values)
|
71
73
|
values[:user] ||= values[:target].current_user if values[:target]
|
72
|
-
@mutex.synchronize { Ditty::AuditLog.create values }
|
74
|
+
@mutex.synchronize { ::Ditty::AuditLog.create values }
|
73
75
|
end
|
74
76
|
|
75
77
|
def user_traits(target)
|
@@ -84,4 +86,4 @@ module Ditty
|
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
87
|
-
Wisper.subscribe(Ditty::Listener.new) unless ENV['RACK_ENV'] == 'test'
|
89
|
+
Wisper.subscribe(::Ditty::Listener.new) unless ENV['RACK_ENV'] == 'test'
|
@@ -8,7 +8,7 @@ module Ditty
|
|
8
8
|
class AcceptExtension
|
9
9
|
attr_reader :env, :regex, :content_type
|
10
10
|
|
11
|
-
def initialize(app, regex =
|
11
|
+
def initialize(app, regex = %r{\A(.*)\.json(/?)\Z}, content_type = 'application/json')
|
12
12
|
# @mutex = Mutex.new
|
13
13
|
@app = app
|
14
14
|
@regex = regex
|
@@ -19,7 +19,7 @@ module Ditty
|
|
19
19
|
@env = env
|
20
20
|
|
21
21
|
request = Rack::Request.new(env)
|
22
|
-
if request.path
|
22
|
+
if request.path&.match?(regex)
|
23
23
|
request.path_info = request.path_info.gsub(regex, '\1\2')
|
24
24
|
env = request.env
|
25
25
|
env['ACCEPT'] = content_type
|
@@ -16,8 +16,8 @@ module Ditty
|
|
16
16
|
begin
|
17
17
|
@app.call env
|
18
18
|
rescue StandardError => e
|
19
|
-
::Ditty::Services::Logger.
|
20
|
-
::Ditty::Services::Logger.
|
19
|
+
::Ditty::Services::Logger.error "Ditty Catchall: #{e.class}"
|
20
|
+
::Ditty::Services::Logger.error e
|
21
21
|
[500, {}, ['Unknown Error']]
|
22
22
|
end
|
23
23
|
end
|
data/lib/ditty/models/base.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'digest/sha2'
|
3
4
|
require 'sequel'
|
4
5
|
|
5
6
|
module Ditty
|
@@ -8,6 +9,14 @@ module Ditty
|
|
8
9
|
values
|
9
10
|
end
|
10
11
|
|
12
|
+
def display_id
|
13
|
+
self[:slug] || self[:guid] || self[:id]
|
14
|
+
end
|
15
|
+
|
16
|
+
def etag
|
17
|
+
Digest::SHA2.hexdigest values.to_json
|
18
|
+
end
|
19
|
+
|
11
20
|
alias for_csv for_json
|
12
21
|
end
|
13
22
|
end
|
@@ -37,6 +37,10 @@ module Ditty
|
|
37
37
|
}
|
38
38
|
end
|
39
39
|
|
40
|
+
def uid
|
41
|
+
user&.id
|
42
|
+
end
|
43
|
+
|
40
44
|
# Validation
|
41
45
|
def validate
|
42
46
|
super
|
@@ -55,7 +59,7 @@ module Ditty
|
|
55
59
|
# 1 Special Character
|
56
60
|
# 1 Number
|
57
61
|
# At least 8 characters
|
58
|
-
%r[\A(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#&$*)(}{%^=_+|\\:";'
|
62
|
+
%r[\A(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#&$*)(}{%^=_+|\\:";'<>,.\-/?\[\]])(?=.*[0-9]).{8,}\Z],
|
59
63
|
:password,
|
60
64
|
message: 'is not strong enough'
|
61
65
|
)
|
@@ -72,12 +76,12 @@ module Ditty
|
|
72
76
|
|
73
77
|
private
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
|
79
|
+
def encrypt_password
|
80
|
+
self.crypted_password = ::BCrypt::Password.create(password)
|
81
|
+
end
|
78
82
|
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
def password_required
|
84
|
+
crypted_password.blank? || !password.blank?
|
85
|
+
end
|
82
86
|
end
|
83
87
|
end
|