paper_trail_viewer 1.0.0

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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +43 -0
  3. data/.gitignore +41 -0
  4. data/Appraisals +13 -0
  5. data/CHANGELOG.md +9 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +23 -0
  8. data/README.md +53 -0
  9. data/Rakefile +45 -0
  10. data/app/controllers/paper_trail_viewer/js_controller.rb +14 -0
  11. data/app/controllers/paper_trail_viewer/versions_controller.rb +119 -0
  12. data/app/controllers/paper_trail_viewer/viewer_controller.rb +4 -0
  13. data/app/views/paper_trail_viewer/viewer/index.html.erb +5 -0
  14. data/bin/setup +8 -0
  15. data/config/routes.rb +5 -0
  16. data/gemfiles/rails_6.0_paper_trail_11.1.gemfile +10 -0
  17. data/gemfiles/rails_6.0_paper_trail_12.2.gemfile +10 -0
  18. data/gemfiles/rails_7.0_paper_trail_12.2.gemfile +10 -0
  19. data/javascript/compiled.js +2 -0
  20. data/javascript/src/app.tsx +100 -0
  21. data/javascript/src/components/change_diff.tsx +57 -0
  22. data/javascript/src/components/config_modal.tsx +22 -0
  23. data/javascript/src/components/controls.tsx +62 -0
  24. data/javascript/src/components/full_object_modal.tsx +21 -0
  25. data/javascript/src/components/index.ts +3 -0
  26. data/javascript/src/components/modal.tsx +34 -0
  27. data/javascript/src/components/pagination.tsx +53 -0
  28. data/javascript/src/components/versions_list.tsx +142 -0
  29. data/javascript/src/index.ts +1 -0
  30. data/javascript/src/types.ts +42 -0
  31. data/lib/paper_trail_viewer/data_source/active_record.rb +30 -0
  32. data/lib/paper_trail_viewer/data_source/bigquery.rb +45 -0
  33. data/lib/paper_trail_viewer/engine.rb +5 -0
  34. data/lib/paper_trail_viewer/version.rb +3 -0
  35. data/lib/paper_trail_viewer.rb +11 -0
  36. data/package.json +43 -0
  37. data/paper_trail_viewer.gemspec +34 -0
  38. data/spec/app_template.rb +19 -0
  39. data/spec/rails_helper.rb +18 -0
  40. data/spec/support/factories.rb +13 -0
  41. data/spec/system/paper_trail_viewer_spec.rb +114 -0
  42. data/tsconfig.json +13 -0
  43. data/webpack.config.js +26 -0
  44. metadata +251 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 06cbe395c995ac810d7164e0efcc15786a545fd5abe4277a6c2e800ed2cb0ef4
