letter_opener_web 1.4.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/brakeman-analysis.yml +46 -0
- data/.github/workflows/main.yml +34 -0
- data/.github/workflows/release-gem.yml +32 -0
- data/.rspec +1 -1
- data/.rubocop.yml +4 -13
- data/.rubocop_todo.yml +19 -0
- data/CHANGELOG.md +13 -0
- data/LICENSE.txt +1 -1
- data/README.md +29 -20
- data/app/controllers/letter_opener_web/application_controller.rb +1 -0
- data/app/controllers/letter_opener_web/letters_controller.rb +7 -4
- data/app/models/letter_opener_web/letter.rb +22 -1
- data/app/views/layouts/letter_opener_web/_javascripts.html.erb +26 -559
- data/app/views/layouts/letter_opener_web/_styles.html.erb +3 -63
- data/app/views/layouts/letter_opener_web/js/_favcount.html.erb +104 -0
- data/app/views/layouts/letter_opener_web/js/_jquery.html.erb +7 -0
- data/app/views/layouts/letter_opener_web/letters.html.erb +4 -3
- data/app/views/layouts/letter_opener_web/styles/_bootstrap.html.erb +9 -0
- data/app/views/layouts/letter_opener_web/styles/_icon.html.erb +2 -0
- data/app/views/layouts/letter_opener_web/styles/_letters.html.erb +70 -0
- data/app/views/letter_opener_web/letters/_item.html.erb +10 -0
- data/app/views/letter_opener_web/letters/index.html.erb +11 -46
- data/config/routes.rb +5 -5
- data/letter_opener_web.gemspec +11 -8
- data/lib/letter_opener_web/version.rb +1 -1
- data/lib/letter_opener_web.rb +1 -0
- data/spec/controllers/letter_opener_web/letters_controller_spec.rb +4 -4
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/assets/stylesheets/application.css +0 -16
- data/spec/dummy/app/channels/application_cable/channel.rb +6 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +0 -1
- data/spec/dummy/app/{assets/javascripts → javascript/packs}/application.js +2 -0
- data/spec/dummy/app/jobs/application_job.rb +9 -0
- data/spec/dummy/app/models/application_record.rb +5 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +4 -7
- data/spec/dummy/bin/rails +2 -4
- data/spec/dummy/bin/rake +2 -4
- data/spec/dummy/bin/setup +7 -10
- data/spec/dummy/config/application.rb +21 -7
- data/spec/dummy/config/environments/development.rb +44 -6
- data/spec/dummy/config/environments/production.rb +51 -14
- data/spec/dummy/config/environments/test.rb +30 -6
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -4
- data/spec/dummy/config/initializers/assets.rb +5 -5
- data/spec/dummy/config/initializers/backtrace_silencers.rb +5 -3
- data/spec/dummy/config/initializers/content_security_policy.rb +29 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +3 -1
- data/spec/dummy/config/initializers/permissions_policy.rb +12 -0
- data/spec/dummy/config/locales/en.yml +11 -1
- data/spec/dummy/config/puma.rb +18 -22
- data/spec/dummy/config/routes.rb +1 -4
- data/spec/dummy/config.ru +1 -0
- data/spec/dummy/public/404.html +6 -6
- data/spec/dummy/public/422.html +6 -6
- data/spec/dummy/public/500.html +6 -6
- data/spec/dummy/storage/.keep +0 -0
- data/spec/letter_opener_web_spec.rb +2 -2
- data/spec/models/letter_opener_web/letter_spec.rb +48 -14
- metadata +87 -42
- data/.travis.yml +0 -23
- data/spec/dummy/app/controllers/home_controller.rb +0 -10
- data/spec/dummy/app/mailers/contact_mailer.rb +0 -14
- data/spec/dummy/app/views/contact_mailer/new_message.html.erb +0 -21
- data/spec/dummy/app/views/contact_mailer/new_message.text.erb +0 -3
- data/spec/dummy/app/views/home/index.html.erb +0 -50
- data/spec/dummy/bin/bundle +0 -5
- data/spec/dummy/bin/update +0 -31
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -5
- data/spec/dummy/config/secrets.yml +0 -22
- data/spec/dummy/config/spring.rb +0 -8
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Define an application-wide HTTP permissions policy. For further
|
3
|
+
# information see https://developers.google.com/web/updates/2018/06/feature-policy
|
4
|
+
#
|
5
|
+
# Rails.application.config.permissions_policy do |f|
|
6
|
+
# f.camera :none
|
7
|
+
# f.gyroscope :none
|
8
|
+
# f.microphone :none
|
9
|
+
# f.usb :none
|
10
|
+
# f.fullscreen :self
|
11
|
+
# f.payment :self, "https://secure.example.com"
|
12
|
+
# end
|
@@ -16,8 +16,18 @@
|
|
16
16
|
#
|
17
17
|
# This would use the information in config/locales/es.yml.
|
18
18
|
#
|
19
|
+
# The following keys must be escaped otherwise they will not be retrieved by
|
20
|
+
# the default I18n backend:
|
21
|
+
#
|
22
|
+
# true, false, on, off, yes, no
|
23
|
+
#
|
24
|
+
# Instead, surround them with single quotes.
|
25
|
+
#
|
26
|
+
# en:
|
27
|
+
# 'true': 'foo'
|
28
|
+
#
|
19
29
|
# To learn more, please read the Rails Internationalization guide
|
20
|
-
# available at
|
30
|
+
# available at https://guides.rubyonrails.org/i18n.html.
|
21
31
|
|
22
32
|
en:
|
23
33
|
hello: "Hello world"
|
data/spec/dummy/config/puma.rb
CHANGED
@@ -1,24 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Puma can serve each request in a thread from an internal thread pool.
|
4
|
-
# The `threads` method setting takes two numbers a minimum and maximum.
|
4
|
+
# The `threads` method setting takes two numbers: a minimum and maximum.
|
5
5
|
# Any libraries that use thread pools should be configured to match
|
6
6
|
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
7
|
-
# and maximum
|
7
|
+
# and maximum; this matches the default thread size of Active Record.
|
8
8
|
#
|
9
|
-
|
10
|
-
|
9
|
+
max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
|
10
|
+
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
|
11
|
+
threads min_threads_count, max_threads_count
|
11
12
|
|
12
|
-
# Specifies the `
|
13
|
+
# Specifies the `worker_timeout` threshold that Puma will use to wait before
|
14
|
+
# terminating a worker in development environments.
|
13
15
|
#
|
14
|
-
|
16
|
+
worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development'
|
17
|
+
|
18
|
+
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
19
|
+
#
|
20
|
+
port ENV.fetch('PORT', 3000)
|
15
21
|
|
16
22
|
# Specifies the `environment` that Puma will run in.
|
17
23
|
#
|
18
|
-
environment ENV.fetch('RAILS_ENV'
|
24
|
+
environment ENV.fetch('RAILS_ENV', 'development')
|
25
|
+
|
26
|
+
# Specifies the `pidfile` that Puma will use.
|
27
|
+
pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid')
|
19
28
|
|
20
29
|
# Specifies the number of `workers` to boot in clustered mode.
|
21
|
-
# Workers are forked
|
30
|
+
# Workers are forked web server processes. If using threads and workers together
|
22
31
|
# the concurrency of the application would be max `threads` * `workers`.
|
23
32
|
# Workers do not work on JRuby or Windows (both of which do not support
|
24
33
|
# processes).
|
@@ -28,22 +37,9 @@ environment ENV.fetch('RAILS_ENV') { 'development' }
|
|
28
37
|
# Use the `preload_app!` method when specifying a `workers` number.
|
29
38
|
# This directive tells Puma to first boot the application and load code
|
30
39
|
# before forking the application. This takes advantage of Copy On Write
|
31
|
-
# process behavior so workers use less memory.
|
32
|
-
# you need to make sure to reconnect any threads in the `on_worker_boot`
|
33
|
-
# block.
|
40
|
+
# process behavior so workers use less memory.
|
34
41
|
#
|
35
42
|
# preload_app!
|
36
43
|
|
37
|
-
# The code in the `on_worker_boot` will be called if you are using
|
38
|
-
# clustered mode by specifying a number of `workers`. After each worker
|
39
|
-
# process is booted this block will be run, if you are using `preload_app!`
|
40
|
-
# option you will want to use this block to reconnect to any threads
|
41
|
-
# or connections that may have been created at application boot, Ruby
|
42
|
-
# cannot share connections between processes.
|
43
|
-
#
|
44
|
-
# on_worker_boot do
|
45
|
-
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
|
46
|
-
# end
|
47
|
-
|
48
44
|
# Allow puma to be restarted by `rails restart` command.
|
49
45
|
plugin :tmp_restart
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/config.ru
CHANGED
data/spec/dummy/public/404.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The page you were looking for doesn't exist (404)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/404.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/422.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The change you wanted was rejected (422)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/422.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/500.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>We're sorry, but something went wrong (500)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/500.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
File without changes
|
@@ -1,19 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
describe LetterOpenerWeb::Letter do
|
3
|
+
RSpec.describe LetterOpenerWeb::Letter do
|
4
4
|
let(:location) { Pathname.new(__dir__).join('..', '..', 'tmp').cleanpath }
|
5
5
|
|
6
6
|
def rich_text(mail_id)
|
7
|
-
|
8
|
-
Rich text for #{mail_id}
|
9
|
-
<!DOCTYPE html>
|
10
|
-
<
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
<
|
15
|
-
<
|
16
|
-
|
7
|
+
<<~MAIL
|
8
|
+
Rich text for #{mail_id}
|
9
|
+
<!DOCTYPE html>
|
10
|
+
<body>
|
11
|
+
<div id="container">
|
12
|
+
<div id="message_headers">
|
13
|
+
<dl>
|
14
|
+
<dt>From:</dt>
|
15
|
+
<dd>noreply@example.com</dd>
|
16
|
+
</dl>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<a href='a-link.html'>
|
20
|
+
<img src='an-image.jpg'>
|
21
|
+
Link text
|
22
|
+
</a>
|
23
|
+
<a href='fooo.html'>Bar</a>
|
24
|
+
<a href="example.html" class="blank"></a>
|
25
|
+
<address><a href="inside-address.html">inside address</a></address>
|
26
|
+
</div>
|
27
|
+
</body>
|
17
28
|
MAIL
|
18
29
|
end
|
19
30
|
|
@@ -36,6 +47,28 @@ Rich text for #{mail_id}
|
|
36
47
|
FileUtils.rm_rf(location)
|
37
48
|
end
|
38
49
|
|
50
|
+
describe 'rich text headers' do
|
51
|
+
let(:id) { '1111_1111' }
|
52
|
+
subject { described_class.new(id: id).headers }
|
53
|
+
|
54
|
+
before do
|
55
|
+
FileUtils.rm_rf("#{location}/#{id}/plain.html")
|
56
|
+
end
|
57
|
+
|
58
|
+
it { is_expected.to match(%r{<dl>\s*<dt>From:</dt>\s*<dd>noreply@example\.com</dd>}m) }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'plain text headers' do
|
62
|
+
let(:id) { '1111_1111' }
|
63
|
+
subject { described_class.new(id: id).headers }
|
64
|
+
|
65
|
+
before do
|
66
|
+
FileUtils.rm_rf("#{location}/#{id}/rich.html")
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to eq('UNABLE TO PARSE HEADERS') }
|
70
|
+
end
|
71
|
+
|
39
72
|
describe 'rich text version' do
|
40
73
|
let(:id) { '1111_1111' }
|
41
74
|
subject { described_class.new(id: id).rich_text }
|
@@ -45,9 +78,10 @@ Rich text for #{mail_id}
|
|
45
78
|
it 'changes links to show up on a new window' do
|
46
79
|
link_html = [
|
47
80
|
"<a href='a-link.html' target='_blank'>",
|
48
|
-
"<img src='an-image.jpg'/>",
|
49
|
-
|
50
|
-
|
81
|
+
" <img src='an-image.jpg'/>",
|
82
|
+
' Link text',
|
83
|
+
'</a>'
|
84
|
+
].join("\n ")
|
51
85
|
|
52
86
|
expect(subject).to include(link_html)
|
53
87
|
end
|