letter_opener_web 1.3.4 → 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/.gitignore +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +5 -16
- data/.rubocop_todo.yml +19 -0
- data/CHANGELOG.md +22 -1
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +33 -24
- data/app/controllers/letter_opener_web/application_controller.rb +1 -0
- data/app/controllers/letter_opener_web/letters_controller.rb +14 -7
- data/app/models/letter_opener_web/letter.rb +37 -5
- data/app/views/layouts/letter_opener_web/_javascripts.html.erb +31 -0
- data/app/views/layouts/letter_opener_web/_styles.html.erb +3 -0
- data/{vendor/assets/javascripts/letter_opener_web/favcount.js → app/views/layouts/letter_opener_web/js/_favcount.html.erb} +9 -7
- data/app/views/layouts/letter_opener_web/js/_jquery.html.erb +7 -0
- data/app/views/layouts/letter_opener_web/letters.html.erb +5 -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 +19 -15
- data/lib/letter_opener_web/delivery_method.rb +1 -1
- data/lib/letter_opener_web/engine.rb +0 -10
- 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 +22 -11
- 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 +62 -17
- data/spec/spec_helper.rb +8 -0
- metadata +91 -54
- data/.travis.yml +0 -26
- data/app/assets/javascripts/letter_opener_web/application.js +0 -30
- data/app/assets/stylesheets/letter_opener_web/application.css.erb +0 -54
- data/bin/rails +0 -11
- 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
- data/vendor/assets/images/letter_opener_web/blue-dot.ico +0 -0
- data/vendor/assets/images/letter_opener_web/glyphicons-halflings-white.png +0 -0
- data/vendor/assets/images/letter_opener_web/glyphicons-halflings.png +0 -0
- data/vendor/assets/javascripts/letter_opener_web/bootstrap.min.js +0 -6
- data/vendor/assets/javascripts/letter_opener_web/jquery-1.8.3.min.js +0 -2
- data/vendor/assets/javascripts/letter_opener_web/jquery_ujs.js +0 -429
- data/vendor/assets/stylesheets/letter_opener_web/bootstrap.min.css +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b31a75a1e88a4e79a2c79ef92da951522caf6ffbd7ab684b53a46b0982efd85
|
4
|
+
data.tar.gz: a4f6a87162bdcc3d28632f192f97aaba812939697c08c86904a36aa4ce9b6da8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c4e1575132e8e895cdd5fdc881516396af19c3efabde95276727c39f106df67d7f0237ae009264f7b31dce15cfd8d83874f0f098fa1145ed2c5d2f4a77fd2d8
|
7
|
+
data.tar.gz: d3b2d72727adfe59f1c3468d832df6522d7792ee1d7e555a205ec2720a2c34e3ff7689cb38016e0561b89ed04ab94e364cdfca68235c4c0f9c1c1a630db140c5
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# This workflow integrates Brakeman with GitHub's Code Scanning feature
|
2
|
+
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
|
3
|
+
|
4
|
+
name: Brakeman Scan
|
5
|
+
|
6
|
+
on:
|
7
|
+
push:
|
8
|
+
branches: [ master ]
|
9
|
+
pull_request:
|
10
|
+
# The branches below must be a subset of the branches above
|
11
|
+
branches: [ master ]
|
12
|
+
schedule:
|
13
|
+
- cron: '21 4 * * 4'
|
14
|
+
|
15
|
+
jobs:
|
16
|
+
brakeman-scan:
|
17
|
+
name: Brakeman Scan
|
18
|
+
runs-on: ubuntu-latest
|
19
|
+
steps:
|
20
|
+
# Checkout the repository to the GitHub Actions runner
|
21
|
+
- name: Checkout
|
22
|
+
uses: actions/checkout@v2
|
23
|
+
|
24
|
+
# Customize the ruby version depending on your needs
|
25
|
+
- name: Setup Ruby
|
26
|
+
uses: actions/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: '2.7'
|
29
|
+
|
30
|
+
- name: Setup Brakeman
|
31
|
+
env:
|
32
|
+
BRAKEMAN_VERSION: '4.10' # SARIF support is provided in Brakeman version 4.10+
|
33
|
+
run: |
|
34
|
+
gem install brakeman --version $BRAKEMAN_VERSION
|
35
|
+
|
36
|
+
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
|
37
|
+
- name: Scan
|
38
|
+
continue-on-error: true
|
39
|
+
run: |
|
40
|
+
brakeman -f sarif -o output.sarif.json .
|
41
|
+
|
42
|
+
# Upload the SARIF file generated in the previous step
|
43
|
+
- name: Upload SARIF
|
44
|
+
uses: github/codeql-action/upload-sarif@v1
|
45
|
+
with:
|
46
|
+
sarif_file: output.sarif.json
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Run tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master, next ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
ruby-version: [2.7, 3.0]
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
|
21
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
22
|
+
uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby-version }}
|
25
|
+
bundler-cache: true
|
26
|
+
|
27
|
+
- name: Install dependencies
|
28
|
+
run: bundle install
|
29
|
+
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rake
|
32
|
+
|
33
|
+
- name: Build gem
|
34
|
+
run: bundle exec rake build
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: Release gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- 'v*'
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
name: Build + Publish
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
|
16
|
+
- name: Set up Ruby 3.0
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: 3.0
|
20
|
+
|
21
|
+
- run: bundle install
|
22
|
+
|
23
|
+
- name: Publish to RubyGems
|
24
|
+
run: |
|
25
|
+
mkdir -p $HOME/.gem
|
26
|
+
touch $HOME/.gem/credentials
|
27
|
+
chmod 0600 $HOME/.gem/credentials
|
28
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
29
|
+
bundle exec rake build
|
30
|
+
gem push pkg/*.gem
|
31
|
+
env:
|
32
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,28 +1,17 @@
|
|
1
1
|
---
|
2
|
+
inherit_from: .rubocop_todo.yml
|
3
|
+
|
2
4
|
AllCops:
|
3
|
-
|
5
|
+
NewCops: enable
|
6
|
+
TargetRubyVersion: 2.7
|
4
7
|
Exclude:
|
5
|
-
- "bin/**/*"
|
6
8
|
- "spec/dummy/bin/**/*"
|
7
9
|
- "tmp/**/*"
|
8
10
|
- "vendor/**/*"
|
9
11
|
|
10
|
-
# not available in older versions of Ruby
|
11
|
-
Layout/IndentHeredoc:
|
12
|
-
Enabled: false
|
13
|
-
|
14
|
-
Style/Documentation:
|
15
|
-
Enabled: false
|
16
|
-
|
17
|
-
Style/ClassAndModuleChildren:
|
18
|
-
EnforcedStyle: nested
|
19
|
-
|
20
|
-
Style/SingleLineBlockParams:
|
21
|
-
Enabled: false
|
22
|
-
|
23
12
|
Metrics/BlockLength:
|
24
13
|
Exclude:
|
25
14
|
- spec/**/*_spec.rb
|
26
15
|
|
27
|
-
|
16
|
+
Layout/LineLength:
|
28
17
|
Max: 120
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2021-10-02 14:42:36 UTC using RuboCop version 1.22.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 5
|
10
|
+
# Configuration parameters: AllowedConstants.
|
11
|
+
Style/Documentation:
|
12
|
+
Exclude:
|
13
|
+
- 'spec/**/*'
|
14
|
+
- 'test/**/*'
|
15
|
+
- 'app/controllers/letter_opener_web/letters_controller.rb'
|
16
|
+
- 'app/models/letter_opener_web/letter.rb'
|
17
|
+
- 'lib/letter_opener_web.rb'
|
18
|
+
- 'lib/letter_opener_web/delivery_method.rb'
|
19
|
+
- 'lib/letter_opener_web/engine.rb'
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,25 @@
|
|
1
|
-
## [
|
1
|
+
## [v2.0.0](https://github.com/fgrehm/letter_opener_web/compare/v1.4.1...v2.0.0)
|
2
|
+
|
3
|
+
- Require Rails >= 5.2, run tests against Rails 6.1 [#113](https://github.com/fgrehm/letter_opener_web/pull/113)
|
4
|
+
- Inline CSS and Javascript, to avoid dependency on asset pipeline [#113](https://github.com/fgrehm/letter_opener_web/pull/113)
|
5
|
+
- Upgrade to Bootstrap 5.1.1 [#113](https://github.com/fgrehm/letter_opener_web/pull/113)
|
6
|
+
- Add rexml gem into dependency for Ruby 3.0 [#106](https://github.com/fgrehm/letter_opener_web/pull/106)
|
7
|
+
- Add routes for Rails API mode [#69](https://github.com/fgrehm/letter_opener_web/pull/69)
|
8
|
+
- Prevent name conflict with `Letter` class [#108](https://github.com/fgrehm/letter_opener_web/pull/108)
|
9
|
+
- Add Rails' built-in CSRF protection [#111](https://github.com/fgrehm/letter_opener_web/pull/111)
|
10
|
+
- Add Rails' CSP nonce to the script tag [#112](https://github.com/fgrehm/letter_opener_web/pull/112)
|
11
|
+
- Update dev dependencies [#113](https://github.com/fgrehm/letter_opener_web/pull/113)
|
12
|
+
- Switched to using GitHub actions as CI for the project [#113](https://github.com/fgrehm/letter_opener_web/pull/113)
|
13
|
+
|
14
|
+
## [1.4.1](https://github.com/fgrehm/letter_opener_web/compare/v1.4.0...v1.4.1) (Oct 5, 2021)
|
15
|
+
|
16
|
+
- Ensure letter is within letters base path [#110](https://github.com/fgrehm/letter_opener_web/pull/110)
|
17
|
+
|
18
|
+
## [1.4.0](https://github.com/fgrehm/letter_opener_web/compare/v1.3.4...v1.4.0) (Jan 29, 2020)
|
19
|
+
|
20
|
+
- Removed the dependency on the asset pipeline. Good news for API-only apps! [#83](https://github.com/fgrehm/letter_opener_web/pull/83)
|
21
|
+
- Avoid `require_dependency` if Zeitwerk is enabled [#98](https://github.com/fgrehm/letter_opener_web/pull/98)
|
22
|
+
- Drop support for old rubies and rails. Ruby 2.5+ is supported and Rails 4 is no longer tested [#100](https://github.com/fgrehm/letter_opener_web/pull/100)
|
2
23
|
|
3
24
|
## [1.3.4](https://github.com/fgrehm/letter_opener_web/compare/v1.3.3...v1.3.4) (Apr 04, 2018)
|
4
25
|
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# letter_opener_web
|
2
2
|
|
3
|
-
|
3
|
+
![Build Status](https://github.com/fgrehm/letter_opener_web/actions/workflows/main.yml/badge.svg)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/letter_opener_web.svg)](http://badge.fury.io/rb/letter_opener_web)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/fgrehm/letter_opener_web.svg)](https://codeclimate.com/github/fgrehm/letter_opener_web)
|
4
6
|
|
5
7
|
Gives [letter_opener](https://github.com/ryanb/letter_opener) an interface for
|
6
8
|
browsing sent emails.
|
@@ -13,7 +15,7 @@ First add the gem to your development environment and run the `bundle` command t
|
|
13
15
|
|
14
16
|
```ruby
|
15
17
|
group :development do
|
16
|
-
gem 'letter_opener_web'
|
18
|
+
gem 'letter_opener_web', '~> 2.0'
|
17
19
|
end
|
18
20
|
```
|
19
21
|
|
@@ -23,9 +25,7 @@ Add to your routes.rb:
|
|
23
25
|
|
24
26
|
```ruby
|
25
27
|
Your::Application.routes.draw do
|
26
|
-
if Rails.env.development?
|
27
|
-
mount LetterOpenerWeb::Engine, at: "/letter_opener"
|
28
|
-
end
|
28
|
+
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
|
29
29
|
end
|
30
30
|
```
|
31
31
|
|
@@ -33,8 +33,9 @@ And make sure you have [`:letter_opener` delivery method](https://github.com/rya
|
|
33
33
|
configured for your app. Then visit `http://localhost:3000/letter_opener` after
|
34
34
|
sending an email and have fun.
|
35
35
|
|
36
|
-
If you are running the app from a [Vagrant](http://vagrantup.com) machine
|
37
|
-
might want to skip `letter_opener`'s `launchy` calls and avoid messages
|
36
|
+
If you are running the app from a [Vagrant](http://vagrantup.com) machine or Docker
|
37
|
+
container, you might want to skip `letter_opener`'s `launchy` calls and avoid messages
|
38
|
+
like these:
|
38
39
|
|
39
40
|
```terminal
|
40
41
|
12:33:42 web.1 | Failure in opening /vagrant/tmp/letter_opener/1358825621_ba83a22/rich.html
|
@@ -43,19 +44,16 @@ environment variable LAUNCHY_DEBUG=true or the '-d' commandline option and file
|
|
43
44
|
https://github.com/copiousfreetime/launchy/issues/new
|
44
45
|
```
|
45
46
|
|
46
|
-
In that case (or if you just want to browse mails using the web interface
|
47
|
-
can set `:letter_opener_web` as
|
48
|
-
`config/environments/development.rb`:
|
47
|
+
In that case (or if you really just want to browse mails using the web interface and
|
48
|
+
don't care about opening emails automatically), you can set `:letter_opener_web` as
|
49
|
+
your delivery method on your `config/environments/development.rb`:
|
49
50
|
|
50
51
|
```ruby
|
51
52
|
config.action_mailer.delivery_method = :letter_opener_web
|
52
|
-
|
53
|
-
# If not everyone on the team is using vagrant
|
54
|
-
config.action_mailer.delivery_method = ENV['USER'] == 'vagrant' ? :letter_opener_web : :letter_opener
|
55
53
|
```
|
56
54
|
|
57
|
-
If you're using `:letter_opener_web` as your delivery method, you can change the location of
|
58
|
-
following to an initializer (or in development.rb):
|
55
|
+
If you're using `:letter_opener_web` as your delivery method, you can change the location of
|
56
|
+
the letters by adding the following to an initializer (or in development.rb):
|
59
57
|
|
60
58
|
```ruby
|
61
59
|
LetterOpenerWeb.configure do |config|
|
@@ -63,13 +61,16 @@ LetterOpenerWeb.configure do |config|
|
|
63
61
|
end
|
64
62
|
```
|
65
63
|
|
66
|
-
## Usage on
|
64
|
+
## Usage on pre-production environments
|
65
|
+
|
66
|
+
Some people use this gem on staging / pre-production environments to avoid having real emails
|
67
|
+
being sent out. To set that up you'll need to:
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
the route for
|
69
|
+
1. Move the gem out of the `development` group in your `Gemfile`
|
70
|
+
2. Set `config.action_mailer.delivery_method` on the appropriate `config/environments/<env>.rb`
|
71
|
+
3. Enable the route for the environments on your `routes.rb`.
|
71
72
|
|
72
|
-
In
|
73
|
+
In other words, your `Gemfile` will have:
|
73
74
|
|
74
75
|
```ruby
|
75
76
|
gem 'letter_opener_web'
|
@@ -79,20 +80,28 @@ And your `routes.rb`:
|
|
79
80
|
|
80
81
|
```ruby
|
81
82
|
Your::Application.routes.draw do
|
82
|
-
|
83
|
+
# If you have a dedicated config/environments/staging.rb
|
84
|
+
mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.staging?
|
85
|
+
|
86
|
+
# If you use RAILS_ENV=production in staging environments, you'll need another
|
87
|
+
# way to disable it in "real production"
|
88
|
+
mount LetterOpenerWeb::Engine, at: "/letter_opener" unless ENV["PRODUCTION_FOR_REAL"]
|
83
89
|
end
|
84
90
|
```
|
85
91
|
|
86
92
|
You might also want to have a look at the sources for the [demo](http://letter-opener-web.herokuapp.com)
|
87
93
|
available at https://github.com/fgrehm/letter_opener_web_demo.
|
88
94
|
|
89
|
-
**NOTICE: Using this gem on Heroku will only work if your app has just one Dyno
|
95
|
+
**NOTICE: Using this gem on Heroku will only work if your app has just one Dyno
|
96
|
+
and does not send emails from background jobs. For updates on this matter please
|
97
|
+
subscribe to [GH-35](https://github.com/fgrehm/letter_opener_web/issues/35)**
|
90
98
|
|
91
99
|
## Acknowledgements
|
92
100
|
|
93
101
|
Special thanks to [@alexrothenberg](https://github.com/alexrothenberg) for some
|
94
|
-
ideas on [this pull request](https://github.com/ryanb/letter_opener/pull/12)
|
95
|
-
|
102
|
+
ideas on [this pull request](https://github.com/ryanb/letter_opener/pull/12) and
|
103
|
+
[@pseudomuto](https://github.com/pseudomuto) for keeping the project alive for a
|
104
|
+
few years.
|
96
105
|
|
97
106
|
## Contributing
|
98
107
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
unless Rails.respond_to?(:autoloaders) && Rails.autoloaders.zeitwerk_enabled?
|
4
|
+
require_dependency 'letter_opener_web/application_controller'
|
5
|
+
end
|
4
6
|
|
5
7
|
module LetterOpenerWeb
|
6
8
|
class LettersController < ApplicationController
|
7
|
-
before_action :check_style, only:
|
9
|
+
before_action :check_style, only: :show
|
8
10
|
before_action :load_letter, only: %i[show attachment destroy]
|
9
11
|
|
10
12
|
def index
|
11
|
-
@letters = Letter.search
|
13
|
+
@letters = LetterOpenerWeb::Letter.search
|
12
14
|
end
|
13
15
|
|
14
16
|
def show
|
@@ -24,17 +26,21 @@ module LetterOpenerWeb
|
|
24
26
|
file = @letter.attachments[filename]
|
25
27
|
|
26
28
|
return render plain: 'Attachment not found!', status: 404 unless file.present?
|
29
|
+
|
27
30
|
send_file(file, filename: filename, disposition: 'inline')
|
28
31
|
end
|
29
32
|
|
30
33
|
def clear
|
31
|
-
Letter.destroy_all
|
34
|
+
LetterOpenerWeb::Letter.destroy_all
|
32
35
|
redirect_to routes.letters_path
|
33
36
|
end
|
34
37
|
|
35
38
|
def destroy
|
36
39
|
@letter.delete
|
37
|
-
|
40
|
+
respond_to do |format|
|
41
|
+
format.html { redirect_to routes.letters_path }
|
42
|
+
format.js { render js: "window.location='#{routes.letters_path}'" }
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
private
|
@@ -44,8 +50,9 @@ module LetterOpenerWeb
|
|
44
50
|
end
|
45
51
|
|
46
52
|
def load_letter
|
47
|
-
@letter = Letter.find(params[:id])
|
48
|
-
|
53
|
+
@letter = LetterOpenerWeb::Letter.find(params[:id])
|
54
|
+
|
55
|
+
head :not_found unless @letter.valid?
|
49
56
|
end
|
50
57
|
|
51
58
|
def routes
|
@@ -33,6 +33,18 @@ module LetterOpenerWeb
|
|
33
33
|
@sent_at = params[:sent_at]
|
34
34
|
end
|
35
35
|
|
36
|
+
def headers
|
37
|
+
html = read_file(:rich) if style_exists?('rich')
|
38
|
+
html ||= read_file(:plain)
|
39
|
+
|
40
|
+
# NOTE: This is ugly, we should look into using nokogiri and making that a
|
41
|
+
# dependency of this gem
|
42
|
+
match_data = html.match(%r{<body>\s*<div[^>]+id="container">\s*<div[^>]+id="message_headers">\s*(<dl>.+</dl>)}m)
|
43
|
+
return remove_attachments_link(match_data[1]).html_safe if match_data && match_data[1].present?
|
44
|
+
|
45
|
+
'UNABLE TO PARSE HEADERS'
|
46
|
+
end
|
47
|
+
|
36
48
|
def plain_text
|
37
49
|
@plain_text ||= adjust_link_targets(read_file(:plain))
|
38
50
|
end
|
@@ -56,17 +68,28 @@ module LetterOpenerWeb
|
|
56
68
|
end
|
57
69
|
|
58
70
|
def delete
|
59
|
-
|
71
|
+
return unless valid?
|
72
|
+
|
73
|
+
FileUtils.rm_rf(base_dir.to_s)
|
60
74
|
end
|
61
75
|
|
62
|
-
def
|
63
|
-
|
76
|
+
def valid?
|
77
|
+
exists? && base_dir_within_letters_location?
|
64
78
|
end
|
65
79
|
|
66
80
|
private
|
67
81
|
|
82
|
+
def remove_attachments_link(headers)
|
83
|
+
xml = REXML::Document.new(headers)
|
84
|
+
if xml.root.elements.size == 10
|
85
|
+
xml.delete_element('//dd[last()]')
|
86
|
+
xml.delete_element('//dt[last()]')
|
87
|
+
end
|
88
|
+
xml.to_s
|
89
|
+
end
|
90
|
+
|
68
91
|
def base_dir
|
69
|
-
|
92
|
+
LetterOpenerWeb.config.letters_location.join(id).cleanpath
|
70
93
|
end
|
71
94
|
|
72
95
|
def read_file(style)
|
@@ -77,8 +100,16 @@ module LetterOpenerWeb
|
|
77
100
|
File.exist?("#{base_dir}/#{style}.html")
|
78
101
|
end
|
79
102
|
|
103
|
+
def exists?
|
104
|
+
File.exist?(base_dir)
|
105
|
+
end
|
106
|
+
|
107
|
+
def base_dir_within_letters_location?
|
108
|
+
base_dir.to_s.start_with?(LetterOpenerWeb.config.letters_location.to_s)
|
109
|
+
end
|
110
|
+
|
80
111
|
def adjust_link_targets(contents)
|
81
|
-
# We cannot feed the whole file to
|
112
|
+
# We cannot feed the whole file to a XML parser as some mails are
|
82
113
|
# "complete" (as in they have the whole <html> structure) and letter_opener
|
83
114
|
# prepends some information about the mail being sent, making REXML
|
84
115
|
# complain about it
|
@@ -86,6 +117,7 @@ module LetterOpenerWeb
|
|
86
117
|
fixed_link = fix_link_html(link)
|
87
118
|
xml = REXML::Document.new(fixed_link).root
|
88
119
|
next if xml.attributes['href'] =~ /(plain|rich).html/
|
120
|
+
|
89
121
|
xml.attributes['target'] = '_blank'
|
90
122
|
xml.add_text('') unless xml.text
|
91
123
|
contents.gsub!(link, xml.to_s)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<%= render "layouts/letter_opener_web/js/jquery" %>
|
2
|
+
<%= render "layouts/letter_opener_web/js/favcount" %>
|
3
|
+
|
4
|
+
<script nonce="<%= content_security_policy_nonce %>">
|
5
|
+
function update_favicon(favicon) {
|
6
|
+
favicon.set($('.letter-opener a').length);
|
7
|
+
}
|
8
|
+
|
9
|
+
jQuery(function($) {
|
10
|
+
var favicon = new Favcount($('link[rel="icon"]').attr('href'));
|
11
|
+
update_favicon(favicon);
|
12
|
+
|
13
|
+
$('.letter-opener').on('click', 'a', function() {
|
14
|
+
var $this = $(this);
|
15
|
+
$('iframe').attr('src', $this.attr('href'));
|
16
|
+
$this.parents('.list-group').find('.active').removeClass('active');
|
17
|
+
$this.parent().addClass('active');
|
18
|
+
});
|
19
|
+
|
20
|
+
$('.refresh').click(function(e) {
|
21
|
+
e.preventDefault();
|
22
|
+
|
23
|
+
var wrapper = $('.letter-opener');
|
24
|
+
wrapper.find('div').text('Loading...');
|
25
|
+
wrapper.load(wrapper.data('letters-path') + ' .letter-opener', function() {
|
26
|
+
$('iframe').attr('src', $('.letter-opener a:first-child()').attr('href'));
|
27
|
+
update_favicon(favicon);
|
28
|
+
});
|
29
|
+
});
|
30
|
+
});
|
31
|
+
</script>
|
@@ -1,3 +1,4 @@
|
|
1
|
+
<script nonce="<%= content_security_policy_nonce %>">
|
1
2
|
/*
|
2
3
|
* favcount.js v1.5.0
|
3
4
|
* http://chrishunt.co/favcount
|
@@ -46,11 +47,10 @@
|
|
46
47
|
|
47
48
|
function drawCanvas(canvas, opacity, font, img, count) {
|
48
49
|
var head = document.getElementsByTagName('head')[0],
|
49
|
-
favicon = document.
|
50
|
+
favicon = document.querySelector('link[rel=icon]'),
|
51
|
+
newFavicon = document.createElement('link'),
|
50
52
|
multiplier, fontSize, context, xOffset, yOffset, border, shadow;
|
51
53
|
|
52
|
-
favicon.rel = 'icon';
|
53
|
-
|
54
54
|
// Scale canvas elements based on favicon size
|
55
55
|
multiplier = img.width / 16;
|
56
56
|
fontSize = multiplier * 11;
|
@@ -89,14 +89,16 @@
|
|
89
89
|
);
|
90
90
|
|
91
91
|
// Replace favicon with new favicon
|
92
|
-
|
93
|
-
|
94
|
-
head.
|
92
|
+
newFavicon.rel = 'icon';
|
93
|
+
newFavicon.href = canvas.toDataURL('image/png');
|
94
|
+
if (favicon) { head.removeChild(favicon); }
|
95
|
+
head.appendChild(newFavicon);
|
95
96
|
}
|
96
97
|
|
97
98
|
this.Favcount = Favcount;
|
98
99
|
}).call(this);
|
99
100
|
|
100
101
|
(function(){
|
101
|
-
Favcount.VERSION = '1.5.
|
102
|
+
Favcount.VERSION = '1.5.1';
|
102
103
|
}).call(this);
|
104
|
+
</script>
|