goodmin 0.0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1359 -0
- data/Rakefile +56 -0
- data/app/assets/stylesheets/goodmin/application.css +75 -0
- data/app/controllers/goodmin/application_controller.rb +43 -0
- data/app/controllers/goodmin/resource_controller.rb +235 -0
- data/app/helpers/goodmin/application_helper.rb +45 -0
- data/app/javascript/goodmin/application.js +8 -0
- data/app/javascript/goodmin/controllers/batch_actions_controller.js +101 -0
- data/app/javascript/goodmin/controllers/datetimepicker_controller.js +24 -0
- data/app/javascript/goodmin/controllers/navigation_controller.js +30 -0
- data/app/jobs/goodmin/application_job.rb +4 -0
- data/app/mailers/goodmin/application_mailer.rb +6 -0
- data/app/models/goodmin/application_record.rb +5 -0
- data/app/views/goodmin/application/welcome.html.erb +17 -0
- data/app/views/goodmin/fields/association/_form.html.erb +19 -0
- data/app/views/goodmin/fields/association/_index.html.erb +6 -0
- data/app/views/goodmin/fields/association/_show.html.erb +6 -0
- data/app/views/goodmin/fields/boolean/_form.html.erb +7 -0
- data/app/views/goodmin/fields/boolean/_index.html.erb +1 -0
- data/app/views/goodmin/fields/boolean/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date_time/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_show.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_index.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_show.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_form.html.erb +6 -0
- data/app/views/goodmin/fields/nested_has_one/_index.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_show.html.erb +1 -0
- data/app/views/goodmin/fields/number/_form.html.erb +5 -0
- data/app/views/goodmin/fields/number/_index.html.erb +1 -0
- data/app/views/goodmin/fields/number/_show.html.erb +1 -0
- data/app/views/goodmin/fields/password/_form.html.erb +5 -0
- data/app/views/goodmin/fields/password/_index.html.erb +1 -0
- data/app/views/goodmin/fields/password/_show.html.erb +1 -0
- data/app/views/goodmin/fields/select/_form.html.erb +5 -0
- data/app/views/goodmin/fields/select/_index.html.erb +1 -0
- data/app/views/goodmin/fields/select/_show.html.erb +1 -0
- data/app/views/goodmin/fields/string/_form.html.erb +5 -0
- data/app/views/goodmin/fields/string/_index.html.erb +1 -0
- data/app/views/goodmin/fields/string/_show.html.erb +1 -0
- data/app/views/goodmin/fields/text/_form.html.erb +5 -0
- data/app/views/goodmin/fields/text/_index.html.erb +1 -0
- data/app/views/goodmin/fields/text/_show.html.erb +1 -0
- data/app/views/goodmin/resource/_actions.html.erb +9 -0
- data/app/views/goodmin/resource/_batch_actions.html.erb +12 -0
- data/app/views/goodmin/resource/_breadcrumb.html.erb +33 -0
- data/app/views/goodmin/resource/_breadcrumb_actions.html.erb +41 -0
- data/app/views/goodmin/resource/_button_actions.html.erb +3 -0
- data/app/views/goodmin/resource/_errors.html.erb +9 -0
- data/app/views/goodmin/resource/_export_actions.html.erb +15 -0
- data/app/views/goodmin/resource/_filters.html.erb +22 -0
- data/app/views/goodmin/resource/_form.html.erb +26 -0
- data/app/views/goodmin/resource/_pagination.html.erb +40 -0
- data/app/views/goodmin/resource/_scopes.html.erb +14 -0
- data/app/views/goodmin/resource/_table.html.erb +45 -0
- data/app/views/goodmin/resource/columns/_actions.html.erb +28 -0
- data/app/views/goodmin/resource/edit.html.erb +5 -0
- data/app/views/goodmin/resource/index.csv.csvbuilder +5 -0
- data/app/views/goodmin/resource/index.html.erb +10 -0
- data/app/views/goodmin/resource/index.json.jbuilder +3 -0
- data/app/views/goodmin/resource/new.html.erb +5 -0
- data/app/views/goodmin/resource/show.html.erb +11 -0
- data/app/views/goodmin/resource/show.json.jbuilder +1 -0
- data/app/views/goodmin/sessions/new.html.erb +11 -0
- data/app/views/goodmin/shared/_navigation.html.erb +0 -0
- data/app/views/goodmin/shared/_navigation_aside.html.erb +7 -0
- data/app/views/layouts/goodmin/_content.html.erb +13 -0
- data/app/views/layouts/goodmin/_layout.html.erb +22 -0
- data/app/views/layouts/goodmin/application.html.erb +28 -0
- data/app/views/layouts/goodmin/login.html.erb +18 -0
- data/config/importmap.rb +5 -0
- data/config/locales/en.yml +49 -0
- data/config/locales/pl-BR.yml +49 -0
- data/config/locales/pt-BR.yml +49 -0
- data/config/locales/sv.yml +49 -0
- data/config/routes.rb +3 -0
- data/lib/generators/goodmin/authentication/authentication_generator.rb +41 -0
- data/lib/generators/goodmin/authentication/templates/sessions_controller.rb +9 -0
- data/lib/generators/goodmin/install/install_generator.rb +41 -0
- data/lib/generators/goodmin/policy/policy_generator.rb +7 -0
- data/lib/generators/goodmin/policy/templates/policy.rb +23 -0
- data/lib/generators/goodmin/resource/resource_generator.rb +31 -0
- data/lib/generators/goodmin/resource/templates/resource.rb +25 -0
- data/lib/generators/goodmin/resource/templates/resource_controller.rb +9 -0
- data/lib/generators/goodmin/resource/templates/resource_model.rb +4 -0
- data/lib/generators/goodmin/resource/templates/resource_service.rb +23 -0
- data/lib/goodmin/authentication/sessions_controller.rb +46 -0
- data/lib/goodmin/authentication/user.rb +27 -0
- data/lib/goodmin/authentication.rb +35 -0
- data/lib/goodmin/authorization/policy.rb +41 -0
- data/lib/goodmin/authorization.rb +69 -0
- data/lib/goodmin/engine.rb +30 -0
- data/lib/goodmin/fields/association.rb +62 -0
- data/lib/goodmin/fields/base.rb +57 -0
- data/lib/goodmin/fields/boolean.rb +6 -0
- data/lib/goodmin/fields/date.rb +6 -0
- data/lib/goodmin/fields/date_time.rb +6 -0
- data/lib/goodmin/fields/enum.rb +15 -0
- data/lib/goodmin/fields/nested_has_one.rb +41 -0
- data/lib/goodmin/fields/number.rb +6 -0
- data/lib/goodmin/fields/password.rb +6 -0
- data/lib/goodmin/fields/select.rb +19 -0
- data/lib/goodmin/fields/string.rb +6 -0
- data/lib/goodmin/fields/text.rb +6 -0
- data/lib/goodmin/generators/base.rb +49 -0
- data/lib/goodmin/generators/named_base.rb +31 -0
- data/lib/goodmin/helpers/application.rb +47 -0
- data/lib/goodmin/helpers/batch_actions.rb +21 -0
- data/lib/goodmin/helpers/filters.rb +123 -0
- data/lib/goodmin/helpers/forms.rb +42 -0
- data/lib/goodmin/helpers/navigation.rb +52 -0
- data/lib/goodmin/helpers/tables.rb +25 -0
- data/lib/goodmin/helpers/translations.rb +19 -0
- data/lib/goodmin/paginator.rb +55 -0
- data/lib/goodmin/resolver.rb +141 -0
- data/lib/goodmin/resources/attribute.rb +46 -0
- data/lib/goodmin/resources/form_builder.rb +96 -0
- data/lib/goodmin/resources/form_component.rb +65 -0
- data/lib/goodmin/resources/form_components/col.rb +33 -0
- data/lib/goodmin/resources/form_components/row.rb +25 -0
- data/lib/goodmin/resources/form_components/section.rb +51 -0
- data/lib/goodmin/resources/form_components/tab.rb +49 -0
- data/lib/goodmin/resources/resource/associations.rb +23 -0
- data/lib/goodmin/resources/resource/batch_actions.rb +56 -0
- data/lib/goodmin/resources/resource/filters.rb +44 -0
- data/lib/goodmin/resources/resource/ordering.rb +41 -0
- data/lib/goodmin/resources/resource/pagination.rb +22 -0
- data/lib/goodmin/resources/resource/scopes.rb +61 -0
- data/lib/goodmin/resources/resource.rb +199 -0
- data/lib/goodmin/resources/resource_controller/batch_actions.rb +49 -0
- data/lib/goodmin/resources/resource_service/associations.rb +23 -0
- data/lib/goodmin/resources/resource_service/batch_actions.rb +52 -0
- data/lib/goodmin/resources/resource_service/filters.rb +44 -0
- data/lib/goodmin/resources/resource_service/ordering.rb +41 -0
- data/lib/goodmin/resources/resource_service/pagination.rb +22 -0
- data/lib/goodmin/resources/resource_service/scopes.rb +61 -0
- data/lib/goodmin/resources/resource_service.rb +199 -0
- data/lib/goodmin/service_locator.rb +25 -0
- data/lib/goodmin/version.rb +3 -0
- data/lib/goodmin.rb +44 -0
- data/lib/tasks/goodmin_tasks.rake +4 -0
- metadata +461 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
en:
|
|
2
|
+
goodmin:
|
|
3
|
+
title: Goodmin
|
|
4
|
+
batch_actions:
|
|
5
|
+
buttons:
|
|
6
|
+
select_all: Select all
|
|
7
|
+
deselect_all: Deselect all
|
|
8
|
+
confirm_message: Are you sure?
|
|
9
|
+
filters:
|
|
10
|
+
select:
|
|
11
|
+
placeholder:
|
|
12
|
+
one: Select something
|
|
13
|
+
many: Select something
|
|
14
|
+
buttons:
|
|
15
|
+
apply: Filter
|
|
16
|
+
clear: Clear filter
|
|
17
|
+
actions:
|
|
18
|
+
label: Actions
|
|
19
|
+
show: Show
|
|
20
|
+
show_title: Show %{resource}
|
|
21
|
+
edit: Edit
|
|
22
|
+
edit_title: Edit %{resource}
|
|
23
|
+
destroy: Destroy
|
|
24
|
+
destroy_title: Destroy %{resource}
|
|
25
|
+
confirm_message: Are you sure?
|
|
26
|
+
export: Export
|
|
27
|
+
export_as: As
|
|
28
|
+
associations:
|
|
29
|
+
label: Nested resources
|
|
30
|
+
sessions:
|
|
31
|
+
sign_in: Sign in
|
|
32
|
+
sign_out: Sign out
|
|
33
|
+
signed_in: Signed in
|
|
34
|
+
signed_out: Signed out
|
|
35
|
+
failed_sign_in: Invalid credentials
|
|
36
|
+
flash:
|
|
37
|
+
create: "%{resource} was successfully created"
|
|
38
|
+
update: "%{resource} was successfully updated"
|
|
39
|
+
destroy: "%{resource} was successfully destroyed"
|
|
40
|
+
batch_action: "%{number_of_records} %{resource} were affected"
|
|
41
|
+
pagination:
|
|
42
|
+
first: "First"
|
|
43
|
+
last: "Last"
|
|
44
|
+
entries:
|
|
45
|
+
zero: "No %{resource} found"
|
|
46
|
+
other: "Showing %{count} out of %{total} %{resource}"
|
|
47
|
+
datetimepickers:
|
|
48
|
+
datepicker: ! "%d/%m/%Y"
|
|
49
|
+
datetimepicker: ! "%d/%m/%Y %H:%M"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
pt-BR:
|
|
2
|
+
goodmin:
|
|
3
|
+
title: Goodmin
|
|
4
|
+
batch_actions:
|
|
5
|
+
buttons:
|
|
6
|
+
select_all: Selecionar todos
|
|
7
|
+
deselect_all: Remover seleção
|
|
8
|
+
confirm_message: Você tem certeza?
|
|
9
|
+
filters:
|
|
10
|
+
select:
|
|
11
|
+
placeholder:
|
|
12
|
+
one: Selecionar um
|
|
13
|
+
many: Selecionar vários
|
|
14
|
+
buttons:
|
|
15
|
+
apply: Filtrar
|
|
16
|
+
clear: Limpar filtro
|
|
17
|
+
actions:
|
|
18
|
+
label: Ações
|
|
19
|
+
show: Exibir
|
|
20
|
+
show_ttitle: Exibir %{resource}
|
|
21
|
+
edit: Editar
|
|
22
|
+
edit_title: Editar %{resource}
|
|
23
|
+
destroy: Remover
|
|
24
|
+
destroy_title: Remover %{resource}
|
|
25
|
+
confirm_message: Você tem certeza?
|
|
26
|
+
export: Exportar
|
|
27
|
+
export_as: Como
|
|
28
|
+
associations:
|
|
29
|
+
label: Nested resources
|
|
30
|
+
sessions:
|
|
31
|
+
sign_in: Entrar
|
|
32
|
+
sign_out: Sair
|
|
33
|
+
signed_in: Conectado
|
|
34
|
+
signed_out: Desconectado
|
|
35
|
+
failed_sign_in: Credenciais inválidas
|
|
36
|
+
flash:
|
|
37
|
+
create: "%{resource} foi criado com sucesso"
|
|
38
|
+
update: "%{resource} foi atualizado com sucesso"
|
|
39
|
+
destroy: "%{resource} foi removido com sucesso"
|
|
40
|
+
batch_action: "%{number_of_records} %{resource} foram modificados"
|
|
41
|
+
pagination:
|
|
42
|
+
first: "Primeiro"
|
|
43
|
+
last: "Último"
|
|
44
|
+
entries:
|
|
45
|
+
zero: "Nenhum %{resource} encontrado"
|
|
46
|
+
other: "Exibindo %{count} de %{total} %{resource}"
|
|
47
|
+
datetimepickers:
|
|
48
|
+
datepicker: ! "%d/%m/%Y"
|
|
49
|
+
datetimepicker: ! "%d/%m/%Y %H:%M"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
pt-BR:
|
|
2
|
+
goodmin:
|
|
3
|
+
title: Goodmin
|
|
4
|
+
batch_actions:
|
|
5
|
+
buttons:
|
|
6
|
+
select_all: Selecionar todos
|
|
7
|
+
deselect_all: Remover seleção
|
|
8
|
+
confirm_message: Você tem certeza?
|
|
9
|
+
filters:
|
|
10
|
+
select:
|
|
11
|
+
placeholder:
|
|
12
|
+
one: Selecionar um
|
|
13
|
+
many: Selecionar vários
|
|
14
|
+
buttons:
|
|
15
|
+
apply: Filtrar
|
|
16
|
+
clear: Limpar filtro
|
|
17
|
+
actions:
|
|
18
|
+
label: Ações
|
|
19
|
+
show: Exibir
|
|
20
|
+
show_ttitle: Exibir %{resource}
|
|
21
|
+
edit: Editar
|
|
22
|
+
edit_title: Editar %{resource}
|
|
23
|
+
destroy: Remover
|
|
24
|
+
destroy_title: Remover %{resource}
|
|
25
|
+
confirm_message: Você tem certeza?
|
|
26
|
+
export: Exportar
|
|
27
|
+
export_as: Como
|
|
28
|
+
associations:
|
|
29
|
+
label: Nested resources
|
|
30
|
+
sessions:
|
|
31
|
+
sign_in: Entrar
|
|
32
|
+
sign_out: Sair
|
|
33
|
+
signed_in: Conectado
|
|
34
|
+
signed_out: Desconectado
|
|
35
|
+
failed_sign_in: Credenciais inválidas
|
|
36
|
+
flash:
|
|
37
|
+
create: "%{resource} foi criado com sucesso"
|
|
38
|
+
update: "%{resource} foi atualizado com sucesso"
|
|
39
|
+
destroy: "%{resource} foi removido com sucesso"
|
|
40
|
+
batch_action: "%{number_of_records} %{resource} foram modificados"
|
|
41
|
+
pagination:
|
|
42
|
+
first: "Primeiro"
|
|
43
|
+
last: "Último"
|
|
44
|
+
entries:
|
|
45
|
+
zero: "Nenhum %{resource} encontrado"
|
|
46
|
+
other: "Exibindo %{count} de %{total} %{resource}"
|
|
47
|
+
datetimepickers:
|
|
48
|
+
datepicker: ! "%d/%m/%Y"
|
|
49
|
+
datetimepicker: ! "%d/%m/%Y %H:%M"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
sv:
|
|
2
|
+
goodmin:
|
|
3
|
+
title: Goodmin
|
|
4
|
+
batch_actions:
|
|
5
|
+
buttons:
|
|
6
|
+
select_all: Markera alla
|
|
7
|
+
deselect_all: Avmarkera alla
|
|
8
|
+
confirm_message: Är du säker?
|
|
9
|
+
filters:
|
|
10
|
+
select:
|
|
11
|
+
placeholder:
|
|
12
|
+
one: Välj någonting
|
|
13
|
+
many: Välj någonting
|
|
14
|
+
buttons:
|
|
15
|
+
apply: Filtrera
|
|
16
|
+
clear: Rensa filter
|
|
17
|
+
actions:
|
|
18
|
+
label: Alternativ
|
|
19
|
+
show: Visa
|
|
20
|
+
show_title: Visa %{resource}
|
|
21
|
+
edit: Ändra
|
|
22
|
+
edit_title: Ändra %{resource}
|
|
23
|
+
destroy: Ta bort
|
|
24
|
+
destroy_title: Ta bort %{resource}
|
|
25
|
+
confirm_message: Är du säker?
|
|
26
|
+
export: Exportera
|
|
27
|
+
export_as: Som
|
|
28
|
+
associations:
|
|
29
|
+
label: Nästlade resurser
|
|
30
|
+
sessions:
|
|
31
|
+
sign_in: Logga in
|
|
32
|
+
sign_out: Logga ut
|
|
33
|
+
signed_in: Loggade in
|
|
34
|
+
signed_out: Loggade ut
|
|
35
|
+
failed_sign_in: Fel inloggningsuppgifter
|
|
36
|
+
flash:
|
|
37
|
+
create: "%{resource} skapades"
|
|
38
|
+
update: "%{resource} uppdaterades"
|
|
39
|
+
destroy: "%{resource} togs bort"
|
|
40
|
+
batch_action: "%{number_of_records} %{resource} påverkades"
|
|
41
|
+
pagination:
|
|
42
|
+
first: "Första"
|
|
43
|
+
last: "Sista"
|
|
44
|
+
entries:
|
|
45
|
+
zero: "Inga %{resource} funna"
|
|
46
|
+
other: "Visar %{count} av %{total} %{resource}"
|
|
47
|
+
datetimepickers:
|
|
48
|
+
datepicker: ! "%Y-%m-%d"
|
|
49
|
+
datetimepicker: ! "%Y-%m-%d %H:%M"
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "goodmin/generators/named_base"
|
|
2
|
+
|
|
3
|
+
class Goodmin::AuthenticationGenerator < Goodmin::Generators::NamedBase
|
|
4
|
+
argument :name, type: :string, default: "admin_user"
|
|
5
|
+
|
|
6
|
+
def create_model
|
|
7
|
+
generate "model", "#{name} email:string password_digest:text --no-test-framework"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def modify_model
|
|
11
|
+
inject_into_file File.join("app/models", class_path, "#{file_name}.rb"), after: "ActiveRecord::Base\n" do
|
|
12
|
+
<<-END.strip_heredoc.indent(namespace ? 4 : 2)
|
|
13
|
+
include Goodmin::Authentication::User
|
|
14
|
+
|
|
15
|
+
def self.login_column
|
|
16
|
+
:email
|
|
17
|
+
end
|
|
18
|
+
END
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_route
|
|
23
|
+
route "resource :session, only: [:new, :create, :destroy]"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_sessions_controller
|
|
27
|
+
template "sessions_controller.rb", File.join("app/controllers", namespaced_path, "sessions_controller.rb")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def modify_application_controller
|
|
31
|
+
inject_into_file File.join("app/controllers", namespaced_path, "application_controller.rb"), after: "Goodmin::ApplicationController\n" do
|
|
32
|
+
<<-END.strip_heredoc.indent(namespace ? 4 : 2)
|
|
33
|
+
include Goodmin::Authentication
|
|
34
|
+
|
|
35
|
+
def admin_user_class
|
|
36
|
+
#{full_class_name}
|
|
37
|
+
end
|
|
38
|
+
END
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% if namespaced? -%>
|
|
2
|
+
require_dependency "<%= File.join(namespaced_path, "application_controller") %>"
|
|
3
|
+
|
|
4
|
+
<% end -%>
|
|
5
|
+
<% module_namespacing do -%>
|
|
6
|
+
class SessionsController < ApplicationController
|
|
7
|
+
include Goodmin::Authentication::SessionsController
|
|
8
|
+
end
|
|
9
|
+
<% end -%>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "goodmin/generators/base"
|
|
2
|
+
|
|
3
|
+
class Goodmin::InstallGenerator < Goodmin::Generators::Base
|
|
4
|
+
def create_routes
|
|
5
|
+
if namespaced?
|
|
6
|
+
inject_into_file "config/routes.rb", before: /^end/ do
|
|
7
|
+
<<-END.strip_heredoc.indent(2)
|
|
8
|
+
root to: "application#welcome"
|
|
9
|
+
END
|
|
10
|
+
end
|
|
11
|
+
else
|
|
12
|
+
inject_into_file "config/routes.rb", before: /^end/ do
|
|
13
|
+
<<-END.strip_heredoc.indent(2)
|
|
14
|
+
mount Goodmin::Engine, at: "/admin"
|
|
15
|
+
END
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_navigation
|
|
21
|
+
create_file "app/views/goodmin/shared/_navigation.html.erb"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def modify_application_controller
|
|
25
|
+
return if namespaced?
|
|
26
|
+
|
|
27
|
+
gsub_file "app/controllers/application_controller.rb",
|
|
28
|
+
/class ApplicationController < ActionController::Base/,
|
|
29
|
+
"class ApplicationController < Goodmin::ApplicationController"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def require_library_if_namespaced
|
|
33
|
+
return unless namespaced?
|
|
34
|
+
|
|
35
|
+
inject_into_file File.join("lib", namespaced_path) + ".rb", before: "require" do
|
|
36
|
+
<<-END.strip_heredoc
|
|
37
|
+
require "goodmin"
|
|
38
|
+
END
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
class <%= class_name %>Policy < Goodmin::Authorization::Policy
|
|
3
|
+
def index?
|
|
4
|
+
true
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def show?
|
|
8
|
+
true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create?
|
|
12
|
+
true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update?
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def destroy?
|
|
20
|
+
true
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
<% end -%>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "goodmin/generators/named_base"
|
|
2
|
+
|
|
3
|
+
class Goodmin::ResourceGenerator < Goodmin::Generators::NamedBase
|
|
4
|
+
argument :attributes, type: :array, default: [], banner: "attribute attribute"
|
|
5
|
+
|
|
6
|
+
def add_route
|
|
7
|
+
invoke "resource_route"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add_navigation
|
|
11
|
+
append_to_file "app/views/goodmin/shared/_navigation.html.erb" do
|
|
12
|
+
<<-END.strip_heredoc
|
|
13
|
+
<%= navbar_item #{class_name} %>
|
|
14
|
+
END
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_model
|
|
19
|
+
if namespaced?
|
|
20
|
+
template "resource_model.rb", File.join("app/models", class_path, "#{file_name}.rb")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_controller
|
|
25
|
+
template "resource_controller.rb", File.join("app/controllers", class_path, "#{file_name.pluralize}_controller.rb")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create_resource
|
|
29
|
+
template "resource.rb", File.join("app/goodmin/resources", "#{file_name}_resource.rb")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
class <%= class_name %>Resource
|
|
4
|
+
include Goodmin::Resources::Resource
|
|
5
|
+
|
|
6
|
+
index do
|
|
7
|
+
<% @attributes.each do |x| -%>
|
|
8
|
+
attribute :<%= x %>
|
|
9
|
+
<% end -%>
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
show do
|
|
13
|
+
<% @attributes.each do |x| -%>
|
|
14
|
+
attribute :<%= x %>
|
|
15
|
+
<% end -%>
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
form do
|
|
19
|
+
<% @attributes.each do |x| -%>
|
|
20
|
+
attribute :<%= x %>
|
|
21
|
+
<% end -%>
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% if namespaced? -%>
|
|
2
|
+
require_dependency "<%= File.join(namespaced_path, "application_controller") %>"
|
|
3
|
+
|
|
4
|
+
<% end -%>
|
|
5
|
+
<% module_namespacing do -%>
|
|
6
|
+
class <%= class_name.pluralize %>Controller < ApplicationController
|
|
7
|
+
include Goodmin::Resources::ResourceController
|
|
8
|
+
end
|
|
9
|
+
<% end -%>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
class <%= class_name %>Service
|
|
3
|
+
include Goodmin::Resources::ResourceService
|
|
4
|
+
|
|
5
|
+
index do
|
|
6
|
+
<% @attributes.each do |x| -%>
|
|
7
|
+
attribute :<%= x %>
|
|
8
|
+
<% end -%>
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
show do
|
|
12
|
+
<% @attributes.each do |x| -%>
|
|
13
|
+
attribute :<%= x %>
|
|
14
|
+
<% end -%>
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
form do
|
|
18
|
+
<% @attributes.each do |x| -%>
|
|
19
|
+
attribute :<%= x %>
|
|
20
|
+
<% end -%>
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
<% end -%>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Authentication
|
|
3
|
+
module SessionsController
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
layout "goodmin/login"
|
|
8
|
+
prepend_before_action :disable_authentication
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def new
|
|
12
|
+
@admin_user = admin_user_class.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create
|
|
16
|
+
@admin_user = admin_user_class.find_by_login(admin_user_login)
|
|
17
|
+
|
|
18
|
+
if @admin_user && @admin_user.authenticate(admin_user_params[:password])
|
|
19
|
+
session[:admin_user_id] = @admin_user.id
|
|
20
|
+
redirect_to root_path, notice: t("goodmin.sessions.signed_in")
|
|
21
|
+
else
|
|
22
|
+
redirect_to new_session_path, alert: t("goodmin.sessions.failed_sign_in")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def destroy
|
|
27
|
+
session[:admin_user_id] = nil
|
|
28
|
+
redirect_to new_session_path, notice: t("goodmin.sessions.signed_out")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def admin_user_login
|
|
34
|
+
admin_user_params[admin_user_class.login_column]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def admin_user_params
|
|
38
|
+
params.require(admin_user_class.model_name.param_key.to_sym).permit(
|
|
39
|
+
admin_user_class.login_column,
|
|
40
|
+
:password,
|
|
41
|
+
:password_confirm
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Authentication
|
|
3
|
+
module User
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
has_secure_password
|
|
8
|
+
|
|
9
|
+
validates :password, length: { minimum: 8 }, allow_nil: true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def login
|
|
13
|
+
send(self.class.login_column)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module ClassMethods
|
|
17
|
+
def find_by_login(login)
|
|
18
|
+
find_by(login_column => login)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def login_column
|
|
22
|
+
raise NotImplementedError, "Must define the admin user login column"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "goodmin/authentication/sessions_controller"
|
|
2
|
+
require "goodmin/authentication/user"
|
|
3
|
+
|
|
4
|
+
module Goodmin
|
|
5
|
+
module Authentication
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
before_action :authenticate
|
|
10
|
+
|
|
11
|
+
helper_method :admin_user
|
|
12
|
+
helper_method :admin_user_signed_in?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def authenticate
|
|
16
|
+
return unless authentication_enabled?
|
|
17
|
+
return if admin_user_signed_in?
|
|
18
|
+
|
|
19
|
+
redirect_to new_session_path
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def admin_user_class; end
|
|
23
|
+
|
|
24
|
+
def admin_user
|
|
25
|
+
return unless admin_user_class
|
|
26
|
+
return unless session[:admin_user_id]
|
|
27
|
+
|
|
28
|
+
@_admin_user ||= admin_user_class.find_by(id: session[:admin_user_id])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def admin_user_signed_in?
|
|
32
|
+
admin_user.present?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Authorization
|
|
3
|
+
class Policy
|
|
4
|
+
attr_reader :user, :record
|
|
5
|
+
|
|
6
|
+
def initialize(user, record, default: false)
|
|
7
|
+
@user = user
|
|
8
|
+
@record = record
|
|
9
|
+
@default = default
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def index?
|
|
13
|
+
@default
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def show?
|
|
17
|
+
@default
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def new?
|
|
21
|
+
create?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def edit?
|
|
25
|
+
update?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def create?
|
|
29
|
+
@default
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update?
|
|
33
|
+
@default
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy?
|
|
37
|
+
@default
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require "pundit"
|
|
2
|
+
require "goodmin/authorization/policy"
|
|
3
|
+
|
|
4
|
+
module Goodmin
|
|
5
|
+
module Authorization
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
include Pundit::Authorization
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
rescue_from Pundit::NotAuthorizedError do
|
|
12
|
+
render plain: "You are not authorized to do this", status: 403, layout: "goodmin/login"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def policy(record)
|
|
17
|
+
policies[record] ||= Pundit.policy!(pundit_user, namespaced_record(record))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def pundit_user
|
|
21
|
+
admin_user
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def namespaced_record(record)
|
|
25
|
+
return record if controller_namespace_path.empty?
|
|
26
|
+
|
|
27
|
+
class_name = find_class_name(record)
|
|
28
|
+
if already_namespaced?(class_name)
|
|
29
|
+
record
|
|
30
|
+
else
|
|
31
|
+
controller_namespace_path.map(&:to_sym) << record
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# Borrowed from Pundit::PolicyFinder
|
|
38
|
+
def find_class_name(subject)
|
|
39
|
+
if subject.respond_to?(:model_name)
|
|
40
|
+
subject.model_name
|
|
41
|
+
elsif subject.class.respond_to?(:model_name)
|
|
42
|
+
subject.class.model_name
|
|
43
|
+
elsif subject.is_a?(Class)
|
|
44
|
+
subject
|
|
45
|
+
elsif subject.is_a?(Symbol)
|
|
46
|
+
subject.to_s.camelize
|
|
47
|
+
else
|
|
48
|
+
subject.class
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def already_namespaced?(subject)
|
|
53
|
+
return false if controller_namespace_name.blank?
|
|
54
|
+
|
|
55
|
+
subject.to_s.start_with?("#{controller_namespace_name}::")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def controller_namespace_path
|
|
59
|
+
@_controller_namespace_path ||= begin
|
|
60
|
+
parts = controller_path.split("/")
|
|
61
|
+
parts.length > 1 ? parts.first(parts.length - 1) : []
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def controller_namespace_name
|
|
66
|
+
@_controller_namespace_name ||= controller_namespace_path.map(&:camelize).join("::")
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace Goodmin
|
|
4
|
+
|
|
5
|
+
initializer "goodmin.autoload_paths", before: :set_autoload_paths do |app|
|
|
6
|
+
goodmin_app_dir = app.root.join("app/goodmin")
|
|
7
|
+
if goodmin_app_dir.exist?
|
|
8
|
+
Rails.autoloaders.main.push_dir(goodmin_app_dir, namespace: Goodmin)
|
|
9
|
+
app.config.eager_load_paths << goodmin_app_dir.to_s
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
initializer "goodmin.assets" do |app|
|
|
14
|
+
if app.config.respond_to?(:assets)
|
|
15
|
+
app.config.assets.paths << root.join("app/assets/stylesheets")
|
|
16
|
+
app.config.assets.paths << root.join("app/javascript")
|
|
17
|
+
app.config.assets.paths << root.join("vendor/assets/javascripts")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
initializer "goodmin.importmap", before: "importmap" do |app|
|
|
22
|
+
Goodmin.importmap.draw root.join("config/importmap.rb")
|
|
23
|
+
Goodmin.importmap.cache_sweeper watches: root.join("app/javascript")
|
|
24
|
+
|
|
25
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
26
|
+
before_action { Goodmin.importmap.cache_sweeper.execute_if_updated }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|