brut 0.0.24 → 0.0.26
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/Gemfile.lock +1 -1
- data/brutrb.com/.vitepress/config.mjs +13 -1
- data/brutrb.com/recipes/authentication.md +26 -0
- data/lib/brut/cli/apps/db.rb +3 -0
- data/lib/brut/front_end/components/form_tag.rb +16 -8
- data/lib/brut/front_end/components/inputs/input_tag.rb +5 -12
- data/lib/brut/front_end/components/inputs/radio_button.rb +8 -4
- data/lib/brut/front_end/components/inputs/textarea_tag.rb +5 -12
- data/lib/brut/front_end/request_context.rb +9 -0
- data/lib/brut/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 327b83333a37823010e1d2763646d56bd503d505d6c965ddc5d0d8098ecd9299
|
4
|
+
data.tar.gz: d12d8d46f6e459d97f3489218302da647e073ac4d8e48cf57cd1d1fee998c6a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a55e3607d5d127e74f93864f6dc19fad6dc2a0631e56559cf92df4b5762771d82d5bc0c5a2d289d6948a0899568e0138e503fea98f91d42007cefb9b3e83482b
|
7
|
+
data.tar.gz: e901897e8d8eb2a2ef08bc4e5efacc0c3a13f6981f8523a2e0db3ade740f648923ecb29e9634ea133dd16efccedeecb0b9ec06f820c0b4d77b7f34068f96d540
|
data/Gemfile.lock
CHANGED
@@ -83,13 +83,25 @@ export default defineConfig({
|
|
83
83
|
},
|
84
84
|
{
|
85
85
|
text: "Advanced Topics",
|
86
|
-
collapsed:
|
86
|
+
collapsed: true,
|
87
87
|
items: [
|
88
88
|
{ text: "Route Hooks", link: "/hooks" },
|
89
89
|
{ text: "Middleware", link: "/middleware" },
|
90
90
|
{ text: "Instrumentation", link: "/instrumentation" },
|
91
91
|
{ text: "Security", link: "/security" },
|
92
92
|
],
|
93
|
+
},
|
94
|
+
{
|
95
|
+
text: "Recipes",
|
96
|
+
collapsed: true,
|
97
|
+
items: [
|
98
|
+
{ text: "Authentication", link: "/recipes/authentication" },
|
99
|
+
{ text: "Form Validations", link: "/recipes/form-validations" },
|
100
|
+
{ text: "Database Migrations", link: "/recipes/database-migrations" },
|
101
|
+
{ text: "Ajax Form Submission", link: "/recipes/ajax-form" },
|
102
|
+
{ text: "Custom Telemetry", link: "/recipes/telemetry" },
|
103
|
+
{ text: "CLI App/Task", link: "/recipes/cli-app" },
|
104
|
+
],
|
93
105
|
}
|
94
106
|
],
|
95
107
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Authentication Example
|
2
|
+
|
3
|
+
It's impossible to account for all types of authentication you may want to use, but
|
4
|
+
this recipe will demonstrate all the moving parts:
|
5
|
+
|
6
|
+
* How to require authentication for some pages
|
7
|
+
* How to design pages that require authentication
|
8
|
+
* How to manage the signed-in user in code
|
9
|
+
|
10
|
+
## Feature Description
|
11
|
+
|
12
|
+
* Visitors can sign up for an account with an email and password
|
13
|
+
* Visitors can log in with their email and password
|
14
|
+
* Visitors cannot access the home page without logging in
|
15
|
+
* Visitors can access the about page without logging in
|
16
|
+
|
17
|
+
## Recipe
|
18
|
+
|
19
|
+
First, we'll make a database table called `accounts` that will have an email field
|
20
|
+
and a password hash field.
|
21
|
+
|
22
|
+
```
|
23
|
+
bin/db new-migration accounts
|
24
|
+
```
|
25
|
+
|
26
|
+
This will create a file in `app/src/back_end/data_models/migrations`
|
data/lib/brut/cli/apps/db.rb
CHANGED
@@ -170,6 +170,9 @@ class Brut::CLI::Apps::DB < Brut::CLI::App
|
|
170
170
|
if !migrations_dir.exist?
|
171
171
|
err.puts "#{migrations_dir} doesn't exist"
|
172
172
|
return
|
173
|
+
elsif Dir[migrations_dir / "*.rb"].empty?
|
174
|
+
out.puts "No migrations yet"
|
175
|
+
return
|
173
176
|
end
|
174
177
|
Brut.container.sequel_db_handle.extension :pg_array
|
175
178
|
|
@@ -4,16 +4,24 @@ class Brut::FrontEnd::Components::FormTag < Brut::FrontEnd::Component
|
|
4
4
|
# If the form's action is GET, it will not.
|
5
5
|
#
|
6
6
|
# @example Route without parameters
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
7
|
+
# # assumes you have included Brut::FrontEnd::Components
|
8
|
+
# def view_template
|
9
|
+
# FormTag(for: NewWidgetForm, class: "new-form") do
|
10
|
+
# input(type: "text", name: "name")
|
11
|
+
# button { "Create" }
|
12
|
+
# end
|
13
|
+
# end
|
11
14
|
#
|
12
15
|
# @example Route with parameters
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
16
|
+
# # assumes you have included Brut::FrontEnd::Components
|
17
|
+
# def view_template
|
18
|
+
# FormTag(for: SaveWidgetWithIdForm,
|
19
|
+
# route_params: { id: widget.external_id },
|
20
|
+
# class: "new-form") do
|
21
|
+
# input(type: "text", name: "name")
|
22
|
+
# button { "Save" }
|
23
|
+
# end
|
24
|
+
# end
|
17
25
|
#
|
18
26
|
# @param route_params [Hash] if the form requires route parameters, their values must be passed here so that the HTML `action`
|
19
27
|
# attribute can be constructed properly.
|
@@ -1,5 +1,7 @@
|
|
1
|
-
# Generates an HTML `<input>` field.
|
1
|
+
# Generates an HTML `<input>` field based on a form input.
|
2
2
|
class Brut::FrontEnd::Components::Inputs::InputTag < Brut::FrontEnd::Components::Input
|
3
|
+
def invalid? = @attributes["data-invalid"] == true
|
4
|
+
|
3
5
|
# Creates the appropriate input for the given {Brut::FrontEnd::Form} and input name.
|
4
6
|
# Generally, you want to use this method over the initializer.
|
5
7
|
#
|
@@ -7,7 +9,7 @@ class Brut::FrontEnd::Components::Inputs::InputTag < Brut::FrontEnd::Components:
|
|
7
9
|
# @param [String] input_name the name of the input, which should be a member of `form`
|
8
10
|
# @param [Integer] index if this input is part of an array, this is the index into that array. This is used to get the input's value.
|
9
11
|
# @param [Hash] html_attributes any additional HTML attributes to include on the `<input>` element.
|
10
|
-
def
|
12
|
+
def initialize(form:, input_name:, index: nil, **html_attributes)
|
11
13
|
input = form.input(input_name, index:)
|
12
14
|
default_html_attributes = {}
|
13
15
|
html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
|
@@ -49,16 +51,7 @@ class Brut::FrontEnd::Components::Inputs::InputTag < Brut::FrontEnd::Components:
|
|
49
51
|
default_html_attributes["data-#{constraint}"] = true
|
50
52
|
end
|
51
53
|
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
def invalid? = @attributes["data-invalid"] == true
|
56
|
-
|
57
|
-
# Create an instance
|
58
|
-
#
|
59
|
-
# @param [Hash] attributes HTML attributes to put on the element.
|
60
|
-
def initialize(attributes)
|
61
|
-
@attributes = attributes
|
54
|
+
@attributes = default_html_attributes.merge(html_attributes)
|
62
55
|
end
|
63
56
|
|
64
57
|
def view_template
|
@@ -12,14 +12,18 @@ class Brut::FrontEnd::Components::Inputs::RadioButton < Brut::FrontEnd::Componen
|
|
12
12
|
# @param [String] value the value for this radio button. The {Brut::FrontEnd::Forms::RadioButtonGroupInput} value is compared
|
13
13
|
# against this value to determine if this `<input>` will have the `checked` attribute.
|
14
14
|
# @param [Hash] html_attributes any additional HTML attributes to include on the `<input>` element.
|
15
|
-
def
|
15
|
+
def initialize(form:, input_name:, value:, html_attributes: {})
|
16
|
+
input = form.input(input_name)
|
16
17
|
default_html_attributes = {}
|
17
18
|
html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
|
18
|
-
input = form.input(input_name)
|
19
19
|
|
20
20
|
default_html_attributes[:required] = input.required
|
21
21
|
default_html_attributes[:type] = "radio"
|
22
|
-
default_html_attributes[:name] = input.
|
22
|
+
default_html_attributes[:name] = if input.array?
|
23
|
+
"#{input.name}[]"
|
24
|
+
else
|
25
|
+
input.name
|
26
|
+
end
|
23
27
|
default_html_attributes[:value] = value
|
24
28
|
|
25
29
|
selected_value = input.value
|
@@ -36,6 +40,6 @@ class Brut::FrontEnd::Components::Inputs::RadioButton < Brut::FrontEnd::Componen
|
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
39
|
-
|
43
|
+
@attributes = default_html_attributes.merge(html_attributes)
|
40
44
|
end
|
41
45
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
# Generates an HTML `<textarea>` field.
|
1
|
+
# Generates an HTML `<textarea>` field based on a form input.
|
2
2
|
class Brut::FrontEnd::Components::Inputs::TextareaTag < Brut::FrontEnd::Components::Input
|
3
|
+
|
3
4
|
# Creates the appropriate textarea for the given {Brut::FrontEnd::Form} and input name.
|
4
5
|
# Generally, you want to use this method over the initializer.
|
5
6
|
#
|
@@ -7,7 +8,7 @@ class Brut::FrontEnd::Components::Inputs::TextareaTag < Brut::FrontEnd::Componen
|
|
7
8
|
# @param [String] input_name the name of the input, which should be a member of `form`
|
8
9
|
# @param [Integer] index if this input is part of an array, this is the index into that array. This is used to get the input's value.
|
9
10
|
# @param [Hash] html_attributes any additional HTML attributes to include on the `<textarea>` element.
|
10
|
-
def
|
11
|
+
def initialize(form:, input_name:, index: nil, **html_attributes)
|
11
12
|
html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
|
12
13
|
default_html_attributes = {}
|
13
14
|
|
@@ -34,16 +35,8 @@ class Brut::FrontEnd::Components::Inputs::TextareaTag < Brut::FrontEnd::Componen
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
|
-
value = input.value
|
38
|
-
|
39
|
-
end
|
40
|
-
# Create an instance
|
41
|
-
#
|
42
|
-
# @param [Hash] attributes HTML attributes to put on the element.
|
43
|
-
# @param [String] value the value to place inside the text area
|
44
|
-
def initialize(attributes, value)
|
45
|
-
@attributes = attributes
|
46
|
-
@value = value
|
38
|
+
@value = input.value
|
39
|
+
@attributes = default_html_attributes.merge(html_attributes)
|
47
40
|
end
|
48
41
|
|
49
42
|
def invalid? = @attributes["data-invalid"] == true
|
@@ -167,6 +167,7 @@ private
|
|
167
167
|
|
168
168
|
def args_for_method(method:, request_params:, form:,route:)
|
169
169
|
args = {}
|
170
|
+
rack_request = Rack::Request.new(self[:env])
|
170
171
|
method.parameters.each do |(type,name)|
|
171
172
|
|
172
173
|
if name.to_s == "**" || name.to_s == "*"
|
@@ -185,6 +186,14 @@ private
|
|
185
186
|
elsif type == :keyreq
|
186
187
|
args[name] = nil
|
187
188
|
end
|
189
|
+
elsif name.to_s =~ /^rack_request_[^_]+/ &&
|
190
|
+
rack_request.respond_to?(name.to_s.sub(/^rack_request_/,""))
|
191
|
+
value = rack_request.send(name.to_s.sub(/^rack_request_/,""))
|
192
|
+
if value
|
193
|
+
args[name] = value
|
194
|
+
elsif type == :keyreq
|
195
|
+
args[name] = nil
|
196
|
+
end
|
188
197
|
elsif !form.nil? && name == :form
|
189
198
|
args[name] = form
|
190
199
|
elsif !route.nil? && name == :route
|
data/lib/brut/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Bryant Copeland
|
@@ -623,6 +623,7 @@ files:
|
|
623
623
|
- brutrb.com/pages.md
|
624
624
|
- brutrb.com/public/images/logo-300.png
|
625
625
|
- brutrb.com/public/images/logo.png
|
626
|
+
- brutrb.com/recipes/authentication.md
|
626
627
|
- brutrb.com/routes.md
|
627
628
|
- brutrb.com/security.md
|
628
629
|
- brutrb.com/seed-data.md
|