cafe_car 0.1.0 → 0.1.2
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/README.md +682 -8
- data/Rakefile +21 -0
- data/app/assets/fonts/Lexend.css +7 -0
- data/app/assets/fonts/Lexend.ttf +0 -0
- data/app/assets/images/noise.svg +16 -0
- data/app/assets/stylesheets/actiontext.css +31 -0
- data/app/assets/stylesheets/application.css +1 -0
- data/app/assets/stylesheets/cafe_car/code/base16-dark.css +89 -0
- data/app/assets/stylesheets/cafe_car/code/base16-light.css +90 -0
- data/app/assets/stylesheets/cafe_car/pagination.css +5 -0
- data/app/assets/stylesheets/cafe_car/themes/cool.css +32 -0
- data/app/assets/stylesheets/cafe_car/themes/cool2.css +31 -0
- data/app/assets/stylesheets/cafe_car/themes/defaults.css +60 -0
- data/app/assets/stylesheets/cafe_car/themes/warm-dark.css +29 -0
- data/app/assets/stylesheets/cafe_car/themes/warm.css +24 -0
- data/app/assets/stylesheets/cafe_car/tooltips.css +20 -0
- data/app/assets/stylesheets/cafe_car/trix.css +56 -0
- data/app/assets/stylesheets/cafe_car/utility.css +63 -0
- data/app/assets/stylesheets/cafe_car.css +96 -0
- data/app/assets/stylesheets/iconoir.css +22 -0
- data/app/assets/stylesheets/ui/Alert.css +25 -0
- data/app/assets/stylesheets/ui/Article.css +11 -0
- data/app/assets/stylesheets/ui/Button.css +42 -0
- data/app/assets/stylesheets/ui/Card.css +74 -0
- data/app/assets/stylesheets/ui/Chat.css +33 -0
- data/app/assets/stylesheets/ui/Close.css +11 -0
- data/app/assets/stylesheets/ui/Code.css +4 -0
- data/app/assets/stylesheets/ui/Controls.css +16 -0
- data/app/assets/stylesheets/ui/Error.css +3 -0
- data/app/assets/stylesheets/ui/Example.css +45 -0
- data/app/assets/stylesheets/ui/Field.css +31 -0
- data/app/assets/stylesheets/ui/Grid.css +6 -0
- data/app/assets/stylesheets/ui/Group.css +16 -0
- data/app/assets/stylesheets/ui/Icon.css +27 -0
- data/app/assets/stylesheets/ui/Image.css +14 -0
- data/app/assets/stylesheets/ui/InfoCircle.css +11 -0
- data/app/assets/stylesheets/ui/Input.css +36 -0
- data/app/assets/stylesheets/ui/Layout.css +100 -0
- data/app/assets/stylesheets/ui/Menu.css +38 -0
- data/app/assets/stylesheets/ui/Modal.css +26 -0
- data/app/assets/stylesheets/ui/Navigation.css +37 -0
- data/app/assets/stylesheets/ui/Page.css +105 -0
- data/app/assets/stylesheets/ui/Row.css +9 -0
- data/app/assets/stylesheets/ui/Table.css +101 -0
- data/app/assets/stylesheets/ui/components.css +24 -0
- data/app/controllers/cafe_car/application_controller.rb +9 -0
- data/app/controllers/cafe_car/examples_controller.rb +22 -0
- data/app/controllers/cafe_car/sessions_controller.rb +30 -0
- data/app/controllers/concerns/cafe_car/authentication.rb +61 -0
- data/app/javascript/application.js +5 -0
- data/app/javascript/cafe_car.js +174 -0
- data/app/models/cafe_car/session.rb +18 -0
- data/app/policies/cafe_car/application_policy.rb +42 -0
- data/app/policies/cafe_car/session_policy.rb +19 -0
- data/app/presenters/cafe_car/action_text/rich_text_presenter.rb +7 -0
- data/app/presenters/cafe_car/active_record/base_presenter.rb +6 -0
- data/app/presenters/cafe_car/active_record/relation_presenter.rb +17 -0
- data/app/presenters/cafe_car/active_storage/attached/one_presenter.rb +9 -0
- data/app/presenters/cafe_car/active_storage/attachment_presenter.rb +18 -0
- data/app/presenters/cafe_car/basic_object_presenter.rb +5 -0
- data/app/presenters/cafe_car/code_presenter.rb +18 -0
- data/app/presenters/cafe_car/currency_presenter.rb +5 -0
- data/app/presenters/cafe_car/date_and_time/compatibility_presenter.rb +6 -0
- data/app/presenters/cafe_car/date_presenter.rb +5 -0
- data/app/presenters/cafe_car/date_time_presenter.rb +11 -0
- data/app/presenters/cafe_car/enumerable_presenter.rb +13 -0
- data/app/presenters/cafe_car/false_class_presenter.rb +5 -0
- data/app/presenters/cafe_car/hash_presenter.rb +6 -0
- data/app/presenters/cafe_car/nil_class_presenter.rb +13 -0
- data/app/presenters/cafe_car/presenter.rb +157 -0
- data/app/presenters/cafe_car/range_presenter.rb +16 -0
- data/app/presenters/cafe_car/record_presenter.rb +5 -0
- data/app/presenters/cafe_car/string_presenter.rb +20 -0
- data/app/presenters/cafe_car/symbol_presenter.rb +5 -0
- data/app/presenters/cafe_car/true_class_presenter.rb +5 -0
- data/app/ui/cafe_car/ui/button.rb +9 -0
- data/app/ui/cafe_car/ui/card.rb +18 -0
- data/app/ui/cafe_car/ui/field.rb +11 -0
- data/app/ui/cafe_car/ui/grid.rb +30 -0
- data/app/ui/cafe_car/ui/layout.rb +7 -0
- data/app/ui/cafe_car/ui/page.rb +14 -0
- data/app/views/application/_actions.html.haml +1 -0
- data/app/views/application/_alerts.html.haml +2 -0
- data/app/views/application/_body.html.haml +7 -0
- data/app/views/application/_controls.html.haml +12 -0
- data/app/views/application/_debug.html.haml +18 -0
- data/app/views/application/_empty.html.haml +1 -0
- data/app/views/application/_errors.html.haml +4 -0
- data/app/views/application/_field.html.haml +5 -0
- data/app/views/application/_fields.html.haml +1 -0
- data/app/views/application/_filters.html.haml +8 -0
- data/app/views/application/_form.html.haml +6 -0
- data/app/views/application/_grid.html.haml +3 -0
- data/app/views/application/_grid_item.html.haml +1 -0
- data/app/views/application/_head.html.haml +17 -0
- data/app/views/application/_index.html.haml +8 -0
- data/app/views/application/_index_actions.html.haml +7 -0
- data/app/views/application/_navigation.html.haml +9 -0
- data/app/views/application/_navigation_links.html.haml +5 -0
- data/app/views/application/_notes.html.haml +10 -0
- data/app/views/application/_popup.html.haml +7 -0
- data/app/views/application/_show.html.haml +9 -0
- data/app/views/application/_submit.html.haml +1 -0
- data/app/views/application/_table.html.haml +6 -0
- data/app/views/cafe_car/application/create.turbo_stream.haml +2 -0
- data/app/views/cafe_car/application/destroy.turbo_stream.haml +1 -0
- data/app/views/cafe_car/application/edit.html.haml +18 -0
- data/app/views/cafe_car/application/edit.turbo_stream.haml +7 -0
- data/app/views/cafe_car/application/index.html.haml +15 -0
- data/app/views/cafe_car/application/new.html.haml +8 -0
- data/app/views/cafe_car/application/new.turbo_stream.haml +8 -0
- data/app/views/cafe_car/application/show.html.haml +36 -0
- data/app/views/cafe_car/application/update.turbo_stream.haml +2 -0
- data/app/views/cafe_car/examples/_example.html.haml +12 -0
- data/app/views/cafe_car/examples/_index.html.haml +16 -0
- data/app/views/cafe_car/examples/_navigation_links.html.haml +2 -0
- data/app/views/cafe_car/examples/ui/_alert.html.haml +4 -0
- data/app/views/cafe_car/examples/ui/_button.html.haml +3 -0
- data/app/views/cafe_car/examples/ui/_card.html.haml +6 -0
- data/app/views/cafe_car/examples/ui/_chat.html.haml +3 -0
- data/app/views/cafe_car/examples/ui/_controls.html.haml +3 -0
- data/app/views/cafe_car/examples/ui/_error.html.haml +1 -0
- data/app/views/cafe_car/examples/ui/_field.html.haml +9 -0
- data/app/views/cafe_car/examples/ui/_grid.html.haml +11 -0
- data/app/views/cafe_car/examples/ui/_group.html.haml +21 -0
- data/app/views/cafe_car/examples/ui/_info_circle.html.haml +1 -0
- data/app/views/cafe_car/examples/ui/_menu.html.haml +5 -0
- data/app/views/cafe_car/examples/ui/_modal.html.haml +4 -0
- data/app/views/cafe_car/examples/ui/_navigation.html.haml +4 -0
- data/app/views/cafe_car/examples/ui/_page.html.haml +4 -0
- data/app/views/cafe_car/examples/ui/_table.html.haml +13 -0
- data/app/views/cafe_car/layouts/mailer.html.haml +8 -0
- data/app/views/cafe_car/layouts/mailer.text.erb +1 -0
- data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
- data/app/views/layouts/application.html.haml +4 -0
- data/app/views/layouts/mailer.html.erb +13 -0
- data/app/views/layouts/mailer.text.erb +1 -0
- data/app/views/notes/_fields.html.haml +1 -0
- data/app/views/passwords_mailer/reset.html.haml +5 -0
- data/app/views/passwords_mailer/reset.text.erb +4 -0
- data/app/views/ui/_card.html.haml +8 -0
- data/app/views/ui/_field.html.haml +1 -0
- data/app/views/ui/_modal_close.html.haml +1 -0
- data/app/views/ui/_page.html.haml +7 -0
- data/config/brakeman.ignore +77 -0
- data/config/importmap.rb +12 -0
- data/config/locales/en.yml +63 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20251005220017_create_slugs.rb +13 -0
- data/lib/cafe_car/active_record.rb +21 -0
- data/lib/cafe_car/application_responder.rb +17 -0
- data/lib/cafe_car/attributes.rb +23 -0
- data/lib/cafe_car/auto_resolver.rb +49 -0
- data/lib/cafe_car/caching.rb +20 -0
- data/lib/cafe_car/component.rb +155 -0
- data/lib/cafe_car/context.rb +17 -0
- data/lib/cafe_car/controller/filtering.rb +30 -0
- data/lib/cafe_car/controller.rb +218 -0
- data/lib/cafe_car/core_ext/array.rb +24 -0
- data/lib/cafe_car/core_ext/hash.rb +15 -0
- data/lib/cafe_car/core_ext/module.rb +15 -0
- data/lib/cafe_car/core_ext.rb +5 -0
- data/lib/cafe_car/current.rb +9 -0
- data/lib/cafe_car/engine.rb +107 -0
- data/lib/cafe_car/field_builder.rb +44 -0
- data/lib/cafe_car/field_info.rb +144 -0
- data/lib/cafe_car/fields.rb +21 -0
- data/lib/cafe_car/filter/field_builder.rb +4 -0
- data/lib/cafe_car/filter/field_info.rb +22 -0
- data/lib/cafe_car/filter/form_builder.rb +21 -0
- data/lib/cafe_car/filter.rb +5 -0
- data/lib/cafe_car/filter_builder.rb +20 -0
- data/lib/cafe_car/form_builder.rb +105 -0
- data/lib/cafe_car/generators.rb +30 -0
- data/lib/cafe_car/helpers.rb +178 -0
- data/lib/cafe_car/href_builder.rb +97 -0
- data/lib/cafe_car/informable.rb +9 -0
- data/lib/cafe_car/input_builder.rb +25 -0
- data/lib/cafe_car/inputs/association_builder.rb +6 -0
- data/lib/cafe_car/inputs/base_input.rb +19 -0
- data/lib/cafe_car/inputs/belongs_to_builder.rb +6 -0
- data/lib/cafe_car/inputs/password_input.rb +7 -0
- data/lib/cafe_car/inputs/string_input.rb +7 -0
- data/lib/cafe_car/link_builder.rb +65 -0
- data/lib/cafe_car/model.rb +23 -0
- data/lib/cafe_car/model_info.rb +24 -0
- data/lib/cafe_car/name_patch.rb +17 -0
- data/lib/cafe_car/navigation.rb +76 -0
- data/lib/cafe_car/option_helpers.rb +53 -0
- data/lib/cafe_car/param_parser.rb +45 -0
- data/lib/cafe_car/pluralization.rb +15 -0
- data/lib/cafe_car/policy.rb +77 -0
- data/lib/cafe_car/proc_helpers.rb +13 -0
- data/lib/cafe_car/query_builder.rb +186 -0
- data/lib/cafe_car/queryable.rb +29 -0
- data/lib/cafe_car/resolver.rb +27 -0
- data/lib/cafe_car/routing.rb +17 -0
- data/lib/cafe_car/table/body_builder.rb +12 -0
- data/lib/cafe_car/table/builder.rb +52 -0
- data/lib/cafe_car/table/foot_builder.rb +14 -0
- data/lib/cafe_car/table/head_builder.rb +26 -0
- data/lib/cafe_car/table/label_builder.rb +48 -0
- data/lib/cafe_car/table/objects_builder.rb +8 -0
- data/lib/cafe_car/table/row_builder.rb +39 -0
- data/lib/cafe_car/table_builder.rb +13 -0
- data/lib/cafe_car/turbo_tag_builder.rb +7 -0
- data/lib/cafe_car/ui.rb +11 -0
- data/lib/cafe_car/version.rb +1 -1
- data/lib/cafe_car/visitors.rb +21 -0
- data/lib/cafe_car.rb +25 -168
- data/lib/generators/cafe_car/controller/USAGE +11 -0
- data/lib/generators/cafe_car/controller/controller_generator.rb +26 -0
- data/lib/generators/cafe_car/controller/templates/controller.rb.tt +5 -0
- data/lib/generators/cafe_car/install/USAGE +8 -0
- data/lib/generators/cafe_car/install/install_generator.rb +46 -0
- data/lib/generators/cafe_car/install/templates/application_policy.rb.tt +7 -0
- data/lib/generators/cafe_car/notes/USAGE +12 -0
- data/lib/generators/cafe_car/notes/notes_generator.rb +13 -0
- data/lib/generators/cafe_car/notes/templates/create_notes.rb.tt +12 -0
- data/lib/generators/cafe_car/notes/templates/notable.rb.tt +7 -0
- data/lib/generators/cafe_car/notes/templates/note.rb.tt +6 -0
- data/lib/generators/cafe_car/policy/USAGE +8 -0
- data/lib/generators/cafe_car/policy/policy_generator.rb +39 -0
- data/lib/generators/cafe_car/policy/templates/policy.rb.tt +20 -0
- data/lib/generators/cafe_car/resource/USAGE +13 -0
- data/lib/generators/cafe_car/resource/resource_generator.rb +32 -0
- data/lib/generators/cafe_car/sessions/USAGE +17 -0
- data/lib/generators/cafe_car/sessions/sessions_generator.rb +29 -0
- data/lib/generators/cafe_car/sessions/templates/create_sessions.rb.tt +12 -0
- data/lib/tasks/holdco_tasks.rake +532 -0
- data/lib/tasks/templates/tasks_header.md +37 -0
- metadata +444 -21
- data/app/views/cafe_car/application/_fields.html.erb +0 -7
- data/app/views/cafe_car/application/_filters.html.erb +0 -0
- data/app/views/cafe_car/application/_form.html.erb +0 -22
- data/lib/cafe_car/railtie.rb +0 -4
- /data/app/views/{cafe_car/application/_actions.html.erb → application/_aside.html.haml} +0 -0
- /data/app/views/{cafe_car/application/_aside.html.erb → application/_footer.html.haml} +0 -0
- /data/app/views/cafe_car/{application/_extra_fields.html.erb → examples/_index_actions.html.haml} +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
- if action.new?
|
|
2
|
+
= render "popup" do
|
|
3
|
+
= Card title: "New #{model_name.human}", actions: Close { icon(:xmark_circle_solid) } do |card|
|
|
4
|
+
= render "form", card:
|
|
5
|
+
|
|
6
|
+
- else # error during :create action
|
|
7
|
+
= turbo_stream.replace(dom_id(object, :new)) do
|
|
8
|
+
= render "form", card: ui.Card
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
- title = breadcrumbs(link(object).index, title(object))
|
|
2
|
+
- summary = ui(object).timestamps try: true
|
|
3
|
+
- body = render("show")
|
|
4
|
+
|
|
5
|
+
= turbo_stream_from(object) if object.persisted?
|
|
6
|
+
= Page :full, title: do |page|
|
|
7
|
+
= page.Aside do
|
|
8
|
+
= yield :left
|
|
9
|
+
|
|
10
|
+
= page.Body do
|
|
11
|
+
= render "alerts"
|
|
12
|
+
|
|
13
|
+
- if tab = params[:tab]
|
|
14
|
+
-# - title tab.humanize
|
|
15
|
+
-# = row bottom: true do
|
|
16
|
+
-# = page.head
|
|
17
|
+
-# %h1 object.try(:name).fmap {|name| "#{name}'s #{tab.humanize(capitalize: false)}" }.felse { tab.humanize }
|
|
18
|
+
-# = link "← Back to #{model_name.human}", link: path_super(object)
|
|
19
|
+
-#
|
|
20
|
+
-# = render "tab_#{tab}"
|
|
21
|
+
- else
|
|
22
|
+
= body
|
|
23
|
+
= render "debug" if debug?
|
|
24
|
+
|
|
25
|
+
= page.Aside do
|
|
26
|
+
= Card :sticky do |card|
|
|
27
|
+
= card.Section ui(object).controls
|
|
28
|
+
= card.Section summary
|
|
29
|
+
|
|
30
|
+
= Card title: "Actions" do |card|
|
|
31
|
+
= render("actions", card:)
|
|
32
|
+
|
|
33
|
+
= Card title: "Notes" do |card|
|
|
34
|
+
= render("notes", card:)
|
|
35
|
+
|
|
36
|
+
= yield :right
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
= Example id: name do |ex|
|
|
2
|
+
= ex.Head do
|
|
3
|
+
= ex.Title ui.class(name), tag: :h2, href: "##{name}"
|
|
4
|
+
|
|
5
|
+
= ex.Body do
|
|
6
|
+
= yield
|
|
7
|
+
|
|
8
|
+
= ex.Source tag: :pre, class: "highlight" do
|
|
9
|
+
- formatter = Rouge::Formatters::HTML.new
|
|
10
|
+
- lexer = Rouge::Lexers::Haml.new
|
|
11
|
+
- source = get_partial(partial).encode!
|
|
12
|
+
= raw formatter.format(lexer.lex(source))
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
= stylesheet_link_tag 'ui/Example'
|
|
2
|
+
|
|
3
|
+
-# :javascript
|
|
4
|
+
-# window.onhashchange = () => {
|
|
5
|
+
-# $("[href]").remove(".current")
|
|
6
|
+
-# $("[href='" + location.hash + "']").add(".current")
|
|
7
|
+
-# }
|
|
8
|
+
|
|
9
|
+
:javascript
|
|
10
|
+
window.addEventListener('load', () => {
|
|
11
|
+
$
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
- @examples.each do |name, partial|
|
|
15
|
+
= render "cafe_car/examples/example", name:, partial: do
|
|
16
|
+
= render partial, href: "##{name}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= Error "Error"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
= Group do
|
|
2
|
+
= Button(href:) { "First" }
|
|
3
|
+
= Button(href:) { "Second" }
|
|
4
|
+
= Button(href:) { "Third" }
|
|
5
|
+
|
|
6
|
+
= Group do
|
|
7
|
+
= Card { "First Card" }
|
|
8
|
+
= Card { "Second Card" }
|
|
9
|
+
= Card { "Third Card" }
|
|
10
|
+
|
|
11
|
+
= Field label: "Inputs" do |f|
|
|
12
|
+
= Group do
|
|
13
|
+
= f.Input tag: :input, value: "first", class: "auto"
|
|
14
|
+
= f.Input tag: :input, value: "second", class: "auto"
|
|
15
|
+
= f.Input tag: :input, value: "third", class: "auto"
|
|
16
|
+
|
|
17
|
+
= Field label: "Input" do |f|
|
|
18
|
+
= f.Error "ERROR"
|
|
19
|
+
= Group do
|
|
20
|
+
= Input "$", tag: :b
|
|
21
|
+
= Input tag: :input, value: "value", class: "auto"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= InfoCircle "Hi", tip: "Hello"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= yield %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= yield %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= f.input :body
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= yield
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= yield || "✕"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ignored_warnings": [
|
|
3
|
+
{
|
|
4
|
+
"warning_type": "Dangerous Eval",
|
|
5
|
+
"warning_code": 13,
|
|
6
|
+
"fingerprint": "9f7c27406a84219ad1d93b07b8c1acd435ad75921861a85a647e32f3d07d1289",
|
|
7
|
+
"check_name": "Evaluation",
|
|
8
|
+
"message": "Dynamic string evaluated as code",
|
|
9
|
+
"file": "lib/cafe_car/auto_resolver.rb",
|
|
10
|
+
"line": 16,
|
|
11
|
+
"link": "https://brakemanscanner.org/docs/warning_types/dangerous_eval/",
|
|
12
|
+
"code": "TOPLEVEL_BINDING.eval(\"class #{mod.name}::#{name} < CafeCar[:ApplicationController]\\n include CafeCar::Controller\\n cafe_car\\n self\\nend\\n\", \"lib/cafe_car/auto_resolver.rb\", 16)",
|
|
13
|
+
"render_path": null,
|
|
14
|
+
"location": {
|
|
15
|
+
"type": "method",
|
|
16
|
+
"class": "CafeCar::AutoResolver",
|
|
17
|
+
"method": "define"
|
|
18
|
+
},
|
|
19
|
+
"user_input": null,
|
|
20
|
+
"confidence": "Weak",
|
|
21
|
+
"cwe_id": [
|
|
22
|
+
913,
|
|
23
|
+
95
|
|
24
|
+
],
|
|
25
|
+
"note": ""
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"warning_type": "Dangerous Eval",
|
|
29
|
+
"warning_code": 13,
|
|
30
|
+
"fingerprint": "48dbe3b4398088c5313b96ac86384413140275ce8852e516f8f3638b4ffdf999",
|
|
31
|
+
"check_name": "Evaluation",
|
|
32
|
+
"message": "Dynamic string evaluated as code",
|
|
33
|
+
"file": "lib/cafe_car/caching.rb",
|
|
34
|
+
"line": 15,
|
|
35
|
+
"link": "https://brakemanscanner.org/docs/warning_types/dangerous_eval/",
|
|
36
|
+
"code": "_1.module_eval(\"def #{name} = cache(:#{name}) { super }\\n\")",
|
|
37
|
+
"render_path": null,
|
|
38
|
+
"location": {
|
|
39
|
+
"type": "method",
|
|
40
|
+
"class": "CafeCar::Caching",
|
|
41
|
+
"method": "cache!"
|
|
42
|
+
},
|
|
43
|
+
"user_input": null,
|
|
44
|
+
"confidence": "Weak",
|
|
45
|
+
"cwe_id": [
|
|
46
|
+
913,
|
|
47
|
+
95
|
|
48
|
+
],
|
|
49
|
+
"note": ""
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"warning_type": "Dangerous Eval",
|
|
53
|
+
"warning_code": 13,
|
|
54
|
+
"fingerprint": "f14f192898bdd59525b84317d91ecbbdc952f71e28dbeca457caf4c11bee0bc7",
|
|
55
|
+
"check_name": "Evaluation",
|
|
56
|
+
"message": "Dynamic string evaluated as code",
|
|
57
|
+
"file": "lib/cafe_car/auto_resolver.rb",
|
|
58
|
+
"line": 24,
|
|
59
|
+
"link": "https://brakemanscanner.org/docs/warning_types/dangerous_eval/",
|
|
60
|
+
"code": "TOPLEVEL_BINDING.eval(\"class #{mod.name}::#{name} < CafeCar[:ApplicationPolicy]\\n def admin? = Rails.env.development?\\n\\n def index? = admin?\\n def show? = admin?\\n def create? = admin?\\n def update? = admin?\\n def destroy? = admin?\\n\\n def permitted_attributes\\n model.info.fields.names.then do |names|\\n [*model.primary_key].reverse.map(&:to_sym) & names | names\\n end\\n end\\n\\n class Scope < Scope\\n def resolve = scope.all\\n end\\n self\\nend\\n\", \"lib/cafe_car/auto_resolver.rb\", 24)",
|
|
61
|
+
"render_path": null,
|
|
62
|
+
"location": {
|
|
63
|
+
"type": "method",
|
|
64
|
+
"class": "CafeCar::AutoResolver",
|
|
65
|
+
"method": "define"
|
|
66
|
+
},
|
|
67
|
+
"user_input": null,
|
|
68
|
+
"confidence": "Weak",
|
|
69
|
+
"cwe_id": [
|
|
70
|
+
913,
|
|
71
|
+
95
|
|
72
|
+
],
|
|
73
|
+
"note": ""
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"brakeman_version": "8.0.4"
|
|
77
|
+
}
|
data/config/importmap.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
pin "application"
|
|
2
|
+
pin "cafe_car"
|
|
3
|
+
|
|
4
|
+
pin "@hotwired/turbo-rails", to: "turbo.min.js"
|
|
5
|
+
pin "@rails/actiontext", to: "actiontext.esm.js"
|
|
6
|
+
pin "trix"
|
|
7
|
+
|
|
8
|
+
# pin "@hotwired/stimulus", to: "stimulus.min.js"
|
|
9
|
+
# pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
|
10
|
+
# pin_all_from "app/javascript/controllers", under: "controllers"
|
|
11
|
+
pin "trix"
|
|
12
|
+
pin "@rails/actiontext", to: "actiontext.esm.js"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
en:
|
|
2
|
+
"true": "Yes"
|
|
3
|
+
"false": "No"
|
|
4
|
+
index: List
|
|
5
|
+
show: View
|
|
6
|
+
destroy: Delete
|
|
7
|
+
new_session: Log In
|
|
8
|
+
auth_required: Please %{new_session} first.
|
|
9
|
+
|
|
10
|
+
navigation:
|
|
11
|
+
icon:
|
|
12
|
+
new_session: log-in
|
|
13
|
+
sessions: log-in
|
|
14
|
+
attachments: media-image-list
|
|
15
|
+
blobs: media-image-folder
|
|
16
|
+
passwords: key
|
|
17
|
+
versions: multiple-pages
|
|
18
|
+
|
|
19
|
+
list_html:
|
|
20
|
+
zero: "(none)"
|
|
21
|
+
one: "%{list}"
|
|
22
|
+
other: "%{count} total: %{list}"
|
|
23
|
+
|
|
24
|
+
controls:
|
|
25
|
+
default: "%{Action}"
|
|
26
|
+
new: "%{Action} %{Model}"
|
|
27
|
+
index: "%{Models}"
|
|
28
|
+
confirm:
|
|
29
|
+
destroy: This %{Model} will be PERMANENTLY deleted. Are you sure?
|
|
30
|
+
disabled:
|
|
31
|
+
policy:
|
|
32
|
+
default: You don't have permission to %{action} this %{model}.
|
|
33
|
+
index: You don't have permission to %{action} %{models}.
|
|
34
|
+
|
|
35
|
+
time:
|
|
36
|
+
formats:
|
|
37
|
+
default: "%b %{ordinal}, %Y at %-l:%M%p"
|
|
38
|
+
long: "%A, %B %{ordinal}, %Y at %-l:%M:%S%p %Z"
|
|
39
|
+
|
|
40
|
+
attributes:
|
|
41
|
+
to_s: Item
|
|
42
|
+
id: ID
|
|
43
|
+
ip: IP
|
|
44
|
+
ip_address: IP address
|
|
45
|
+
created_at: Created
|
|
46
|
+
updated_at: Updated
|
|
47
|
+
deleted_at: Deleted
|
|
48
|
+
published_at: Published
|
|
49
|
+
|
|
50
|
+
flashes:
|
|
51
|
+
create_html: "%{Model} created!"
|
|
52
|
+
update_html: "%{Model} updated!"
|
|
53
|
+
destroy_html: "%{Model} deleted!"
|
|
54
|
+
|
|
55
|
+
activerecord:
|
|
56
|
+
models:
|
|
57
|
+
application_record: Record # .model_name.human
|
|
58
|
+
person:
|
|
59
|
+
one: Person
|
|
60
|
+
other: People
|
|
61
|
+
attributes:
|
|
62
|
+
article:
|
|
63
|
+
title: Title # .human_attribute_name("title")
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
CafeCar::Engine.routes.draw do
|
|
2
|
+
scope module: :cafe_car, as: :cafe_car do
|
|
3
|
+
get "components", to: "examples#index"
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
# Opt-in login/logout. Singular resource so the form posts to /session and
|
|
7
|
+
# request_authentication can redirect to new_session_path.
|
|
8
|
+
resource :session, only: %i[new create destroy], controller: "cafe_car/sessions"
|
|
9
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class CreateSlugs < ActiveRecord::Migration[8.0]
|
|
2
|
+
def change
|
|
3
|
+
create_table :slugs do |t|
|
|
4
|
+
t.string :slug, null: false
|
|
5
|
+
t.references :sluggable, polymorphic: true
|
|
6
|
+
t.string :scope
|
|
7
|
+
t.datetime :created_at
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
add_index :slugs, [ :slug, :sluggable_type ]
|
|
11
|
+
add_index :slugs, [ :slug, :sluggable_type, :scope ], unique: true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module CafeCar::ActiveRecord
|
|
2
|
+
module SQLite3Extension
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
alias_method :pre_cafe_car_initialize, :initialize
|
|
7
|
+
private :pre_cafe_car_initialize
|
|
8
|
+
|
|
9
|
+
def initialize(*args)
|
|
10
|
+
pre_cafe_car_initialize(*args)
|
|
11
|
+
|
|
12
|
+
raw_connection.create_function("regexp", -1) do |func, pattern, expression, case_sensitive|
|
|
13
|
+
options = 0
|
|
14
|
+
options |= Regexp::IGNORECASE if case_sensitive.zero?
|
|
15
|
+
pattern = Regexp.new(pattern.to_s, options)
|
|
16
|
+
func.result = expression.to_s.match(pattern) ? 1 : 0
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require "responders"
|
|
2
|
+
|
|
3
|
+
module CafeCar
|
|
4
|
+
class ApplicationResponder < ActionController::Responder
|
|
5
|
+
include Responders::FlashResponder
|
|
6
|
+
include Responders::HttpCacheResponder
|
|
7
|
+
|
|
8
|
+
self.error_status = :unprocessable_entity
|
|
9
|
+
self.redirect_status = :see_other
|
|
10
|
+
|
|
11
|
+
def to_turbo_stream
|
|
12
|
+
# Put :html back in the accepted format list. respond_with removes it
|
|
13
|
+
controller.lookup_context.formats << :html
|
|
14
|
+
to_html
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class CafeCar::Attributes
|
|
2
|
+
attr_reader :user, :object, :permitted
|
|
3
|
+
|
|
4
|
+
def initialize(user, object, permitted_attributes)
|
|
5
|
+
@user = user
|
|
6
|
+
@object = object
|
|
7
|
+
@permitted = [ *permitted_attributes ]
|
|
8
|
+
process_attributes!
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def info(method) = CafeCar[:FieldInfo].new(object:, method:)
|
|
12
|
+
|
|
13
|
+
def editable
|
|
14
|
+
@editable ||= @permitted.map()
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def process_attributes!
|
|
21
|
+
@editable = @permitted.clone
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module CafeCar
|
|
2
|
+
module AutoResolver
|
|
3
|
+
def auto_resolve!(mod)
|
|
4
|
+
mod.instance_eval <<~RUBY, __FILE__, __LINE__
|
|
5
|
+
def const_missing(name)
|
|
6
|
+
super
|
|
7
|
+
rescue NameError
|
|
8
|
+
CafeCar.define(self, name) or raise
|
|
9
|
+
end
|
|
10
|
+
RUBY
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def define(mod, name)
|
|
14
|
+
case name.to_s
|
|
15
|
+
when /^\w+Controller$/
|
|
16
|
+
TOPLEVEL_BINDING.eval <<~RUBY, __FILE__, __LINE__
|
|
17
|
+
class #{mod.name}::#{name} < CafeCar[:ApplicationController]
|
|
18
|
+
include CafeCar::Controller
|
|
19
|
+
cafe_car
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
RUBY
|
|
23
|
+
when /^\w+Policy$/
|
|
24
|
+
TOPLEVEL_BINDING.eval <<~RUBY, __FILE__, __LINE__
|
|
25
|
+
class #{mod.name}::#{name} < CafeCar[:ApplicationPolicy]
|
|
26
|
+
def admin? = Rails.env.development?
|
|
27
|
+
|
|
28
|
+
def index? = admin?
|
|
29
|
+
def show? = admin?
|
|
30
|
+
def create? = admin?
|
|
31
|
+
def update? = admin?
|
|
32
|
+
def destroy? = admin?
|
|
33
|
+
|
|
34
|
+
def permitted_attributes
|
|
35
|
+
model.info.fields.names.then do |names|
|
|
36
|
+
[*model.primary_key].reverse.map(&:to_sym) & names | names
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Scope < Scope
|
|
41
|
+
def resolve = scope.all
|
|
42
|
+
end
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
RUBY
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module CafeCar::Caching
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
def cache(name, &)
|
|
5
|
+
instance_variable_get("@#{name}") || instance_variable_set("@#{name}", instance_exec(&))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class_methods do
|
|
9
|
+
def derive(name, proc = nil, &block)
|
|
10
|
+
proc ||= block
|
|
11
|
+
define_method(name) { cache(name, &proc) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cache!(name)
|
|
15
|
+
prepend Module.new.tap { _1.module_eval <<~RUBY }
|
|
16
|
+
def #{name} = cache(:#{name}) { super }
|
|
17
|
+
RUBY
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|