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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/brakeman-analysis.yml +46 -0
  3. data/.github/workflows/main.yml +34 -0
  4. data/.github/workflows/release-gem.yml +32 -0
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +4 -13
  7. data/.rubocop_todo.yml +19 -0
  8. data/CHANGELOG.md +13 -0
  9. data/LICENSE.txt +1 -1
  10. data/README.md +29 -20
  11. data/app/controllers/letter_opener_web/application_controller.rb +1 -0
  12. data/app/controllers/letter_opener_web/letters_controller.rb +7 -4
  13. data/app/models/letter_opener_web/letter.rb +22 -1
  14. data/app/views/layouts/letter_opener_web/_javascripts.html.erb +26 -559
  15. data/app/views/layouts/letter_opener_web/_styles.html.erb +3 -63
  16. data/app/views/layouts/letter_opener_web/js/_favcount.html.erb +104 -0
  17. data/app/views/layouts/letter_opener_web/js/_jquery.html.erb +7 -0
  18. data/app/views/layouts/letter_opener_web/letters.html.erb +4 -3
  19. data/app/views/layouts/letter_opener_web/styles/_bootstrap.html.erb +9 -0
  20. data/app/views/layouts/letter_opener_web/styles/_icon.html.erb +2 -0
  21. data/app/views/layouts/letter_opener_web/styles/_letters.html.erb +70 -0
  22. data/app/views/letter_opener_web/letters/_item.html.erb +10 -0
  23. data/app/views/letter_opener_web/letters/index.html.erb +11 -46
  24. data/config/routes.rb +5 -5
  25. data/letter_opener_web.gemspec +11 -8
  26. data/lib/letter_opener_web/version.rb +1 -1
  27. data/lib/letter_opener_web.rb +1 -0
  28. data/spec/controllers/letter_opener_web/letters_controller_spec.rb +4 -4
  29. data/spec/dummy/app/assets/config/manifest.js +0 -2
  30. data/spec/dummy/app/assets/stylesheets/application.css +0 -16
  31. data/spec/dummy/app/channels/application_cable/channel.rb +6 -0
  32. data/spec/dummy/app/channels/application_cable/connection.rb +6 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +0 -1
  34. data/spec/dummy/app/{assets/javascripts → javascript/packs}/application.js +2 -0
  35. data/spec/dummy/app/jobs/application_job.rb +9 -0
  36. data/spec/dummy/app/models/application_record.rb +5 -0
  37. data/spec/dummy/app/models/concerns/.keep +0 -0
  38. data/spec/dummy/app/views/layouts/application.html.erb +4 -7
  39. data/spec/dummy/bin/rails +2 -4
  40. data/spec/dummy/bin/rake +2 -4
  41. data/spec/dummy/bin/setup +7 -10
  42. data/spec/dummy/config/application.rb +21 -7
  43. data/spec/dummy/config/environments/development.rb +44 -6
  44. data/spec/dummy/config/environments/production.rb +51 -14
  45. data/spec/dummy/config/environments/test.rb +30 -6
  46. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -4
  47. data/spec/dummy/config/initializers/assets.rb +5 -5
  48. data/spec/dummy/config/initializers/backtrace_silencers.rb +5 -3
  49. data/spec/dummy/config/initializers/content_security_policy.rb +29 -0
  50. data/spec/dummy/config/initializers/filter_parameter_logging.rb +3 -1
  51. data/spec/dummy/config/initializers/permissions_policy.rb +12 -0
  52. data/spec/dummy/config/locales/en.yml +11 -1
  53. data/spec/dummy/config/puma.rb +18 -22
  54. data/spec/dummy/config/routes.rb +1 -4
  55. data/spec/dummy/config.ru +1 -0
  56. data/spec/dummy/public/404.html +6 -6
  57. data/spec/dummy/public/422.html +6 -6
  58. data/spec/dummy/public/500.html +6 -6
  59. data/spec/dummy/storage/.keep +0 -0
  60. data/spec/letter_opener_web_spec.rb +2 -2
  61. data/spec/models/letter_opener_web/letter_spec.rb +48 -14
  62. metadata +87 -42
  63. data/.travis.yml +0 -23
  64. data/spec/dummy/app/controllers/home_controller.rb +0 -10
  65. data/spec/dummy/app/mailers/contact_mailer.rb +0 -14
  66. data/spec/dummy/app/views/contact_mailer/new_message.html.erb +0 -21
  67. data/spec/dummy/app/views/contact_mailer/new_message.text.erb +0 -3
  68. data/spec/dummy/app/views/home/index.html.erb +0 -50
  69. data/spec/dummy/bin/bundle +0 -5
  70. data/spec/dummy/bin/update +0 -31
  71. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
  72. data/spec/dummy/config/initializers/session_store.rb +0 -5
  73. data/spec/dummy/config/secrets.yml +0 -22
  74. 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 http://guides.rubyonrails.org/i18n.html.
30
+ # available at https://guides.rubyonrails.org/i18n.html.
21
31
 
22
32
  en:
23
33
  hello: "Hello world"
@@ -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, this matches the default thread size of Active Record.
7
+ # and maximum; this matches the default thread size of Active Record.
8
8
  #
9
- threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }.to_i
10
- threads threads_count, threads_count
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 `port` that Puma will listen on to receive requests, default is 3000.
13
+ # Specifies the `worker_timeout` threshold that Puma will use to wait before
14
+ # terminating a worker in development environments.
13
15
  #
14
- port ENV.fetch('PORT') { 3000 }
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') { 'development' }
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 webserver processes. If using threads and workers together
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. If you use this option
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
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.routes.draw do
4
- mount LetterOpenerWeb::Engine => '/letter_opener'
5
-
6
- root to: 'home#index'
7
- post '/', to: 'home#create'
4
+ mount LetterOpenerWeb::Engine => '/letter_opener_web'
8
5
  end
data/spec/dummy/config.ru CHANGED
@@ -5,3 +5,4 @@
5
5
  require_relative 'config/environment'
6
6
 
7
7
  run Rails.application
8
+ Rails.application.load_server
@@ -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
- body {
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>
@@ -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
- body {
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>
@@ -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
- body {
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,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
- describe LetterOpenerWeb do
5
+ RSpec.describe LetterOpenerWeb do
6
6
  subject { described_class }
7
7
  after(:each) { described_class.reset! }
8
8
 
@@ -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
- <<-MAIL
8
- Rich text for #{mail_id}
9
- <!DOCTYPE html>
10
- <a href='a-link.html'>
11
- <img src='an-image.jpg'>
12
- Link text
13
- </a>
14
- <a href='fooo.html'>Bar</a>
15
- <a href="example.html" class="blank"></a>
16
- <address><a href="inside-address.html">inside address</a></address>
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
- "Link text\n</a>"
50
- ].join("\n ")
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