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,23 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'ditty/controllers/
|
|
3
|
+
require 'ditty/controllers/component_controller'
|
|
4
4
|
require 'ditty/models/user'
|
|
5
|
+
require 'ditty/models/user_login_trait'
|
|
5
6
|
require 'ditty/policies/user_policy'
|
|
6
7
|
require 'ditty/models/identity'
|
|
7
8
|
require 'ditty/policies/identity_policy'
|
|
8
9
|
|
|
9
10
|
module Ditty
|
|
10
|
-
class
|
|
11
|
+
class UsersController < ::Ditty::ComponentController
|
|
11
12
|
SEARCHABLE = %i[name surname email].freeze
|
|
12
13
|
|
|
13
14
|
set model_class: User
|
|
14
15
|
set track_actions: true
|
|
15
16
|
|
|
16
|
-
def find_template(views, name, engine, &block)
|
|
17
|
-
super(views, name, engine, &block) # Root
|
|
18
|
-
super(::Ditty::App.view_folder, name, engine, &block) # Ditty
|
|
19
|
-
end
|
|
20
|
-
|
|
21
17
|
# New
|
|
22
18
|
get '/new' do
|
|
23
19
|
authorize settings.model_class, :create
|
|
@@ -32,8 +28,8 @@ module Ditty
|
|
|
32
28
|
|
|
33
29
|
locals = { title: heading(:new) }
|
|
34
30
|
|
|
35
|
-
user_params =
|
|
36
|
-
identity_params =
|
|
31
|
+
user_params = permitted_parameters(User, :create)
|
|
32
|
+
identity_params = permitted_parameters(Identity, :create)
|
|
37
33
|
user_params['email'] = identity_params['username']
|
|
38
34
|
roles = user_params.delete('role_id')
|
|
39
35
|
|
|
@@ -42,25 +38,24 @@ module Ditty
|
|
|
42
38
|
|
|
43
39
|
DB.transaction(isolation: :serializable) do
|
|
44
40
|
begin
|
|
45
|
-
identity.
|
|
41
|
+
identity.save_changes
|
|
46
42
|
rescue Sequel::ValidationFailed
|
|
47
43
|
raise unless request.accept? 'text/html'
|
|
44
|
+
|
|
48
45
|
status 400
|
|
49
46
|
locals = { title: heading(:new), entity: user, identity: identity }
|
|
50
47
|
return haml(:"#{view_location}/new", locals: locals)
|
|
51
48
|
end
|
|
52
|
-
user.
|
|
49
|
+
user.save_changes
|
|
53
50
|
user.add_identity identity
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
roles.
|
|
57
|
-
user.add_role(role_id) unless user.roles.map(&:id).include? role_id.to_i
|
|
58
|
-
end
|
|
52
|
+
roles&.each do |role_id|
|
|
53
|
+
user.add_role(role_id) unless user.roles.map(&:id).include? role_id.to_i
|
|
59
54
|
end
|
|
60
55
|
user.check_roles
|
|
61
56
|
end
|
|
62
57
|
|
|
63
|
-
broadcast(:component_create, target: self)
|
|
58
|
+
broadcast(:component_create, target: self, entity: user)
|
|
64
59
|
create_response(user)
|
|
65
60
|
end
|
|
66
61
|
|
|
@@ -70,10 +65,10 @@ module Ditty
|
|
|
70
65
|
halt 404 unless entity
|
|
71
66
|
authorize entity, :update
|
|
72
67
|
|
|
73
|
-
values =
|
|
68
|
+
values = permitted_parameters(settings.model_class, :update)
|
|
74
69
|
roles = values.delete('role_id')
|
|
75
70
|
entity.set values
|
|
76
|
-
entity.
|
|
71
|
+
entity.save_changes # Will trigger a Sequel::ValidationFailed exception if the model is incorrect
|
|
77
72
|
|
|
78
73
|
if roles
|
|
79
74
|
entity.remove_all_roles
|
|
@@ -99,9 +94,10 @@ module Ditty
|
|
|
99
94
|
return redirect back
|
|
100
95
|
end
|
|
101
96
|
|
|
102
|
-
values =
|
|
97
|
+
values = permitted_parameters(Identity, :create)
|
|
103
98
|
identity.set values
|
|
104
|
-
if identity.valid?
|
|
99
|
+
if identity.valid?
|
|
100
|
+
identity.save_changes
|
|
105
101
|
broadcast(:identity_update_password, target: self)
|
|
106
102
|
flash[:success] = 'Password Updated'
|
|
107
103
|
redirect back
|
|
@@ -134,6 +130,7 @@ module Ditty
|
|
|
134
130
|
halt 404 unless entity
|
|
135
131
|
authorize entity, :read
|
|
136
132
|
|
|
133
|
+
flash[:redirect_to] = request.path
|
|
137
134
|
haml :"#{view_location}/profile", locals: { entity: entity, identity: entity.identity.first, title: 'My Account' }
|
|
138
135
|
end
|
|
139
136
|
end
|
data/lib/ditty/db.rb
CHANGED
|
@@ -8,7 +8,7 @@ require 'active_support/core_ext/object/blank'
|
|
|
8
8
|
pool_timeout = (ENV['DB_POOL_TIMEOUT'] || 5).to_i
|
|
9
9
|
|
|
10
10
|
if defined? DB
|
|
11
|
-
Ditty::Services::Logger.
|
|
11
|
+
::Ditty::Services::Logger.warn 'Database connection already set up'
|
|
12
12
|
elsif ENV['DATABASE_URL'].blank? == false
|
|
13
13
|
# Delete DATABASE_URL from the environment, so it isn't accidently
|
|
14
14
|
# passed to subprocesses. DATABASE_URL may contain passwords.
|
|
@@ -18,12 +18,16 @@ elsif ENV['DATABASE_URL'].blank? == false
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
DB.sql_log_level = (ENV['SEQUEL_LOGGING_LEVEL'] || :debug).to_sym
|
|
21
|
-
DB.loggers << Ditty::Services::Logger.
|
|
21
|
+
DB.loggers << ::Ditty::Services::Logger if ENV['DB_DEBUG'].to_i == 1
|
|
22
22
|
DB.extension(:pagination)
|
|
23
|
+
DB.extension(:schema_caching)
|
|
24
|
+
DB.load_schema_cache?('./config/schema.dump')
|
|
23
25
|
|
|
24
|
-
Sequel::Model.plugin :
|
|
25
|
-
Sequel::Model.plugin :
|
|
26
|
+
Sequel::Model.plugin :auto_validations
|
|
27
|
+
Sequel::Model.plugin :string_stripper
|
|
26
28
|
Sequel::Model.plugin :timestamps, update_on_create: true
|
|
29
|
+
Sequel::Model.plugin :update_or_create
|
|
30
|
+
Sequel::Model.plugin :validation_helpers
|
|
27
31
|
else
|
|
28
|
-
Ditty::Services::Logger.
|
|
32
|
+
::Ditty::Services::Logger.error 'No database connection set up'
|
|
29
33
|
end
|
data/lib/ditty/emails/base.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'haml'
|
|
2
|
-
require 'ditty/components/
|
|
4
|
+
require 'ditty/components/ditty'
|
|
3
5
|
|
|
4
6
|
module Ditty
|
|
5
7
|
module Emails
|
|
@@ -15,60 +17,72 @@ module Ditty
|
|
|
15
17
|
def deliver!(to = nil, locals = {})
|
|
16
18
|
options[:to] = to unless to.nil?
|
|
17
19
|
@locals.merge!(locals)
|
|
18
|
-
%i[to from subject].each do |param|
|
|
19
|
-
|
|
20
|
+
%i[to from subject content_type].each do |param|
|
|
21
|
+
next unless options[param]
|
|
22
|
+
|
|
23
|
+
@locals[param] ||= options[param]
|
|
24
|
+
mail.send(param, options[param])
|
|
25
|
+
end
|
|
26
|
+
html = content
|
|
27
|
+
mail.html_part do
|
|
28
|
+
body html
|
|
20
29
|
end
|
|
21
|
-
mail.body content
|
|
22
30
|
mail.deliver!
|
|
23
31
|
end
|
|
24
32
|
|
|
25
33
|
def method_missing(method, *args, &block)
|
|
26
34
|
return super unless respond_to_missing?(method)
|
|
35
|
+
|
|
27
36
|
mail.send(method, *args, &block)
|
|
28
37
|
end
|
|
29
38
|
|
|
30
39
|
def respond_to_missing?(method, _include_private = false)
|
|
31
|
-
mail.respond_to?
|
|
40
|
+
return true if mail.respond_to?(method)
|
|
41
|
+
|
|
42
|
+
super
|
|
32
43
|
end
|
|
33
44
|
|
|
34
45
|
private
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Haml::Engine.new(layout_haml).render(Object.new, content: result)
|
|
40
|
-
end
|
|
47
|
+
def content
|
|
48
|
+
result = Haml::Engine.new(content_haml).render(Object.new, locals)
|
|
49
|
+
return result unless options[:layout]
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
end
|
|
51
|
+
Haml::Engine.new(layout_haml).render(Object.new, locals.merge(content: result))
|
|
52
|
+
end
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
def content_haml
|
|
55
|
+
read_template(options[:view])
|
|
56
|
+
end
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
def layout_haml
|
|
59
|
+
read_template("layouts/#{options[:layout]}") if options[:layout]
|
|
60
|
+
end
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
def read_template(template)
|
|
63
|
+
File.read(find_template("emails/#{template}"))
|
|
64
|
+
end
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
template = File.expand_path("./#{file}.haml", App.view_folder)
|
|
62
|
-
return template if File.file? template
|
|
63
|
-
file
|
|
64
|
-
end
|
|
66
|
+
def base_options
|
|
67
|
+
{ subject: '(No Subject)', from: 'no-reply@ditty.io', view: :base, content_type: 'text/html; charset=UTF-8' }
|
|
68
|
+
end
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
def find_template(file)
|
|
71
|
+
template = File.expand_path("./views/#{file}.haml")
|
|
72
|
+
return template if File.file? template
|
|
73
|
+
|
|
74
|
+
template = File.expand_path("./#{file}.haml", App.view_folder)
|
|
75
|
+
return template if File.file? template
|
|
76
|
+
|
|
77
|
+
file
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class << self
|
|
81
|
+
def deliver!(to = nil, options = {})
|
|
82
|
+
locals = options[:locals] || {}
|
|
83
|
+
new(options).deliver!(to, locals)
|
|
84
|
+
end
|
|
70
85
|
end
|
|
71
|
-
end
|
|
72
86
|
end
|
|
73
87
|
end
|
|
74
88
|
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'thor/group'
|
|
4
|
+
require 'active_support/inflector'
|
|
5
|
+
|
|
6
|
+
module Ditty
|
|
7
|
+
module Generators
|
|
8
|
+
class CrudGenerator < Thor::Group
|
|
9
|
+
include Thor::Actions
|
|
10
|
+
attr_reader :namespace, :folder, :views_folder, :controller_name, :model_name, :policy_name # , :file_name
|
|
11
|
+
|
|
12
|
+
desc 'Create a CRUD Endpoint including the Model, Controller, Policy, Views and GraphQL Types'
|
|
13
|
+
argument :name, type: :string, desc: 'Name of the Model, eg. MyApp::User'
|
|
14
|
+
|
|
15
|
+
# --no-views make views optional
|
|
16
|
+
class_option :views, type: :boolean, default: true, desc: 'Generate views for controller'
|
|
17
|
+
|
|
18
|
+
def self.source_root
|
|
19
|
+
File.dirname(__FILE__)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def setup
|
|
23
|
+
@namespace = name.deconstantize
|
|
24
|
+
@folder = namespace.underscore
|
|
25
|
+
@model_name = name.demodulize
|
|
26
|
+
@views_folder = File.join('views', model_name.pluralize.underscore)
|
|
27
|
+
@controller_name = "#{model_name.pluralize}Controller"
|
|
28
|
+
@policy_name = "#{model_name}Policy"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def create_model
|
|
32
|
+
filename = File.join("lib/#{folder}/models", "#{model_name.underscore}.rb")
|
|
33
|
+
template '../templates/model.rb.erb', filename
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
puts "Could not generate model for #{model_name}: #{e.message}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def create_controller
|
|
39
|
+
filename = File.join("lib/#{folder}/controllers", "#{controller_name.underscore}.rb")
|
|
40
|
+
template '../templates/controller.rb.erb', filename
|
|
41
|
+
# TODO: Insert the route into the component file
|
|
42
|
+
# insert_into_file 'config.ru', "use #{class_name}\n", after: 'run ApplicationController\n'
|
|
43
|
+
rescue StandardError => e
|
|
44
|
+
puts "Could not generate controller for #{model_name}: #{e.message}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_policy
|
|
48
|
+
filename = File.join("lib/#{folder}/policies", "#{policy_name.underscore}.rb")
|
|
49
|
+
template '../templates/policy.rb.erb', filename
|
|
50
|
+
rescue StandardError => e
|
|
51
|
+
puts "Could not generate policy for #{model_name}: #{e.message}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def create_type
|
|
55
|
+
filename = File.join("lib/#{folder}/types", "#{model_name.underscore}_type.rb")
|
|
56
|
+
template '../templates/type.rb.erb', filename
|
|
57
|
+
rescue StandardError => e
|
|
58
|
+
puts "Could not generate type for #{model_name}: #{e.message}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def create_views
|
|
62
|
+
return unless options[:views]
|
|
63
|
+
|
|
64
|
+
directory '../templates/views', views_folder
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def meta_columns
|
|
70
|
+
%i[id guid slug created_at updated_at]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def columns
|
|
74
|
+
require "#{folder}/models/#{model_name.underscore}"
|
|
75
|
+
name.constantize.columns
|
|
76
|
+
rescue StandardError
|
|
77
|
+
[]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def schema
|
|
81
|
+
require "#{folder}/models/#{model_name.underscore}"
|
|
82
|
+
name.constantize.db_schema
|
|
83
|
+
rescue StandardError
|
|
84
|
+
[]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def many_to_ones
|
|
88
|
+
DB.foreign_key_list(model_name.underscore.pluralize)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def name_column(table)
|
|
92
|
+
candidates = DB.schema(table.to_sym).to_h.keys - DB.foreign_key_list(table.to_sym).map do |e|
|
|
93
|
+
e[:columns]
|
|
94
|
+
end.flatten
|
|
95
|
+
(candidates - meta_columns).first
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def graphql_types
|
|
99
|
+
@graphql_types ||= Hash.new('String').merge(
|
|
100
|
+
integer: 'Integer',
|
|
101
|
+
boolean: 'Boolean',
|
|
102
|
+
datetime: 'GraphQL::Types::ISO8601DateTime'
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def input_types
|
|
107
|
+
@input_types ||= Hash.new('text').merge(
|
|
108
|
+
integer: 'number',
|
|
109
|
+
datetime: 'date'
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'thor/group'
|
|
4
|
+
require 'active_support/inflector'
|
|
5
|
+
|
|
6
|
+
module Ditty
|
|
7
|
+
module Generators
|
|
8
|
+
class MigrationGenerator < Thor::Group
|
|
9
|
+
include Thor::Actions
|
|
10
|
+
|
|
11
|
+
attr_reader :namespace, :folder
|
|
12
|
+
|
|
13
|
+
desc 'Creates a new Sequel migration for the current project'
|
|
14
|
+
argument :name, type: :string, desc: 'Name of the migration'
|
|
15
|
+
|
|
16
|
+
def self.source_root
|
|
17
|
+
File.expand_path('../templates', __dir__)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_model
|
|
21
|
+
filename = File.join('migrations', "#{Time.now.strftime('%Y%m%d')}_#{name.underscore}.rb")
|
|
22
|
+
template '../templates/migration.rb.erb', filename
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -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
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'ditty/models/user'
|
|
4
|
-
require 'ditty/models/role'
|
|
5
|
-
require 'ditty/models/identity'
|
|
6
4
|
|
|
7
5
|
module Ditty
|
|
8
6
|
module Helpers
|
|
9
7
|
module Authentication
|
|
10
8
|
def current_user
|
|
11
9
|
return nil if current_user_id.nil?
|
|
10
|
+
|
|
12
11
|
@current_user ||= User[current_user_id]
|
|
13
12
|
end
|
|
14
13
|
|
|
@@ -19,8 +18,9 @@ module Ditty
|
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
def current_user_id
|
|
22
|
-
return env['rack.session']['user_id'] if env['rack.session']
|
|
23
|
-
|
|
21
|
+
return env['rack.session']['user_id'] if env['rack.session'] && env['rack.session']['user_id']
|
|
22
|
+
|
|
23
|
+
env['omniauth.auth']&.uid
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def authenticate
|
|
@@ -33,11 +33,12 @@ module Ditty
|
|
|
33
33
|
|
|
34
34
|
def authenticate!
|
|
35
35
|
raise NotAuthenticated unless authenticated?
|
|
36
|
+
|
|
36
37
|
true
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def logout
|
|
40
|
-
env['rack.session']
|
|
41
|
+
env['rack.session']&.delete('user_id')
|
|
41
42
|
env.delete('omniauth.auth')
|
|
42
43
|
end
|
|
43
44
|
end
|