Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add papertrail gem #587

Open
wants to merge 94 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
e98d484
Add papertrail gem
Apr 1, 2022
8db48ad
Replaced papertrail with paper_trail gem
Apr 1, 2022
9317dcd
Sort gems alphabetically
Apr 1, 2022
5cd488a
Add papertrail to model and migration
Apr 1, 2022
e9d37a3
Add ignore to papertrail
Apr 1, 2022
045b832
Fixed rubocop error
Apr 1, 2022
7983e14
Changed show function to touch
Apr 1, 2022
e20bd83
Add spec for touch
Apr 1, 2022
7f50548
Add specs for papertrail
Apr 1, 2022
8775a62
Change rubocop rule to allow touch method
Apr 3, 2022
5c9f03a
add route to logs and first draft of logs_controller
RamonaChristen Apr 3, 2022
96a63c0
Fix rubocop and spec
Apr 3, 2022
610a59b
Add log policy
Apr 3, 2022
f33f40f
Change show to index
Apr 5, 2022
2473cb2
Refactor index? method
Apr 5, 2022
acfc099
Re-add show restriction
Apr 5, 2022
d73cae2
add controller spec
RamonaChristen Apr 5, 2022
3744505
Fixed encryptable controller spec
Apr 5, 2022
c135350
extend controller spec, specs fail because controller doesn't work as…
RamonaChristen Apr 5, 2022
f9efbb4
add logs serializer and fix controller
RamonaChristen Apr 6, 2022
f265b72
fix rubocop error
RamonaChristen Apr 6, 2022
ad72818
Add logs component
Apr 6, 2022
590be35
Merge branch '564-LOG_encryptable_read_access' of https://github.com/…
Apr 6, 2022
cf7c8b7
restrict access for api users, add specs
RamonaChristen Apr 7, 2022
d2a96b3
Change policy to check for team membership
Apr 7, 2022
d744841
Add tabs for logs
Apr 7, 2022
9ae217a
Removed tautologous expectation+
Apr 7, 2022
6be41fe
Remove pry
Apr 7, 2022
739a20f
Add stub components for table and table row
Apr 7, 2022
5a064b1
add logs model to frontend
RamonaChristen Apr 7, 2022
fbe53cf
Merge remote-tracking branch 'origin/564-LOG_encryptable_read_access'…
RamonaChristen Apr 7, 2022
ab7e6cb
Fix log model not found error
Apr 7, 2022
00dd3e1
implement table-row.hbs, work on getting logs to frontend
RamonaChristen Apr 8, 2022
477125a
Add adapter and fix component
Apr 8, 2022
5b61e29
Change log adapter name
Apr 8, 2022
8508e8a
Fix backend to frontend serialization
Robin481 Apr 8, 2022
1b63d3a
Fix table and add update to papertrail
Apr 8, 2022
04d1424
fix logs table, make prettier
RamonaChristen Apr 8, 2022
cc89947
log username instead of userid
RamonaChristen Apr 11, 2022
1017f8c
Merge branch 'master' of https://github.com/puzzle/cryptopus into 564…
Apr 12, 2022
133b5a5
log view access
RamonaChristen Apr 12, 2022
cb57571
add translations for log entry event
RamonaChristen Apr 12, 2022
6ac6a91
Merge branch '564-LOG_encryptable_read_access' of https://github.com/…
Apr 13, 2022
d537036
reload logs when switching tabs, fix linting errors
RamonaChristen Apr 23, 2022
b88a00e
fix rubocop errors
RamonaChristen Apr 23, 2022
e98beef
Merge branch 'master' of https://github.com/puzzle/cryptopus into 564…
Apr 25, 2022
1417b36
Rebase with master
Apr 25, 2022
5c1ac4b
Add encryptable specs
Apr 26, 2022
df3a9c9
add username and userid to log
RamonaChristen Apr 27, 2022
5aec2e0
Merge remote-tracking branch 'origin/564-LOG_encryptable_read_access'…
RamonaChristen Apr 27, 2022
b991304
correct spelling of model attribute
RamonaChristen Apr 28, 2022
0de70d1
add more frontend tests
RamonaChristen Apr 28, 2022
a1aabdd
improve frontend tests and add id to tabs
RamonaChristen Apr 28, 2022
51c8933
fix serializer and backend specs
RamonaChristen Apr 28, 2022
23fd312
use correct date format in paper_trail table
RamonaChristen Apr 29, 2022
f79ad57
user save_with_version on encryptable show
RamonaChristen Apr 29, 2022
c06353f
fix mistake
RamonaChristen Apr 29, 2022
6d84e7f
Add destroy on delete to encryptable
Apr 29, 2022
b355ea1
merge master
RamonaChristen May 1, 2022
e055936
log all update actions, fix problem with sorting logs on update
RamonaChristen May 1, 2022
5b352a9
limit query to only get 20 logs
RamonaChristen May 1, 2022
37a0ba0
add load more button to always load 10 logs at a time
RamonaChristen May 1, 2022
3286250
Change find_by to find
May 2, 2022
143eb24
Format code
May 2, 2022
791a15e
Fix rubocop issue
May 3, 2022
25937f6
Merge branch 'master' of https://github.com/puzzle/cryptopus into 564…
May 3, 2022
93aebfb
Adjust to PR review
May 4, 2022
30b9714
add system spec for view log
RamonaChristen May 4, 2022
77d08a7
add test for edit log (doesnt pass yet)
RamonaChristen May 5, 2022
d478e36
fix bug where view access is logged as update
RamonaChristen May 5, 2022
c56df1a
Replace alice with bob to fix spec
May 6, 2022
679ea3f
Restructure specs
May 6, 2022
17bb5d9
adjust frontend log model to backend model
RamonaChristen May 7, 2022
f439030
load logs directly from Versions table, optimize viewed access log
RamonaChristen May 9, 2022
b737cbc
Change parent class of log policy
May 9, 2022
58f413c
Merge branch '564-LOG_encryptable_read_access' of https://github.com/…
May 9, 2022
f19dc36
Move papertrail spec to encryptable controller spec
May 9, 2022
8402150
change header names in logs table, add space between tabs and log table
RamonaChristen May 9, 2022
c2096e0
Add encryptables controller show test
May 9, 2022
f21bbbf
Merge branch '564-LOG_encryptable_read_access' of https://github.com/…
May 9, 2022
94f42b4
Remove trailing whitespaces
May 9, 2022
b4a0fa5
query for username in log query to aviod n+1
RamonaChristen May 13, 2022
8aa4ddc
add version model
RamonaChristen May 17, 2022
93dc302
use includes to get username to logs, refactor from paper-trail-versi…
RamonaChristen May 17, 2022
41e728c
Merge branch 'master' into 564-LOG_encryptable_read_access
RamonaChristen May 18, 2022
67661b0
Fix frontend test after merge conflict
RamonaChristen May 18, 2022
1217ef4
improve load more function
RamonaChristen May 18, 2022
ee2bc92
extend versions destroy spec
RamonaChristen May 24, 2022
8c7782a
572 log recent credentials on dashboard (#608)
renato-oester May 24, 2022
65b5d3d
Merge remote-tracking branch 'origin/master' into 564-LOG_encryptable…
RamonaChristen May 24, 2022
7923d78
Merge branch 'master' into 564-LOG_encryptable_read_access
RamonaChristen Jun 3, 2022
0b45274
change translations in line with changes on main
RamonaChristen Jun 3, 2022
f3a4e62
Merge branch 'master' into 564-LOG_encryptable_read_access
RamonaChristen Jun 10, 2022
1ad9130
Merge branch 'master' into 564-LOG_encryptable_read_access
RamonaChristen Jun 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ Naming/FileName:
Rails/EnumHash:
Enabled: false

Rails/SkipsModelValidations:
Robin481 marked this conversation as resolved.
Show resolved Hide resolved
AllowedMethods: ["touch"]

# Keep for now, easier with superclass definitions
Style/ClassAndModuleChildren:
Enabled: false
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ gem 'faker'
gem 'haml'
gem 'maxmind-db'
gem 'openid_connect'
gem 'paper_trail', '~> 12.3'
gem 'password_strength'
gem 'pg'
gem 'pundit'
Expand Down
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ GEM
validate_email
validate_url
webfinger (>= 1.0.1)
paper_trail (12.3.0)
activerecord (>= 5.2)
request_store (~> 1.1)
parallel (1.21.0)
parser (3.1.1.0)
ast (~> 2.4.1)
Expand Down Expand Up @@ -263,6 +266,8 @@ GEM
rainbow (3.1.1)
rake (13.0.6)
regexp_parser (2.2.1)
request_store (1.5.1)
rack (>= 1.4)
rexml (3.2.5)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
Expand Down Expand Up @@ -384,6 +389,7 @@ DEPENDENCIES
mysql2
net-ldap
openid_connect
paper_trail (~> 12.3)
password_strength
pg
pry
Expand Down
20 changes: 20 additions & 0 deletions app/controllers/api/encryptables_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class Api::EncryptablesController < ApiController

self.permitted_attrs = [:name, :description, :tag]

before_action :set_paper_trail_whodunnit

helper_method :team

# GET /api/encryptables
Expand All @@ -19,6 +21,7 @@ def index
def show
authorize entry
entry.decrypt(decrypted_team_password(team))
log_read_access
render_entry
end

Expand Down Expand Up @@ -69,6 +72,16 @@ def model_class
end
# rubocop:enable Metrics/MethodLength

def fetch_entries
if encryptable_file?
super
elsif tag_param.present?
user_encryptables.find_by(tag: tag_param)
else
Encryptables::FilteredList.new(current_user, params).fetch_entries
end
end

def build_entry
return build_encryptable_file if encryptable_file?

Expand Down Expand Up @@ -128,4 +141,11 @@ def permitted_attrs
[]
end
end

def log_read_access
v = encryptable.paper_trail.save_with_version
v.event = :viewed
v.created_at = DateTime.now
v.save!
end
end
28 changes: 28 additions & 0 deletions app/controllers/api/logs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

class Api::LogsController < ApiController

def index(options = {})
authorize(team, :index?, policy_class: LogPolicy)
render({ json: fetch_entries,
each_serializer: @model_serializer ||= LogsSerializer }
.merge(render_options)
.merge(options.fetch(:render_options, {})))
end

def fetch_entries
Robin481 marked this conversation as resolved.
Show resolved Hide resolved
PaperTrail.serializer = JSON
limit = params[:load] || 20
offset = params[:offset] || 0
Version
.includes(:user)
.where(item_id: params[:encryptable_id])
.order(created_at: :desc)
.offset(offset)
.limit(limit)
end

def team
@team ||= Encryptable.find(params[:encryptable_id]).folder.team
end
end
10 changes: 10 additions & 0 deletions app/models/encryptable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@

class Encryptable < ApplicationRecord

has_paper_trail on: [:touch, :update], ignore: [:tag, :type], versions: {
class_name: 'Version'
}

before_destroy :destroy_versions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that necessary? (not necessarily criticizing just trying to understand)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Robin481 The papertrail versions are not deleted from the db by default, if the encryptable they correspond to is deleted. We discussed if it would make sense to keep the old versions because the api user may still want to know what happened to an encryptable that doesn't exist anymore. However, keeping the old encryptables may pollute the db quite heavily. What do you think?

Copy link
Member

@Robin481 Robin481 May 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes deleting them makes sense.
However, dependent: :destroy should already do that, that is why I am asking. 😁
(there was more text here that I deleted because I got confused by which branch i was on 😂 )

Copy link
Contributor Author

@Drinion Drinion May 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Robin481 Yes, dependent: :destroy should do that but it doesn't. There might be something wrong with the way we used active record with regards to paper_trail. I look into it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on this front?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to be a bug within the papertrail gem, dependent: :destroy does not work here but I extended the encryptable_spec to make sure that our :destroy versions method deletes everything it need to and nothing more so I think we should leave it like this


serialize :encrypted_data, ::EncryptedData

attr_readonly :type
Expand Down Expand Up @@ -71,4 +77,8 @@ def decrypt_attr(attr, team_password)
instance_variable_set("@cleartext_#{attr}", cleartext_value)
end

def destroy_versions
versions.destroy_all
end

end
2 changes: 2 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class User < ApplicationRecord
validates :username, uniqueness: :username
validates :username, presence: true

has_many :versions, foreign_key: :whodunnit, dependent: :destroy, class_name: 'Version'

def update_password(old, new)
return unless auth_db?

Expand Down
6 changes: 6 additions & 0 deletions app/models/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Version < PaperTrail::Version
belongs_to :user, class_name: 'User', foreign_key: :whodunnit
belongs_to :encryptable, class_name: 'Encryptable', foreign_key: :item_id
end
11 changes: 11 additions & 0 deletions app/policies/log_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class LogPolicy < TeamPolicy
def index?
team_member?
end

def show?
@team.teammember?(@user.id) && [email protected]_a?(User::Api)
end
end
49 changes: 49 additions & 0 deletions app/presenters/encryptables/filtered_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

module ::Encryptables
class FilteredList < ::FilteredList

def fetch_entries
filtered_encryptables = encryptables

filtered_encryptables = filter_by_recent if recent?
filtered_encryptables = filter_by_query(filtered_encryptables) if query


filtered_encryptables
end

private

def query
@params[:q]&.strip&.downcase
end

def recent?
true?(@params[:recent])
end

def encryptables
@current_user.encryptables
end

def filter_by_query(encryptables)
encryptables.where(
'lower(encryptables.description) LIKE :query
OR lower(encryptables.name) LIKE :query',
query: "%#{query}%"
)
end

def filter_by_recent
Version
.includes(:encryptable, encryptable: [:folder])
.where(whodunnit: @current_user)
.order(created_at: :desc)
.group(:item_id, :item_type)
.select(:item_id, :item_type)
.limit(5)
.map(&:encryptable)
end
end
end
4 changes: 4 additions & 0 deletions app/presenters/filtered_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ def fetch_entries
def list_param(key)
@params[key].to_a.map(&:to_i)
end

def true?(value)
%w[1 yes true].include?(value.to_s.downcase)
end
end
19 changes: 19 additions & 0 deletions app/serializers/logs_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class LogsSerializer < ApplicationSerializer
attributes :id, :item_type, :event, :user_id, :username, :created_at

belongs_to :encryptable
RamonaChristen marked this conversation as resolved.
Show resolved Hide resolved

def user_id
object.whodunnit
end

def encryptable
object.item
end

def username
object.user.username
end
end
4 changes: 3 additions & 1 deletion config/routes/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
end
end

resources :encryptables, except: [:new, :edit]
resources :encryptables, except: [:new, :edit] do
resources :logs, only: [:index]
end

resources :api_users, except: [:new, :edit] do
member do
Expand Down
38 changes: 38 additions & 0 deletions db/migrate/20220401130939_create_versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This migration creates the `versions` table, the only schema PT requires.
# All other migrations PT provides are optional.
class CreateVersions < ActiveRecord::Migration[7.0]

# The largest text column available in all supported RDBMS is
# 1024^3 - 1 bytes, roughly one gibibyte. We specify a size
# so that MySQL will use `longtext` instead of `text`. Otherwise,
# when serializing very large objects, `text` might not be big enough.
TEXT_BYTES = 1_073_741_823

def change
create_table :versions do |t|
t.string :item_type, null: false
t.bigint :item_id, null: false
t.string :event, null: false
t.string :whodunnit
t.text :object, limit: TEXT_BYTES

# Known issue in MySQL: fractional second precision
# -------------------------------------------------
#
# MySQL timestamp columns do not support fractional seconds unless
# defined with "fractional seconds precision". MySQL users should manually
# add fractional seconds precision to this migration, specifically, to
# the `created_at` column.
# (https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html)
#
# MySQL users should also upgrade to at least rails 4.2, which is the first
# version of ActiveRecord with support for fractional seconds in MySQL.
# (https://github.com/rails/rails/pull/14359)
#
# MySQL users should use the following line for `created_at`
t.datetime :created_at, limit: 6
#t.datetime :created_at
end
add_index :versions, %i(item_type item_id)
end
end
12 changes: 11 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_03_29_122335) do
ActiveRecord::Schema[7.0].define(version: 2022_04_01_130939) do
create_table "encryptables", force: :cascade do |t|
t.string "name", limit: 255, default: "", null: false
t.integer "folder_id"
Expand Down Expand Up @@ -92,4 +92,14 @@
t.index ["default_ccli_user_id"], name: "index_users_on_default_ccli_user_id"
end

create_table "versions", force: :cascade do |t|
t.string "item_type", null: false
t.bigint "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object", limit: 1073741823
t.datetime "created_at"
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end

end
19 changes: 19 additions & 0 deletions frontend/app/adapters/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ApplicationAdapter from "./application";

export default ApplicationAdapter.extend({
namespace: "api/encryptables",

pathForType() {
return "logs";
},

urlForQuery(query, modelName) {
if (query.encryptableId) {
let url = `/${this.namespace}/${query.encryptableId}/logs`;

delete query.encryptableId;
return url;
}
return super.urlForQuery(query, modelName);
}
});
Loading