ditty 0.7.1 → 0.10.1
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 +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
|