4
+ data.tar.gz: 991c4f1ed961a5d8a5c5967d3b14c78534cdb549d6d7a235e3e38de634797e14
5
+ SHA512:
6
+ metadata.gz: af134d7971dff9b4d2344c534aa47f61e4bcd52fa06bcba99e7336db544a50aa0e0ac262db3e03b44830a2df7cf517e9aa9c44e9ce2912c37c0342bf18eaf29b
7
+ data.tar.gz: 8508f49cf1d1267b793f20917ec7f52363ce186898f6d8c36827e50619387bff0eecb3ee2f5a9bfe9c9d47c5974cc03cef2edd32958e6a4d082da91b16467f11
@@ -0,0 +1,43 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby:
13
+ - 2.7
14
+ - 3.0
15
+ gemfile:
16
+ - gemfiles/rails_6.0_paper_trail_11.1.gemfile
17
+ - gemfiles/rails_6.0_paper_trail_12.2.gemfile
18
+ - gemfiles/rails_7.0_paper_trail_12.2.gemfile
19
+
20
+ env:
21
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
22
+
23
+ steps:
24
+ - uses: actions/checkout@v2
25
+ - uses: actions/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{ matrix.ruby }}
28
+ - uses: actions/cache@v1
29
+ with:
30
+ path: vendor/bundle
31
+ key: ${{ runner.os }}-${{ matrix.ruby}}-gems-${{ hashFiles('**/paper_trail_viewer.gemspec') }}
32
+ restore-keys: |
33
+ ${{ runner.os }}-${{ matrix.ruby }}-gems-
34
+ - uses: actions/setup-node@v2
35
+ with:
36
+ node-version: '16'
37
+ # - uses: nanasess/setup-chromedriver@v1.0.1
38
+ - name: Install dependencies
39
+ run: |
40
+ bundle install --jobs 4 --retry 3
41
+ npm install
42
+ - name: Build
43
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,41 @@
1
+ *.a
2
+ *.bundle
3
+ *.gem
4
+ *.gemfile.lock
5
+ *.iml
6
+ *.o
7
+ *.so
8
+ *.stTheme.cache
9
+ *.sublime-project
10
+ *.sublime-workspace
11
+ *.swp
12
+ *.tmPreferences.cache
13
+ *.tmlanguage.cache
14
+ *~
15
+ .DS_Store
16
+ .byebug_history
17
+ .idea/
18
+ .rspec_status
19
+ .ruby-gemset
20
+ .ruby-version
21
+ .tags
22
+ .tags1
23
+ .tool-versions
24
+ .vscode
25
+ /.bundle/
26
+ /.yardoc
27
+ /_yardoc/
28
+ /coverage/
29
+ /doc/
30
+ /javascript/compiled*
31
+ /node_modules
32
+ /pkg/
33
+ /spec/reports/
34
+ /tmp/
35
+ Gemfile.lock
36
+ bbin/
37
+ binstubs/*
38
+ bundler_stubs/*/.yardoc
39
+ mkmf.log
40
+ package-lock.json
41
+ spec/dummy
data/Appraisals ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ '6.0' => %w[11.1 12.2],
3
+ '7.0' => %w[12.2],
4
+ }.each do |rails_version, paper_trail_versions|
5
+ paper_trail_versions.each do |paper_trail_version|
6
+ appraise "rails-#{rails_version}-paper_trail-#{paper_trail_version}" do
7
+ gem 'rails', "~> #{rails_version}"
8
+ gem 'sqlite3', '~> 1.4'
9
+ gem 'paper_trail', "~> #{paper_trail_version}"
10
+ gem 'kaminari'
11
+ end
12
+ end
13
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [1.0.0] - 2022-03-26
8
+
9
+ Initial release.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in paper_trail_viewer.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright for portions of paper_trail_viewer are held by Igal Koshevoy, 2011,
2
+ as part of project paper_trail_manager.
3
+
4
+ All other copyright for paper_trail_viewer is held by Janosch Müller, 2022.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ [![Gem Version](https://badge.fury.io/rb/paper_trail_viewer.svg)](http://badge.fury.io/rb/paper_trail_viewer)
2
+ [![Build Status](https://github.com/jaynetics/paper_trail_viewer/workflows/tests/badge.svg)](https://github.com/jaynetics/paper_trail_viewer/actions)
3
+
4
+ # PaperTrailViewer
5
+
6
+ Browse changes to records when using Ruby on Rails and the [`paper_trail` gem](https://github.com/paper-trail-gem/paper_trail).
7
+
8
+ ## Installation
9
+
10
+ Add `paper_trail_viewer` to your bundle and add the following line to your `config/routes.rb`:
11
+
12
+ mount PaperTrailViewer::Engine => '/changes'
13
+
14
+ You can pick any path. Restart the server and go to the chosen path to view your versions.
15
+
16
+ To limit access to this view, do something like:
17
+
18
+ authenticate :user, ->*{ |u| u.superadmin? } do
19
+ mount PaperTrailViewer::Engine => '/changes'
20
+ end
21
+
22
+ ### Configuration
23
+
24
+ Put configuration in `config/initializers/paper_trail_viewer.rb`.
25
+
26
+ E.g. for linking (or not) to the whodunnit user with a custom path helper:
27
+
28
+ PaperTrailViewer.user_path_method = :admin_path # default is :user_path
29
+ PaperTrailViewer.user_path_method = nil # don't link to the user
30
+
31
+ ## Development
32
+
33
+ ### Setup
34
+
35
+ * Clone the repository
36
+ * Go into the directory
37
+ * Run `bin/setup` to install Ruby and JS dependencies
38
+
39
+ ### Running tests
40
+
41
+ * This repo uses the [Appraisal](https://github.com/thoughtbot/appraisal) gem
42
+ * Run `appraisal generate`
43
+ * Run `appraisal install`
44
+ * Run `appraisal rake generate_spec_app`
45
+ * Run `appraisal rake`
46
+
47
+ ## License
48
+
49
+ This program is provided under an MIT open source license, read the [LICENSE.txt](https://github.com/jaynetics/paper_trail_viewer/blob/master/LICENSE.txt) file for details.
50
+
51
+ ## To Note:
52
+
53
+ This project started as a fork of [PaperTrailManager](https://github.com/fusion94/paper_trail_manager), which was originally developed by [Igal Koshevoy](https://github.com/igal), [Reid Beels](https://github.com/reidab), and [Micah Geisel](https://github.com/botandrose).
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rake'
2
+ require 'bundler/gem_tasks'
3
+ require 'rubygems/package_task'
4
+ require 'rspec/core/rake_task'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ RSpec::Core::RakeTask.new
9
+ task default: [:compile_js, :generate_spec_app, :spec]
10
+
11
+ task :compile_js do
12
+ `npm run compile`
13
+ end
14
+
15
+ task :generate_spec_app do
16
+ sh 'rm -rf spec/dummy'
17
+ sh *%w[
18
+ rails new spec/dummy
19
+ --template=spec/app_template.rb
20
+ --skip-action-cable
21
+ --skip-action-mailbox
22
+ --skip-action-mailer
23
+ --skip-action-text
24
+ --skip-active-job
25
+ --skip-active-storage
26
+ --skip-asset-pipeline
27
+ --skip-bootsnap
28
+ --skip-bundle
29
+ --skip-git
30
+ --skip-hotwire
31
+ --skip-javascript
32
+ --skip-jbuilder
33
+ --skip-keeps
34
+ --skip-listen
35
+ --skip-spring
36
+ --skip-sprockets
37
+ --skip-system-test
38
+ --skip-test
39
+ --skip-turbolinks
40
+ --skip-webpack
41
+ ]
42
+ end
43
+
44
+ # ensure fresh js is compiled when packaging the gem
45
+ task build: [:compile_js]
@@ -0,0 +1,14 @@
1
+ # This returns the pre-compiled JS for the viewer component.
2
+ # Yes, that is a hacky way to make the gem work without
3
+ # forcing users to install and integrate an npm package.
4
+ class PaperTrailViewer::JsController < ActionController::Base
5
+ protect_from_forgery unless: -> { request.format.js? }
6
+
7
+ def show
8
+ send_file js_file, type: 'text/javascript', disposition: 'inline'
9
+ end
10
+
11
+ def js_file
12
+ File.join(__dir__, '..', '..', '..', 'javascript', 'compiled.js')
13
+ end
14
+ end
@@ -0,0 +1,119 @@
1
+ class PaperTrailViewer::VersionsController < ActionController::Base
2
+ # Return the queried versions as JSON.
3
+ def index
4
+ query = sanitized_params
5
+ versions = PaperTrailViewer.data_source.call(**query)
6
+ versions_as_json = versions.map { |v| version_as_json(v) }
7
+
8
+ render json: {
9
+ hasNextPage: !versions.last_page? && versions_as_json.any?,
10
+ query: query,
11
+ versions: versions_as_json,
12
+ }
13
+ end
14
+
15
+ # Rollback a change
16
+ def update
17
+ unless version = PaperTrail::Version.find_by(id: params[:id])
18
+ flash[:error] = 'No such version.'
19
+ return redirect_to(root_url)
20
+ end
21
+
22
+ result =
23
+ if version.event == 'create'
24
+ version.item_type.constantize.find(version.item_id).destroy
25
+ else
26
+ version.reify.save
27
+ end
28
+
29
+ if result
30
+ if version.event == 'create'
31
+ flash[:notice] = 'Rolled back newly-created record by destroying it.'
32
+ redirect_to root_url
33
+ else
34
+ flash[:notice] = 'Rolled back changes to this record.'
35
+ redirect_to change_item_url(version)
36
+ end
37
+ else
38
+ flash[:error] = "Couldn't rollback. Sorry."
39
+ redirect_to root_url
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def sanitized_params
46
+ {
47
+ event: params[:event].presence_in(%w[create update destroy]),
48
+ filter: (params[:filter].presence if params[:filter] != '%%'),
49
+ item_id: params[:item_id].presence,
50
+ item_type: params[:item_type].presence,
51
+ page: (page = params[:page].to_i) > 0 ? page : 1,
52
+ per_page: (per = params[:per_page].to_i).clamp(1, 1000),
53
+ }
54
+ end
55
+
56
+ def version_as_json(version)
57
+ {
58
+ **version.attributes.slice(*%w[id whodunnit event created_at]),
59
+ changeset: changeset_for(version),
60
+ object: load_object(version),
61
+ item_id: version.item_id.to_s,
62
+ item_type: version.item_type,
63
+ item_url: change_item_url(version),
64
+ user_url: user_url(version),
65
+ }
66
+ end
67
+
68
+ def changeset_for(version)
69
+ case version.event
70
+ when 'create', 'update'
71
+ version.changeset || {}
72
+ when 'destroy'
73
+ record = version.reify rescue nil
74
+ return {} unless record
75
+
76
+ record.attributes.each_with_object({}) do |changes, (k, v)|
77
+ changes[k] = [v, nil] unless v.nil?
78
+ end
79
+ else
80
+ raise ArgumentError, "Unknown event: #{version.event}"
81
+ end
82
+ end
83
+
84
+ # Return the URL for the item represented by the +version+,
85
+ # e.g. a Company record instance referenced by a version.
86
+ def change_item_url(version)
87
+ version_type = version.item_type.underscore.split('/').last
88
+ main_app.try("#{version_type}_url", version.item_id)
89
+ end
90
+
91
+ def user_url(version)
92
+ (path_method = PaperTrailViewer.user_path_method).present? &&
93
+ (id = version.whodunnit).present? &&
94
+ !id.start_with?('#') &&
95
+ main_app.try(path_method, id) ||
96
+ nil
97
+ end
98
+
99
+ def load_object(version)
100
+ obj = version.object
101
+ if obj.is_a?(String)
102
+ PaperTrail.serializer.load(obj)
103
+ elsif obj.is_a?(Hash)
104
+ OpenStruct.new(obj)
105
+ else
106
+ obj
107
+ end
108
+ end
109
+ end
110
+
111
+ # backport deserialization fix for recent rubies
112
+ # https://github.com/paper-trail-gem/paper_trail/pull/1338
113
+ if PaperTrail::VERSION.to_s < '12.2.0'
114
+ module PaperTrail::Serializers::YAML
115
+ def load(string)
116
+ ::YAML.respond_to?(:unsafe_load) ? ::YAML.unsafe_load(string) : ::YAML.load(string)
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,4 @@
1
+ class PaperTrailViewer::ViewerController < ActionController::Base
2
+ def index
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ <link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>
2
+
3
+ <script src='<%= "#{js_url}?v=#{PaperTrailViewer::VERSION}" %>' type='text/javascript'></script>
4
+
5
+ <div id='mount-paper-trail-viewer'/>
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+ npm install
8
+ npm run compile
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ PaperTrailViewer::Engine.routes.draw do
2
+ root to: 'viewer#index'
3
+ resource :js, only: :show, defaults: { format: :js }
4
+ resources :versions, only: %i[index update]
5
+ end
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.0"
6
+ gem "sqlite3", "~> 1.4"
7
+ gem "paper_trail", "~> 11.1"
8
+ gem "kaminari"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.0"
6
+ gem "sqlite3", "~> 1.4"
7
+ gem "paper_trail", "~> 12.2"
8
+ gem "kaminari"
9
+
10
+ gemspec :path => "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.0"
6
+ gem "sqlite3", "~> 1.4"
7
+ gem "paper_trail", "~> 12.2"
8
+ gem "kaminari"
9
+
10
+ gemspec :path => "../"