paper_trail_viewer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 => "../"