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.
- checksums.yaml +4 -4
- data/.env.test +2 -0
- data/.gitignore +3 -0
- data/.pryrc +2 -0
- data/.rubocop.yml +24 -8
- data/.travis.yml +4 -8
- data/CNAME +1 -0
- data/Dockerfile +18 -0
- data/Gemfile.ci +0 -15
- data/Rakefile +5 -4
- data/Readme.md +24 -2
- data/_config.yml +1 -0
- data/config.ru +4 -4
- data/ditty.gemspec +31 -20
- 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.rb +30 -4
- data/lib/ditty/cli.rb +38 -5
- data/lib/ditty/components/ditty.rb +82 -0
- data/lib/ditty/controllers/application_controller.rb +267 -0
- data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +5 -7
- data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +56 -32
- data/lib/ditty/controllers/{component.rb → component_controller.rb} +35 -24
- data/lib/ditty/controllers/{main.rb → main_controller.rb} +7 -7
- 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} +17 -20
- data/lib/ditty/db.rb +9 -5
- data/lib/ditty/emails/base.rb +48 -34
- 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/authentication.rb +6 -5
- data/lib/ditty/helpers/component.rb +11 -2
- data/lib/ditty/helpers/pundit.rb +24 -8
- data/lib/ditty/helpers/response.rb +38 -15
- data/lib/ditty/helpers/views.rb +48 -6
- data/lib/ditty/listener.rb +44 -14
- data/lib/ditty/memcached.rb +8 -0
- data/lib/ditty/middleware/accept_extension.rb +4 -2
- data/lib/ditty/middleware/error_catchall.rb +4 -2
- data/lib/ditty/models/audit_log.rb +1 -0
- data/lib/ditty/models/base.rb +13 -0
- data/lib/ditty/models/identity.rb +10 -7
- data/lib/ditty/models/role.rb +2 -0
- data/lib/ditty/models/user.rb +40 -3
- data/lib/ditty/models/user_login_trait.rb +17 -0
- data/lib/ditty/policies/audit_log_policy.rb +6 -6
- data/lib/ditty/policies/role_policy.rb +3 -3
- data/lib/ditty/policies/user_login_trait_policy.rb +45 -0
- data/lib/ditty/policies/user_policy.rb +3 -3
- data/lib/ditty/rubocop.rb +3 -0
- data/lib/ditty/seed.rb +2 -0
- data/lib/ditty/services/authentication.rb +31 -15
- data/lib/ditty/services/email.rb +22 -12
- data/lib/ditty/services/logger.rb +30 -13
- data/lib/ditty/services/pagination_wrapper.rb +9 -5
- data/lib/ditty/services/settings.rb +19 -7
- data/lib/ditty/tasks/ditty.rake +127 -0
- data/lib/ditty/tasks/omniauth-ldap.rake +43 -0
- 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/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 +19 -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/rubocop/cop/ditty/call_services_directly.rb +42 -0
- data/migrate/20181209_add_user_login_traits.rb +16 -0
- data/migrate/20181209_extend_audit_log.rb +12 -0
- 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 +2 -0
- data/views/404.haml +2 -4
- data/views/500.haml +11 -0
- data/views/audit_logs/index.haml +32 -28
- data/views/auth/forgot_password.haml +32 -16
- data/views/auth/identity.haml +14 -13
- data/views/auth/ldap.haml +17 -0
- 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/emails/forgot_password.haml +1 -1
- data/views/emails/layouts/action.haml +10 -6
- data/views/emails/layouts/alert.haml +2 -1
- data/views/emails/layouts/billing.haml +2 -1
- data/views/embedded.haml +17 -11
- data/views/error.haml +8 -3
- 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 +13 -5
- data/views/partials/form_control.haml +30 -19
- 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/timespan_selector.haml +64 -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 -14
- data/views/roles/new.haml +2 -2
- data/views/user_login_traits/display.haml +32 -0
- data/views/user_login_traits/edit.haml +10 -0
- data/views/user_login_traits/form.haml +5 -0
- data/views/user_login_traits/index.haml +28 -0
- data/views/user_login_traits/new.haml +10 -0
- data/views/users/display.haml +15 -16
- 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 +25 -0
- data/views/users/new.haml +2 -2
- data/views/users/profile.haml +17 -15
- data/views/users/user.haml +1 -1
- metadata +314 -76
- data/lib/ditty/components/app.rb +0 -77
- data/lib/ditty/controllers/application.rb +0 -175
- data/lib/ditty/controllers/roles.rb +0 -16
- data/lib/ditty/rake_tasks.rb +0 -102
- data/views/partials/navbar.haml +0 -23
|
@@ -1,53 +1,63 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ditty/controllers/application_controller'
|
|
2
4
|
require 'ditty/services/email'
|
|
3
5
|
require 'securerandom'
|
|
4
6
|
|
|
5
7
|
module Ditty
|
|
6
|
-
class
|
|
8
|
+
class AuthController < ApplicationController
|
|
7
9
|
set track_actions: true
|
|
8
10
|
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
def redirect_path
|
|
12
|
+
return "#{settings.map_path}/" if omniauth_redirect_path.nil?
|
|
13
|
+
return "#{settings.map_path}/" if omniauth_redirect_path.match? %r{/#{settings.map_path}/auth/?}
|
|
14
|
+
|
|
15
|
+
omniauth_redirect_path
|
|
12
16
|
end
|
|
13
17
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
return "#{settings.map_path}/" if env['omniauth.origin'] =~ %r{/#{settings.map_path}/auth/?}
|
|
17
|
-
env['omniauth.origin']
|
|
18
|
+
def omniauth_redirect_path
|
|
19
|
+
env['omniauth.origin'] || request.session['omniauth.origin']
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def omniauth_callback(provider)
|
|
21
23
|
return failed_login unless env['omniauth.auth']
|
|
24
|
+
|
|
25
|
+
broadcast("before_#{provider}_login".to_sym, env['omniauth.auth'])
|
|
22
26
|
user = User.first(email: env['omniauth.auth']['info']['email'])
|
|
23
|
-
user = register_user if user.nil? &&
|
|
27
|
+
user = register_user if user.nil? && authorize(::Ditty::User, :register?)
|
|
24
28
|
return failed_login if user.nil?
|
|
29
|
+
|
|
30
|
+
broadcast("#{provider}_login".to_sym, user)
|
|
25
31
|
successful_login(user)
|
|
26
32
|
end
|
|
27
33
|
|
|
28
34
|
def failed_login
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
details = params[:message] || 'None'
|
|
36
|
+
logger.warn "Invalid Login: #{details}"
|
|
37
|
+
broadcast(:user_failed_login, target: self, details: details)
|
|
38
|
+
flash[:warning] = 'Invalid credentials. Please try again'
|
|
39
|
+
headers 'X-Authentication-Failure' => params[:message] if params[:message]
|
|
31
40
|
redirect "#{settings.map_path}/auth/login"
|
|
32
41
|
end
|
|
33
42
|
|
|
34
43
|
def successful_login(user)
|
|
35
44
|
halt 200 if request.xhr?
|
|
36
45
|
self.current_user = user
|
|
37
|
-
broadcast(:user_login, target: self
|
|
46
|
+
broadcast(:user_login, target: self)
|
|
38
47
|
flash[:success] = 'Logged In'
|
|
39
48
|
redirect redirect_path
|
|
40
49
|
end
|
|
41
50
|
|
|
42
51
|
def register_user
|
|
43
52
|
user = User.create(email: env['omniauth.auth']['info']['email'])
|
|
44
|
-
broadcast(:user_register, target: self, values: { user: user }
|
|
53
|
+
broadcast(:user_register, target: self, values: { user: user })
|
|
45
54
|
flash[:info] = 'Successfully Registered.'
|
|
46
55
|
user
|
|
47
56
|
end
|
|
48
57
|
|
|
49
58
|
before '/login' do
|
|
50
59
|
return if User.where(roles: Role.find_or_create(name: 'super_admin')).count.positive?
|
|
60
|
+
|
|
51
61
|
flash[:info] = 'Please register the super admin user.'
|
|
52
62
|
redirect "#{settings.map_path}/auth/register"
|
|
53
63
|
end
|
|
@@ -55,14 +65,24 @@ module Ditty
|
|
|
55
65
|
# TODO: Make this work for both LDAP and Identity
|
|
56
66
|
get '/login' do
|
|
57
67
|
authorize ::Ditty::Identity, :login
|
|
68
|
+
redirect settings.map_path if authenticated?
|
|
58
69
|
|
|
59
|
-
haml :'auth/login', locals: { title: 'Log In' }
|
|
70
|
+
haml :'auth/login', locals: { title: 'Log In' }, layout: :blank
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Custom login form for LDAP to allow CSRF checks. Set the `request_path` for
|
|
74
|
+
# the omniauth-ldap provider to another path so that this gest triggered
|
|
75
|
+
get '/ldap' do
|
|
76
|
+
authorize ::Ditty::Identity, :login
|
|
77
|
+
redirect settings.map_path if authenticated?
|
|
78
|
+
|
|
79
|
+
haml :'auth/ldap', locals: { title: 'Company Log In' }, layout: :blank
|
|
60
80
|
end
|
|
61
81
|
|
|
62
82
|
get '/forgot-password' do
|
|
63
83
|
authorize ::Ditty::Identity, :forgot_password
|
|
64
84
|
|
|
65
|
-
haml :'auth/forgot_password', locals: { title: 'Forgot your password?' }
|
|
85
|
+
haml :'auth/forgot_password', locals: { title: 'Forgot your password?' }, layout: :blank
|
|
66
86
|
end
|
|
67
87
|
|
|
68
88
|
post '/forgot-password' do
|
|
@@ -76,15 +96,18 @@ module Ditty
|
|
|
76
96
|
token = SecureRandom.hex(16)
|
|
77
97
|
identity.update(reset_token: token, reset_requested: Time.now)
|
|
78
98
|
# Send Email
|
|
79
|
-
reset_url = "#{request.base_url}#{settings.map_path}/reset-password?token=#{token}"
|
|
80
|
-
Ditty::Services::Email.deliver(
|
|
99
|
+
reset_url = "#{request.base_url}#{settings.map_path}/auth/reset-password?token=#{token}"
|
|
100
|
+
::Ditty::Services::Email.deliver(
|
|
81
101
|
:forgot_password,
|
|
82
102
|
email,
|
|
83
103
|
locals: { identity: identity, reset_url: reset_url, request: request }
|
|
84
104
|
)
|
|
85
105
|
end
|
|
86
106
|
flash[:info] = 'An email was sent to the email provided with instructions on how to reset your password'
|
|
87
|
-
redirect
|
|
107
|
+
redirect "#{settings.map_path}/auth/login"
|
|
108
|
+
rescue Sinatra::Param::InvalidParameterError
|
|
109
|
+
flash[:warning] = 'Email address not provided'
|
|
110
|
+
redirect back
|
|
88
111
|
end
|
|
89
112
|
|
|
90
113
|
get '/reset-password' do
|
|
@@ -92,9 +115,9 @@ module Ditty
|
|
|
92
115
|
|
|
93
116
|
param :token, String, required: true
|
|
94
117
|
identity = Identity[reset_token: params[:token]]
|
|
95
|
-
halt 404 unless identity
|
|
118
|
+
halt 404 unless identity&.reset_requested && identity.reset_requested > (Time.now - (24 * 60 * 60))
|
|
96
119
|
|
|
97
|
-
haml :'auth/reset_password', locals: { title: 'Reset your password', identity: identity }
|
|
120
|
+
haml :'auth/reset_password', locals: { title: 'Reset your password', identity: identity }, layout: :blank
|
|
98
121
|
end
|
|
99
122
|
|
|
100
123
|
put '/reset-password' do
|
|
@@ -104,15 +127,15 @@ module Ditty
|
|
|
104
127
|
halt 404 unless identity
|
|
105
128
|
authorize identity, :reset_password
|
|
106
129
|
|
|
107
|
-
identity_params =
|
|
130
|
+
identity_params = permitted_parameters(Identity, :update)
|
|
108
131
|
identity.set identity_params.merge(reset_token: nil, reset_requested: nil)
|
|
109
|
-
if identity.valid? && identity.
|
|
110
|
-
broadcast(:identity_update_password, target: self
|
|
132
|
+
if identity.valid? && identity.save_changes
|
|
133
|
+
broadcast(:identity_update_password, target: self)
|
|
111
134
|
flash[:success] = 'Password Updated'
|
|
112
135
|
redirect "#{settings.map_path}/auth/login"
|
|
113
136
|
else
|
|
114
|
-
broadcast(:identity_update_password_failed, target: self
|
|
115
|
-
haml :'auth/reset_password', locals: { title: 'Reset your password', identity: identity }
|
|
137
|
+
broadcast(:identity_update_password_failed, target: self)
|
|
138
|
+
haml :'auth/reset_password', locals: { title: 'Reset your password', identity: identity }, layout: :blank
|
|
116
139
|
end
|
|
117
140
|
end
|
|
118
141
|
|
|
@@ -121,7 +144,7 @@ module Ditty
|
|
|
121
144
|
authorize ::Ditty::User.new, :register
|
|
122
145
|
|
|
123
146
|
identity = Identity.new
|
|
124
|
-
haml :'auth/register', locals: { title: 'Register', identity: identity }
|
|
147
|
+
haml :'auth/register', locals: { title: 'Register', identity: identity }, layout: :blank
|
|
125
148
|
end
|
|
126
149
|
|
|
127
150
|
# Register Action
|
|
@@ -132,27 +155,28 @@ module Ditty
|
|
|
132
155
|
authorize user, :register
|
|
133
156
|
|
|
134
157
|
begin
|
|
158
|
+
identity.valid?
|
|
135
159
|
DB.transaction do
|
|
136
|
-
user.
|
|
160
|
+
user.save_changes
|
|
137
161
|
user.add_identity identity
|
|
138
|
-
broadcast(:user_register, target: self, values: { user: user }
|
|
162
|
+
broadcast(:user_register, target: self, values: { user: user })
|
|
139
163
|
flash[:info] = 'Successfully Registered. Please log in'
|
|
140
164
|
redirect "#{settings.map_path}/auth/login"
|
|
141
165
|
end
|
|
142
166
|
rescue Sequel::ValidationFailed
|
|
143
167
|
flash.now[:warning] = 'Could not complete the registration. Please try again.'
|
|
144
|
-
haml :'auth/register', locals: { identity: identity }
|
|
168
|
+
haml :'auth/register', locals: { identity: identity }, layout: :blank
|
|
145
169
|
end
|
|
146
170
|
end
|
|
147
171
|
|
|
148
172
|
# Logout Action
|
|
149
173
|
delete '/' do
|
|
150
|
-
broadcast(:user_logout, target: self
|
|
174
|
+
broadcast(:user_logout, target: self)
|
|
151
175
|
logout
|
|
152
176
|
|
|
153
177
|
halt 200 if request.xhr?
|
|
154
178
|
flash[:info] = 'Logged Out'
|
|
155
|
-
redirect(Ditty::Services::Settings[:logout_redirect_path] || "#{settings.map_path}/")
|
|
179
|
+
redirect(::Ditty::Services::Settings[:logout_redirect_path] || "#{settings.map_path}/")
|
|
156
180
|
end
|
|
157
181
|
|
|
158
182
|
# Unauthenticated
|
|
@@ -1,36 +1,50 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'ditty/controllers/
|
|
3
|
+
require 'ditty/controllers/application_controller'
|
|
4
4
|
require 'ditty/helpers/component'
|
|
5
5
|
require 'ditty/helpers/response'
|
|
6
6
|
require 'sinatra/json'
|
|
7
7
|
|
|
8
8
|
module Ditty
|
|
9
|
-
class
|
|
9
|
+
class ComponentController < ApplicationController
|
|
10
10
|
helpers Helpers::Component, Helpers::Response
|
|
11
11
|
|
|
12
12
|
set base_path: nil
|
|
13
13
|
set dehumanized: nil
|
|
14
14
|
set view_location: nil
|
|
15
15
|
set track_actions: false
|
|
16
|
+
set heading: nil
|
|
16
17
|
|
|
17
18
|
def read(id)
|
|
18
|
-
dataset.
|
|
19
|
+
dataset.with_pk(id)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def read!(id)
|
|
23
|
+
halt 404 unless (entity = read(id))
|
|
24
|
+
entity
|
|
19
25
|
end
|
|
20
26
|
|
|
21
27
|
def skip_verify!
|
|
22
28
|
@skip_verify = true
|
|
23
29
|
end
|
|
24
30
|
|
|
31
|
+
def trigger(event, attribs = {})
|
|
32
|
+
attribs[:target] ||= self
|
|
33
|
+
send(event, attribs) if respond_to? event
|
|
34
|
+
broadcast(event, attribs)
|
|
35
|
+
end
|
|
36
|
+
|
|
25
37
|
after do
|
|
26
38
|
return if settings.environment == 'production'
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
|
|
40
|
+
if (response.successful? || response.redirection?) && @skip_verify == false && (settings.environment != 'production')
|
|
41
|
+
verify_authorized
|
|
29
42
|
end
|
|
30
43
|
end
|
|
31
44
|
|
|
32
45
|
after '/' do
|
|
33
46
|
return if settings.environment == 'production' || request.request_method != 'GET'
|
|
47
|
+
|
|
34
48
|
verify_policy_scoped if (response.successful? || response.redirection?) && @skip_verify == false
|
|
35
49
|
end
|
|
36
50
|
|
|
@@ -40,7 +54,8 @@ module Ditty
|
|
|
40
54
|
|
|
41
55
|
result = list
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
trigger :component_list
|
|
58
|
+
|
|
44
59
|
list_response(result)
|
|
45
60
|
end
|
|
46
61
|
|
|
@@ -48,8 +63,7 @@ module Ditty
|
|
|
48
63
|
get '/new/?' do
|
|
49
64
|
authorize settings.model_class, :create
|
|
50
65
|
|
|
51
|
-
entity = settings.model_class.new(
|
|
52
|
-
session[:redirect_to] = request.fullpath
|
|
66
|
+
entity = settings.model_class.new(permitted_parameters(settings.model_class, :create))
|
|
53
67
|
haml :"#{view_location}/new",
|
|
54
68
|
locals: { entity: entity, title: heading(:new) },
|
|
55
69
|
layout: layout
|
|
@@ -57,12 +71,12 @@ module Ditty
|
|
|
57
71
|
|
|
58
72
|
# Create
|
|
59
73
|
post '/' do
|
|
60
|
-
entity = settings.model_class.new(
|
|
74
|
+
entity = settings.model_class.new(permitted_parameters(settings.model_class, :create))
|
|
61
75
|
authorize entity, :create
|
|
62
76
|
|
|
63
77
|
entity.db.transaction do
|
|
64
|
-
entity.
|
|
65
|
-
|
|
78
|
+
entity.save_changes # Will trigger a Sequel::ValidationFailed exception if the model is incorrect
|
|
79
|
+
trigger :component_create, entity: entity
|
|
66
80
|
end
|
|
67
81
|
|
|
68
82
|
create_response(entity)
|
|
@@ -70,20 +84,19 @@ module Ditty
|
|
|
70
84
|
|
|
71
85
|
# Read
|
|
72
86
|
get '/:id/?' do |id|
|
|
73
|
-
entity = read(id)
|
|
74
|
-
halt 404 unless entity
|
|
87
|
+
entity = read!(id)
|
|
75
88
|
authorize entity, :read
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
trigger :component_read, entity: entity
|
|
78
91
|
read_response(entity)
|
|
79
92
|
end
|
|
80
93
|
|
|
81
94
|
# Update Form
|
|
82
95
|
get '/:id/edit/?' do |id|
|
|
83
|
-
entity = read(id)
|
|
84
|
-
halt 404 unless entity
|
|
96
|
+
entity = read!(id)
|
|
85
97
|
authorize entity, :update
|
|
86
98
|
|
|
99
|
+
flash[:redirect_to] = "#{base_path}/#{entity.display_id}" unless flash.keep(:redirect_to)
|
|
87
100
|
haml :"#{view_location}/edit",
|
|
88
101
|
locals: { entity: entity, title: heading(:edit) },
|
|
89
102
|
layout: layout
|
|
@@ -91,27 +104,25 @@ module Ditty
|
|
|
91
104
|
|
|
92
105
|
# Update
|
|
93
106
|
put '/:id/?' do |id|
|
|
94
|
-
entity = read(id)
|
|
95
|
-
halt 404 unless entity
|
|
107
|
+
entity = read!(id)
|
|
96
108
|
authorize entity, :update
|
|
97
109
|
|
|
98
110
|
entity.db.transaction do
|
|
99
|
-
entity.set(
|
|
100
|
-
entity.
|
|
101
|
-
|
|
111
|
+
entity.set(permitted_parameters(settings.model_class, :update))
|
|
112
|
+
entity.save_changes # Will trigger a Sequel::ValidationFailed exception if the model is incorrect
|
|
113
|
+
trigger :component_update, entity: entity
|
|
102
114
|
end
|
|
103
115
|
|
|
104
116
|
update_response(entity)
|
|
105
117
|
end
|
|
106
118
|
|
|
107
119
|
delete '/:id/?' do |id|
|
|
108
|
-
entity = read(id)
|
|
109
|
-
halt 404 unless entity
|
|
120
|
+
entity = read!(id)
|
|
110
121
|
authorize entity, :delete
|
|
111
122
|
|
|
112
123
|
entity.db.transaction do
|
|
113
124
|
entity.destroy
|
|
114
|
-
|
|
125
|
+
trigger :component_delete, entity: entity
|
|
115
126
|
end
|
|
116
127
|
|
|
117
128
|
delete_response(entity)
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'ditty/controllers/
|
|
3
|
+
require 'ditty/controllers/application_controller'
|
|
4
4
|
require 'ditty/models/role'
|
|
5
5
|
require 'ditty/models/user'
|
|
6
|
+
require 'ditty/services/settings'
|
|
6
7
|
|
|
7
8
|
module Ditty
|
|
8
|
-
class
|
|
9
|
+
class MainController < ApplicationController
|
|
9
10
|
set track_actions: true
|
|
10
11
|
|
|
11
|
-
def find_template(views, name, engine, &block)
|
|
12
|
-
super(views, name, engine, &block) # Root
|
|
13
|
-
super(::Ditty::App.view_folder, name, engine, &block) # Basic Plugin
|
|
14
|
-
end
|
|
15
|
-
|
|
16
12
|
before '/' do
|
|
17
13
|
return if User.where(roles: Role.find_or_create(name: 'super_admin')).count.positive?
|
|
14
|
+
|
|
18
15
|
flash[:info] = 'Please register the super admin user.'
|
|
19
16
|
redirect "#{settings.map_path}/auth/register"
|
|
20
17
|
end
|
|
21
18
|
|
|
22
19
|
# Home Page
|
|
23
20
|
get '/' do
|
|
21
|
+
home_page = Services::Settings['ditty.home_page']
|
|
22
|
+
redirect "#{settings.map_path}#{home_page}" if home_page
|
|
23
|
+
|
|
24
24
|
authenticate!
|
|
25
25
|
haml :index, locals: { title: 'Home' }
|
|
26
26
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ditty/controllers/component_controller'
|
|
4
|
+
require 'ditty/models/role'
|
|
5
|
+
require 'ditty/policies/role_policy'
|
|
6
|
+
|
|
7
|
+
module Ditty
|
|
8
|
+
class RolesController < ::Ditty::ComponentController
|
|
9
|
+
SEARCHABLE = %i[name].freeze
|
|
10
|
+
|
|
11
|
+
set model_class: Role
|
|
12
|
+
|
|
13
|
+
helpers do
|
|
14
|
+
def parent_options(entity)
|
|
15
|
+
return policy_scope(::Ditty::Role) if entity.new?
|
|
16
|
+
|
|
17
|
+
policy_scope(::Ditty::Role)
|
|
18
|
+
.exclude(id: [entity.id] + entity.descendants.map(&:id))
|
|
19
|
+
.order(:name)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'ditty/controllers/component_controller'
|
|
4
|
+
require 'ditty/models/user_login_trait'
|
|
5
|
+
require 'ditty/policies/user_login_trait_policy'
|
|
6
|
+
|
|
7
|
+
module Ditty
|
|
8
|
+
class UserLoginTraitsController < ::Ditty::ComponentController
|
|
9
|
+
SEARCHABLE = %i[platform device browser ip_address].freeze
|
|
10
|
+
FILTERS = [
|
|
11
|
+
{ name: :user, field: 'user.email' },
|
|
12
|
+
{ name: :platform },
|
|
13
|
+
{ name: :device },
|
|
14
|
+
{ name: :browser }
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
set base_path: '/login-traits'
|
|
18
|
+
set model_class: UserLoginTrait
|
|
19
|
+
set heading: 'Login'
|
|
20
|
+
# set track_actions: true
|
|
21
|
+
|
|
22
|
+
helpers do
|
|
23
|
+
def user_options
|
|
24
|
+
policy_scope(::Ditty::User).as_hash(:email, :email)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def platform_options
|
|
28
|
+
policy_scope(::Ditty::UserLoginTrait).select(:platform).distinct.as_hash(:platform, :platform)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def device_options
|
|
32
|
+
policy_scope(::Ditty::UserLoginTrait).select(:device).distinct.as_hash(:device, :device)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def browser_options
|
|
36
|
+
policy_scope(::Ditty::UserLoginTrait).select(:browser).distinct.as_hash(:browser, :browser)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def list
|
|
41
|
+
return super if params[:sort]
|
|
42
|
+
|
|
43
|
+
super.order(:updated_at).reverse
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|