loggable_activity 0.2.1 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +29 -42
- data/.vscode/commands.json +2 -2
- data/.vscode/terminals.json +8 -8
- data/CHANGELOG.md +9 -0
- data/CHEAT_SHEET.md +31 -0
- data/MIT-LICENSE +21 -0
- data/README.md +1 -1
- data/Rakefile +6 -4
- data/app/assets/config/loggable_activity_manifest.js +2 -0
- data/app/assets/javascripts/loggable_activity/application.js +1 -0
- data/app/assets/stylesheets/loggable_activity/activities.scss +25 -0
- data/app/assets/stylesheets/loggable_activity/application.scss +16 -0
- data/app/controllers/concerns/.keep +0 -0
- data/app/controllers/loggable_activity/activities_controller.rb +12 -0
- data/app/controllers/loggable_activity/application_controller.rb +6 -0
- data/app/helpers/loggable_activity/activities_helper.rb +17 -0
- data/app/helpers/loggable_activity/application_helper.rb +6 -0
- data/app/jobs/loggable_activity/application_job.rb +6 -0
- data/app/mailers/loggable_activity/application_mailer.rb +8 -0
- data/app/models/loggable_activity/application_record.rb +7 -0
- data/app/views/kaminari/pico/_first_page.html.erb +13 -0
- data/app/views/kaminari/pico/_gap.html.erb +8 -0
- data/app/views/kaminari/pico/_last_page.html.erb +12 -0
- data/app/views/kaminari/pico/_next_page.html.erb +13 -0
- data/app/views/kaminari/pico/_page.html.erb +14 -0
- data/app/views/kaminari/pico/_paginator.html.erb +27 -0
- data/app/views/kaminari/pico/_prev_page.html.erb +14 -0
- data/app/views/layouts/loggable_activity/application.html.slim +20 -0
- data/app/views/loggable_activity/activities/_activities.html.slim +28 -0
- data/app/views/loggable_activity/activities/index.html.erb +6 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_first_page.html.erb +13 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_gap.html.erb +8 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_last_page.html.erb +13 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_next_page.html.erb +13 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_page.html.erb +14 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_paginator.html.erb +27 -0
- data/app/views/loggable_activity/bootstrap/kaminari/_prev_page.html.erb +13 -0
- data/config/initializers/kaminari_config.rb +14 -0
- data/config/routes.rb +7 -0
- data/{lib/generators/loggable_activity/templates/create_loggable_activities.rb → db/migrate/20240702092648_create_loggable_activity_tables.rb} +18 -10
- data/git-org/HEAD +1 -0
- data/git-org/config +7 -0
- data/git-org/description +1 -0
- data/git-org/hooks/applypatch-msg.sample +15 -0
- data/git-org/hooks/commit-msg.sample +24 -0
- data/git-org/hooks/fsmonitor-watchman.sample +174 -0
- data/git-org/hooks/post-update.sample +8 -0
- data/git-org/hooks/pre-applypatch.sample +14 -0
- data/git-org/hooks/pre-commit.sample +49 -0
- data/git-org/hooks/pre-merge-commit.sample +13 -0
- data/git-org/hooks/pre-push.sample +53 -0
- data/git-org/hooks/pre-rebase.sample +169 -0
- data/git-org/hooks/pre-receive.sample +24 -0
- data/git-org/hooks/prepare-commit-msg.sample +42 -0
- data/git-org/hooks/push-to-checkout.sample +78 -0
- data/git-org/hooks/update.sample +128 -0
- data/git-org/info/exclude +6 -0
- data/lib/loggable_activity/activity.rb +4 -3
- data/lib/{schemas → loggable_activity}/config_schema.json +3 -10
- data/lib/loggable_activity/configuration.rb +48 -77
- data/lib/loggable_activity/data_owner.rb +0 -1
- data/lib/loggable_activity/encryption.rb +16 -7
- data/lib/loggable_activity/encryption_key.rb +4 -7
- data/lib/loggable_activity/engine.rb +22 -0
- data/lib/loggable_activity/error.rb +0 -10
- data/lib/loggable_activity/hooks.rb +10 -15
- data/lib/loggable_activity/payload.rb +8 -11
- data/lib/loggable_activity/sanitizer.rb +6 -2
- data/lib/loggable_activity/services/base_payloads_builder.rb +14 -5
- data/lib/loggable_activity/services/destroy_payloads_builder.rb +2 -1
- data/lib/loggable_activity/services/payloads_builder.rb +12 -5
- data/lib/loggable_activity/services/update_payloads_builder.rb +34 -6
- data/lib/loggable_activity/version.rb +1 -1
- data/lib/loggable_activity.rb +51 -14
- data/lib/tasks/loggable_activity_tasks.rake +6 -0
- data/loggable_activity-0.5.0.gem +0 -0
- metadata +129 -109
- data/.document +0 -1
- data/.nojekyll +0 -1
- data/.rspec +0 -3
- data/CONSIDERTIONS.md +0 -129
- data/GETTING-STARTED.md +0 -119
- data/LICENSE.txt +0 -21
- data/PAYLOAD_EXAMPLE.md +0 -63
- data/ROADMAP.md +0 -23
- data/docs/LoggableActivity/Activity.html +0 -555
- data/docs/LoggableActivity/Configuration.html +0 -330
- data/docs/LoggableActivity/ConfigurationError.html +0 -148
- data/docs/LoggableActivity/DataOwner.html +0 -138
- data/docs/LoggableActivity/Encryption.html +0 -234
- data/docs/LoggableActivity/EncryptionError.html +0 -145
- data/docs/LoggableActivity/EncryptionKey.html +0 -351
- data/docs/LoggableActivity/Error.html +0 -145
- data/docs/LoggableActivity/Hooks.html +0 -759
- data/docs/LoggableActivity/Payload.html +0 -432
- data/docs/LoggableActivity/Services/BasePayloadsBuilder.html +0 -442
- data/docs/LoggableActivity/Services/DestroyPayloadsBuilder.html +0 -395
- data/docs/LoggableActivity/Services/PayloadsBuilder.html +0 -342
- data/docs/LoggableActivity/Services/UpdatePayloadsBuilder.html +0 -490
- data/docs/LoggableActivity/Services.html +0 -93
- data/docs/LoggableActivity.html +0 -102
- data/docs/created.rid +0 -14
- data/docs/css/fonts.css +0 -167
- data/docs/css/rdoc.css +0 -687
- data/docs/fonts/Lato-Light.ttf +0 -0
- data/docs/fonts/Lato-LightItalic.ttf +0 -0
- data/docs/fonts/Lato-Regular.ttf +0 -0
- data/docs/fonts/Lato-RegularItalic.ttf +0 -0
- data/docs/fonts/SourceCodePro-Bold.ttf +0 -0
- data/docs/fonts/SourceCodePro-Regular.ttf +0 -0
- data/docs/images/add.png +0 -0
- data/docs/images/arrow_up.png +0 -0
- data/docs/images/brick.png +0 -0
- data/docs/images/brick_link.png +0 -0
- data/docs/images/bug.png +0 -0
- data/docs/images/bullet_black.png +0 -0
- data/docs/images/bullet_toggle_minus.png +0 -0
- data/docs/images/bullet_toggle_plus.png +0 -0
- data/docs/images/date.png +0 -0
- data/docs/images/delete.png +0 -0
- data/docs/images/find.png +0 -0
- data/docs/images/loadingAnimation.gif +0 -0
- data/docs/images/macFFBgHack.png +0 -0
- data/docs/images/package.png +0 -0
- data/docs/images/page_green.png +0 -0
- data/docs/images/page_white_text.png +0 -0
- data/docs/images/page_white_width.png +0 -0
- data/docs/images/plugin.png +0 -0
- data/docs/images/ruby.png +0 -0
- data/docs/images/tag_blue.png +0 -0
- data/docs/images/tag_green.png +0 -0
- data/docs/images/transparent.png +0 -0
- data/docs/images/wrench.png +0 -0
- data/docs/images/wrench_orange.png +0 -0
- data/docs/images/zoom.png +0 -0
- data/docs/index.html +0 -99
- data/docs/js/darkfish.js +0 -97
- data/docs/js/navigation.js +0 -105
- data/docs/js/navigation.js.gz +0 -0
- data/docs/js/search.js +0 -110
- data/docs/js/search_index.js +0 -1
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +0 -229
- data/docs/js/searcher.js.gz +0 -0
- data/docs/table_of_contents.html +0 -617
- data/help/loggable_activity_help.txt +0 -19
- data/lib/generators/.DS_Store +0 -0
- data/lib/generators/loggable_activity/.DS_Store +0 -0
- data/lib/generators/loggable_activity/install_generator.rb +0 -109
- data/lib/generators/loggable_activity/templates/.DS_Store +0 -0
- data/lib/generators/loggable_activity/templates/binary_ids/create_loggable_activities.rb +0 -30
- data/lib/generators/loggable_activity/templates/config/locales/loggable_activity.en.yml +0 -36
- data/lib/generators/loggable_activity/templates/config/loggable_activity.yaml +0 -29
- data/lib/generators/loggable_activity/templates/loggable_activity.en.yaml +0 -36
- data/pkg/loggable_activity-0.1.35.gem +0 -0
- data/sig/loggable_activity.rbs +0 -4
- /data/{.rspec_status → app/assets/images/loggable_activity/.keep} +0 -0
- /data/lib/{generators/loggable_activity/templates → loggable_activity/concerns}/current_user.rb +0 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# An example hook script to prepare the commit log message.
|
4
|
+
# Called by "git commit" with the name of the file that has the
|
5
|
+
# commit message, followed by the description of the commit
|
6
|
+
# message's source. The hook's purpose is to edit the commit
|
7
|
+
# message file. If the hook fails with a non-zero status,
|
8
|
+
# the commit is aborted.
|
9
|
+
#
|
10
|
+
# To enable this hook, rename this file to "prepare-commit-msg".
|
11
|
+
|
12
|
+
# This hook includes three examples. The first one removes the
|
13
|
+
# "# Please enter the commit message..." help message.
|
14
|
+
#
|
15
|
+
# The second includes the output of "git diff --name-status -r"
|
16
|
+
# into the message, just before the "git status" output. It is
|
17
|
+
# commented because it doesn't cope with --amend or with squashed
|
18
|
+
# commits.
|
19
|
+
#
|
20
|
+
# The third example adds a Signed-off-by line to the message, that can
|
21
|
+
# still be edited. This is rarely a good idea.
|
22
|
+
|
23
|
+
COMMIT_MSG_FILE=$1
|
24
|
+
COMMIT_SOURCE=$2
|
25
|
+
SHA1=$3
|
26
|
+
|
27
|
+
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
28
|
+
|
29
|
+
# case "$COMMIT_SOURCE,$SHA1" in
|
30
|
+
# ,|template,)
|
31
|
+
# /usr/bin/perl -i.bak -pe '
|
32
|
+
# print "\n" . `git diff --cached --name-status -r`
|
33
|
+
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
34
|
+
# *) ;;
|
35
|
+
# esac
|
36
|
+
|
37
|
+
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
38
|
+
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
39
|
+
# if test -z "$COMMIT_SOURCE"
|
40
|
+
# then
|
41
|
+
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
42
|
+
# fi
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# An example hook script to update a checked-out tree on a git push.
|
4
|
+
#
|
5
|
+
# This hook is invoked by git-receive-pack(1) when it reacts to git
|
6
|
+
# push and updates reference(s) in its repository, and when the push
|
7
|
+
# tries to update the branch that is currently checked out and the
|
8
|
+
# receive.denyCurrentBranch configuration variable is set to
|
9
|
+
# updateInstead.
|
10
|
+
#
|
11
|
+
# By default, such a push is refused if the working tree and the index
|
12
|
+
# of the remote repository has any difference from the currently
|
13
|
+
# checked out commit; when both the working tree and the index match
|
14
|
+
# the current commit, they are updated to match the newly pushed tip
|
15
|
+
# of the branch. This hook is to be used to override the default
|
16
|
+
# behaviour; however the code below reimplements the default behaviour
|
17
|
+
# as a starting point for convenient modification.
|
18
|
+
#
|
19
|
+
# The hook receives the commit with which the tip of the current
|
20
|
+
# branch is going to be updated:
|
21
|
+
commit=$1
|
22
|
+
|
23
|
+
# It can exit with a non-zero status to refuse the push (when it does
|
24
|
+
# so, it must not modify the index or the working tree).
|
25
|
+
die () {
|
26
|
+
echo >&2 "$*"
|
27
|
+
exit 1
|
28
|
+
}
|
29
|
+
|
30
|
+
# Or it can make any necessary changes to the working tree and to the
|
31
|
+
# index to bring them to the desired state when the tip of the current
|
32
|
+
# branch is updated to the new commit, and exit with a zero status.
|
33
|
+
#
|
34
|
+
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
|
35
|
+
# in order to emulate git fetch that is run in the reverse direction
|
36
|
+
# with git push, as the two-tree form of git read-tree -u -m is
|
37
|
+
# essentially the same as git switch or git checkout that switches
|
38
|
+
# branches while keeping the local changes in the working tree that do
|
39
|
+
# not interfere with the difference between the branches.
|
40
|
+
|
41
|
+
# The below is a more-or-less exact translation to shell of the C code
|
42
|
+
# for the default behaviour for git's push-to-checkout hook defined in
|
43
|
+
# the push_to_deploy() function in builtin/receive-pack.c.
|
44
|
+
#
|
45
|
+
# Note that the hook will be executed from the repository directory,
|
46
|
+
# not from the working tree, so if you want to perform operations on
|
47
|
+
# the working tree, you will have to adapt your code accordingly, e.g.
|
48
|
+
# by adding "cd .." or using relative paths.
|
49
|
+
|
50
|
+
if ! git update-index -q --ignore-submodules --refresh
|
51
|
+
then
|
52
|
+
die "Up-to-date check failed"
|
53
|
+
fi
|
54
|
+
|
55
|
+
if ! git diff-files --quiet --ignore-submodules --
|
56
|
+
then
|
57
|
+
die "Working directory has unstaged changes"
|
58
|
+
fi
|
59
|
+
|
60
|
+
# This is a rough translation of:
|
61
|
+
#
|
62
|
+
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
|
63
|
+
if git cat-file -e HEAD 2>/dev/null
|
64
|
+
then
|
65
|
+
head=HEAD
|
66
|
+
else
|
67
|
+
head=$(git hash-object -t tree --stdin </dev/null)
|
68
|
+
fi
|
69
|
+
|
70
|
+
if ! git diff-index --quiet --cached --ignore-submodules $head --
|
71
|
+
then
|
72
|
+
die "Working directory has staged changes"
|
73
|
+
fi
|
74
|
+
|
75
|
+
if ! git read-tree -u -m "$commit"
|
76
|
+
then
|
77
|
+
die "Could not update working tree to new HEAD"
|
78
|
+
fi
|
@@ -0,0 +1,128 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# An example hook script to block unannotated tags from entering.
|
4
|
+
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
5
|
+
#
|
6
|
+
# To enable this hook, rename this file to "update".
|
7
|
+
#
|
8
|
+
# Config
|
9
|
+
# ------
|
10
|
+
# hooks.allowunannotated
|
11
|
+
# This boolean sets whether unannotated tags will be allowed into the
|
12
|
+
# repository. By default they won't be.
|
13
|
+
# hooks.allowdeletetag
|
14
|
+
# This boolean sets whether deleting tags will be allowed in the
|
15
|
+
# repository. By default they won't be.
|
16
|
+
# hooks.allowmodifytag
|
17
|
+
# This boolean sets whether a tag may be modified after creation. By default
|
18
|
+
# it won't be.
|
19
|
+
# hooks.allowdeletebranch
|
20
|
+
# This boolean sets whether deleting branches will be allowed in the
|
21
|
+
# repository. By default they won't be.
|
22
|
+
# hooks.denycreatebranch
|
23
|
+
# This boolean sets whether remotely creating branches will be denied
|
24
|
+
# in the repository. By default this is allowed.
|
25
|
+
#
|
26
|
+
|
27
|
+
# --- Command line
|
28
|
+
refname="$1"
|
29
|
+
oldrev="$2"
|
30
|
+
newrev="$3"
|
31
|
+
|
32
|
+
# --- Safety check
|
33
|
+
if [ -z "$GIT_DIR" ]; then
|
34
|
+
echo "Don't run this script from the command line." >&2
|
35
|
+
echo " (if you want, you could supply GIT_DIR then run" >&2
|
36
|
+
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
37
|
+
exit 1
|
38
|
+
fi
|
39
|
+
|
40
|
+
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
41
|
+
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
42
|
+
exit 1
|
43
|
+
fi
|
44
|
+
|
45
|
+
# --- Config
|
46
|
+
allowunannotated=$(git config --type=bool hooks.allowunannotated)
|
47
|
+
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
|
48
|
+
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
|
49
|
+
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
|
50
|
+
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
|
51
|
+
|
52
|
+
# check for no description
|
53
|
+
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
54
|
+
case "$projectdesc" in
|
55
|
+
"Unnamed repository"* | "")
|
56
|
+
echo "*** Project description file hasn't been set" >&2
|
57
|
+
exit 1
|
58
|
+
;;
|
59
|
+
esac
|
60
|
+
|
61
|
+
# --- Check types
|
62
|
+
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
63
|
+
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
64
|
+
if [ "$newrev" = "$zero" ]; then
|
65
|
+
newrev_type=delete
|
66
|
+
else
|
67
|
+
newrev_type=$(git cat-file -t $newrev)
|
68
|
+
fi
|
69
|
+
|
70
|
+
case "$refname","$newrev_type" in
|
71
|
+
refs/tags/*,commit)
|
72
|
+
# un-annotated tag
|
73
|
+
short_refname=${refname##refs/tags/}
|
74
|
+
if [ "$allowunannotated" != "true" ]; then
|
75
|
+
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
76
|
+
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
77
|
+
exit 1
|
78
|
+
fi
|
79
|
+
;;
|
80
|
+
refs/tags/*,delete)
|
81
|
+
# delete tag
|
82
|
+
if [ "$allowdeletetag" != "true" ]; then
|
83
|
+
echo "*** Deleting a tag is not allowed in this repository" >&2
|
84
|
+
exit 1
|
85
|
+
fi
|
86
|
+
;;
|
87
|
+
refs/tags/*,tag)
|
88
|
+
# annotated tag
|
89
|
+
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
90
|
+
then
|
91
|
+
echo "*** Tag '$refname' already exists." >&2
|
92
|
+
echo "*** Modifying a tag is not allowed in this repository." >&2
|
93
|
+
exit 1
|
94
|
+
fi
|
95
|
+
;;
|
96
|
+
refs/heads/*,commit)
|
97
|
+
# branch
|
98
|
+
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
99
|
+
echo "*** Creating a branch is not allowed in this repository" >&2
|
100
|
+
exit 1
|
101
|
+
fi
|
102
|
+
;;
|
103
|
+
refs/heads/*,delete)
|
104
|
+
# delete branch
|
105
|
+
if [ "$allowdeletebranch" != "true" ]; then
|
106
|
+
echo "*** Deleting a branch is not allowed in this repository" >&2
|
107
|
+
exit 1
|
108
|
+
fi
|
109
|
+
;;
|
110
|
+
refs/remotes/*,commit)
|
111
|
+
# tracking branch
|
112
|
+
;;
|
113
|
+
refs/remotes/*,delete)
|
114
|
+
# delete tracking branch
|
115
|
+
if [ "$allowdeletebranch" != "true" ]; then
|
116
|
+
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
117
|
+
exit 1
|
118
|
+
fi
|
119
|
+
;;
|
120
|
+
*)
|
121
|
+
# Anything else (is there anything else?)
|
122
|
+
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
123
|
+
exit 1
|
124
|
+
;;
|
125
|
+
esac
|
126
|
+
|
127
|
+
# --- Finished
|
128
|
+
exit 0
|
@@ -5,7 +5,6 @@ require 'active_record'
|
|
5
5
|
module LoggableActivity
|
6
6
|
# Represents one action in the activity log.
|
7
7
|
class Activity < ActiveRecord::Base
|
8
|
-
self.table_name = 'loggable_activities'
|
9
8
|
# Associations
|
10
9
|
has_many :payloads, class_name: '::LoggableActivity::Payload', dependent: :destroy
|
11
10
|
belongs_to :actor, polymorphic: true, optional: true
|
@@ -33,7 +32,7 @@ module LoggableActivity
|
|
33
32
|
'belongs_to_payload' => 'belongs_to',
|
34
33
|
'belongs_to_destroy_payload' => 'belongs_to',
|
35
34
|
'belongs_to_update_payload' => 'belongs_to'
|
36
|
-
}
|
35
|
+
}.freeze
|
37
36
|
|
38
37
|
# Returns an array of hashes, each representing an activity's attributes and its associated relations. The structure and relations to include are specified in 'config/loggable_activity.yaml'. This format is designed for UI display purposes.
|
39
38
|
#
|
@@ -72,7 +71,8 @@ module LoggableActivity
|
|
72
71
|
route: payload.payload_route,
|
73
72
|
record_display_name: payload.record_display_name,
|
74
73
|
current_payload: payload.current_payload,
|
75
|
-
data_owner: payload.data_owner
|
74
|
+
data_owner: payload.data_owner,
|
75
|
+
public_attrs: payload.public_attrs
|
76
76
|
}
|
77
77
|
end
|
78
78
|
end
|
@@ -135,6 +135,7 @@ module LoggableActivity
|
|
135
135
|
return I18n.t('loggable.activity.deleted') if actor_deleted?
|
136
136
|
|
137
137
|
::LoggableActivity::Encryption.decrypt(encrypted_actor_name, actor_secret_key)
|
138
|
+
|
138
139
|
end
|
139
140
|
|
140
141
|
# Returns a list of activities for a given actor.
|
@@ -2,10 +2,7 @@
|
|
2
2
|
"$schema": "http://json-schema.org/draft-06/schema#",
|
3
3
|
"type": "object",
|
4
4
|
"properties": {
|
5
|
-
"
|
6
|
-
"type": "string"
|
7
|
-
},
|
8
|
-
"fetch_current_user_name_from": {
|
5
|
+
"fetch_actor_name_from": {
|
9
6
|
"type": "string"
|
10
7
|
},
|
11
8
|
"task_for_sanitization": {
|
@@ -13,7 +10,7 @@
|
|
13
10
|
}
|
14
11
|
},
|
15
12
|
"patternProperties": {
|
16
|
-
"^(?!
|
13
|
+
"^(?!fetch_actor_name_from$|task_for_sanitization)[A-Za-z0-9_:]+$": {
|
17
14
|
"type": "object",
|
18
15
|
"properties": {
|
19
16
|
"data_owner": {
|
@@ -72,9 +69,6 @@
|
|
72
69
|
"route": {
|
73
70
|
"type": "string",
|
74
71
|
"minLength": 1
|
75
|
-
},
|
76
|
-
"fetch_record_name_from": {
|
77
|
-
"type": "string"
|
78
72
|
}
|
79
73
|
},
|
80
74
|
"required": [
|
@@ -90,7 +84,6 @@
|
|
90
84
|
},
|
91
85
|
"additionalProperties": false,
|
92
86
|
"required": [
|
93
|
-
"
|
94
|
-
"fetch_current_user_name_from"
|
87
|
+
"fetch_actor_name_from"
|
95
88
|
]
|
96
89
|
}
|
@@ -2,94 +2,65 @@
|
|
2
2
|
|
3
3
|
require 'json-schema'
|
4
4
|
require 'json'
|
5
|
-
require 'awesome_print'
|
6
5
|
|
7
6
|
module LoggableActivity
|
8
|
-
# This class is used to load the configuration file located at config/loggable_activity.yml
|
9
|
-
class ConfigurationError < StandardError
|
10
|
-
def initialize(msg = '')
|
11
|
-
# https://api.loggable_activity.com/msg
|
12
|
-
puts '---------------- LOGGABLE ACTIVITY -----------------'
|
13
|
-
puts msg
|
14
|
-
puts '----------------------------------------------------'
|
15
|
-
super(msg)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
7
|
# This class is used to load the configuration file located at config/loggable_activity.yml
|
20
8
|
# When the LoggableActivity::Hook is included in a model
|
21
9
|
# it takes the model's name and find the configuration for that model in the configuration file.
|
22
10
|
class Configuration
|
23
|
-
# Loads the configuration file
|
24
|
-
def self.load_config_file(config_file_path)
|
25
|
-
@config_data = YAML.load_file(config_file_path)
|
26
|
-
validate_config_file
|
27
|
-
rescue Errno::ENOENT
|
28
|
-
raise ConfigurationError, 'config/loggable_activity.yaml not found'
|
29
|
-
end
|
30
|
-
|
31
|
-
# Loads the schema file for the configuration file
|
32
|
-
def self.load_schema
|
33
|
-
schema_path = File.join(__dir__, '..', 'schemas', 'config_schema.json')
|
34
|
-
JSON.parse(File.read(schema_path))
|
35
|
-
end
|
36
|
-
|
37
|
-
# Validates the configuration file againss the schema
|
38
|
-
def self.validate_config_file
|
39
|
-
schema = load_schema
|
40
|
-
errors = JSON::Validator.fully_validate(schema, @config_data)
|
41
|
-
return unless errors.any?
|
42
|
-
|
43
|
-
raise ConfigurationError,
|
44
|
-
"config/loggable_activity.yaml is invalid: #{errors.join(', ')}"
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns true if the configuration file has been loaded
|
48
|
-
def self.loaded?
|
49
|
-
!@config_data.nil?
|
50
|
-
end
|
51
|
-
|
52
|
-
# Returns the configuration data
|
53
11
|
class << self
|
54
|
-
#
|
55
|
-
|
56
|
-
|
12
|
+
# Loads the schema file for the configuration file
|
13
|
+
def load_schema
|
14
|
+
schema_path = File.join(__dir__, 'config_schema.json')
|
15
|
+
JSON.parse(File.read(schema_path))
|
16
|
+
end
|
57
17
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# Returns:
|
63
|
-
# {
|
64
|
-
# "fetch_record_name_from": "full_name",
|
65
|
-
# "loggable_attrs": [
|
66
|
-
# "first_name",
|
67
|
-
# "last_name",
|
68
|
-
# ],
|
69
|
-
# "auto_log": [
|
70
|
-
# "create",
|
71
|
-
# "update",
|
72
|
-
# "destroy"
|
73
|
-
# ],
|
74
|
-
# ....
|
75
|
-
# }
|
76
|
-
def self.for_class(class_name)
|
77
|
-
@config_data[class_name]
|
78
|
-
end
|
18
|
+
# Loads the configuration file, and store it as a hash
|
19
|
+
def config_data
|
20
|
+
@config_data ||= YAML.load_file(LoggableActivity.config_file_path)
|
21
|
+
end
|
79
22
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
23
|
+
# Validates the configuration file againss the schema
|
24
|
+
def validate_config_file
|
25
|
+
schema = load_schema
|
26
|
+
errors = JSON::Validator.fully_validate(schema, config_data)
|
27
|
+
return true unless errors.any?
|
84
28
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
29
|
+
raise ConfigurationError,
|
30
|
+
"config/loggable_activity.yaml is invalid: #{errors.join(', ')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the configuration data for the given class
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
# ::LoggableActivity::Configuration.for_class('User')
|
37
|
+
# Returns:
|
38
|
+
# {
|
39
|
+
# "fetch_record_name_from": "full_name",
|
40
|
+
# "loggable_attrs": [
|
41
|
+
# "first_name",
|
42
|
+
# "last_name",
|
43
|
+
# ],
|
44
|
+
# "auto_log": [
|
45
|
+
# "create",
|
46
|
+
# "update",
|
47
|
+
# "destroy"
|
48
|
+
# ],
|
49
|
+
# ....
|
50
|
+
# }
|
51
|
+
def for_class(class_name)
|
52
|
+
config_data[class_name]
|
53
|
+
end
|
89
54
|
|
90
|
-
|
91
|
-
|
92
|
-
|
55
|
+
# Returns the name of the field or method to use for the actor's display name.
|
56
|
+
def fetch_actor_name_from
|
57
|
+
config_data['fetch_actor_name_from']
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns whatever models should be sanitized on delete.
|
61
|
+
def task_for_sanitization
|
62
|
+
config_data['task_for_sanitization']
|
63
|
+
end
|
93
64
|
end
|
94
65
|
end
|
95
66
|
end
|
@@ -6,7 +6,6 @@ module LoggableActivity
|
|
6
6
|
# This class represends an additional data owner for a record.
|
7
7
|
# For it to kick in, the data_owner configuration has to be set to true in the loggable_activity.yaml file.
|
8
8
|
class DataOwner < ActiveRecord::Base
|
9
|
-
self.table_name = 'loggable_data_owners'
|
10
9
|
belongs_to :record, polymorphic: true, optional: true
|
11
10
|
belongs_to :encryption_key, class_name: '::LoggableActivity::EncryptionKey'
|
12
11
|
|
@@ -20,7 +20,10 @@ module LoggableActivity
|
|
20
20
|
return nil if data.nil?
|
21
21
|
|
22
22
|
encryption_key = Base64.decode64(secret_key)
|
23
|
-
|
23
|
+
unless encryption_key.bytesize == 32
|
24
|
+
raise EncryptionError,
|
25
|
+
"Encryption failed: Invalid encoded_key length #{encryption_key.bytesize}"
|
26
|
+
end
|
24
27
|
|
25
28
|
cipher = OpenSSL::Cipher.new('AES-256-CBC').encrypt
|
26
29
|
cipher.key = encryption_key
|
@@ -42,11 +45,14 @@ module LoggableActivity
|
|
42
45
|
# "my secret data"
|
43
46
|
#
|
44
47
|
def self.decrypt(data, secret_key)
|
45
|
-
return I18n.t('
|
48
|
+
return I18n.t('loggable_activity.activity.deleted') if secret_key.nil?
|
46
49
|
return '' if data.blank?
|
47
50
|
|
48
51
|
encryption_key = Base64.decode64(secret_key)
|
49
|
-
|
52
|
+
unless encryption_key.bytesize == 32
|
53
|
+
raise EncryptionError,
|
54
|
+
"Decryption failed: Invalid encoded_key length: #{encryption_key.bytesize}"
|
55
|
+
end
|
50
56
|
|
51
57
|
cipher = OpenSSL::Cipher.new('AES-256-CBC').decrypt
|
52
58
|
cipher.key = encryption_key
|
@@ -58,11 +64,14 @@ module LoggableActivity
|
|
58
64
|
|
59
65
|
decrypted_data.force_encoding('UTF-8')
|
60
66
|
rescue OpenSSL::Cipher::CipherError => e
|
61
|
-
|
62
|
-
'
|
67
|
+
Rails.logger.error "CipherError Decryption failed: #{e.message}"
|
68
|
+
I18n.t('loggable_activity.decryption.failed')
|
63
69
|
rescue EncryptionError => e
|
64
|
-
|
65
|
-
'
|
70
|
+
Rails.logger.error "EncryptionError: #{e.message}"
|
71
|
+
I18n.t('loggable_activity.decryption.failed')
|
72
|
+
rescue ArgumentError => e
|
73
|
+
Rails.logger.error "ArgumentError Decryption failed: #{e.message}"
|
74
|
+
I18n.t('loggable_activity.decryption.failed')
|
66
75
|
end
|
67
76
|
|
68
77
|
# Returns true if the given value is blank
|
@@ -6,15 +6,13 @@ module LoggableActivity
|
|
6
6
|
# This class represents the encryption key used to unlock the data for one payload.
|
7
7
|
# When deleted, only the encryption_key field is deleted.
|
8
8
|
class EncryptionKey < ActiveRecord::Base
|
9
|
-
self.table_name = 'loggable_encryption_keys'
|
10
|
-
|
11
9
|
# Associations
|
12
10
|
belongs_to :record, polymorphic: true, optional: true
|
13
11
|
# belongs_to :payload, class_name: '::LoggableActivity::Payload', optional: true
|
14
12
|
# belongs_to :parent_key, class_name: '::LoggableActivity::EncryptionKey', optional: true,
|
15
13
|
# foreign_key: 'parent_key_id'
|
16
14
|
|
17
|
-
# Prepare the record for deletion
|
15
|
+
# Prepare the record for deletion
|
18
16
|
def mark_as_deleted!
|
19
17
|
LoggableActivity::Configuration.task_for_sanitization ? update(delete_at: DateTime.now + 1.month) : delete
|
20
18
|
end
|
@@ -25,17 +23,16 @@ module LoggableActivity
|
|
25
23
|
end
|
26
24
|
|
27
25
|
# Delete the encryption key by updating the key to nil.
|
26
|
+
# Nullify the delete_at field, so the key is not deleted when the sanitization task runs.
|
28
27
|
def delete
|
29
|
-
update(secret_key: nil, delete_at: nil)
|
28
|
+
update(secret_key: nil, delete_at: nil)
|
30
29
|
end
|
31
30
|
|
32
31
|
# Restores the encryption key by updating the delete_at field to nil.
|
33
32
|
def restore!
|
34
|
-
update(delete_at: nil) if delete_at &&
|
33
|
+
update(delete_at: nil) if delete_at && DateTime.now < delete_at
|
35
34
|
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
36
|
# Returns an encryption key for a record by its type and ID, optionally using a parent key.
|
40
37
|
#
|
41
38
|
# @param record_type [String] The type of the record.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LoggableActivity
|
4
|
+
# Engine
|
5
|
+
#
|
6
|
+
# This module defines the LoggableActivity engine for use within a Rails application.
|
7
|
+
# It leverages Rails::Engine to create an isolated namespace, ensuring that the components
|
8
|
+
# of the LoggableActivity engine (such as models, controllers, and views) do not interfere
|
9
|
+
# with those of the host application or other engines.
|
10
|
+
#
|
11
|
+
# Example Usage:
|
12
|
+
# In a Rails application, you can mount this engine to make its functionality available:
|
13
|
+
#
|
14
|
+
# mount LoggableActivity::Engine, at: "/loggable_activity"
|
15
|
+
#
|
16
|
+
# This will allow the application to utilize the features provided by the LoggableActivity engine
|
17
|
+
# under the specified mount path.
|
18
|
+
#
|
19
|
+
class Engine < ::Rails::Engine
|
20
|
+
isolate_namespace LoggableActivity
|
21
|
+
end
|
22
|
+
end
|
@@ -4,9 +4,6 @@ module LoggableActivity
|
|
4
4
|
# Error class for loggable activity.
|
5
5
|
class Error < StandardError
|
6
6
|
def initialize(msg = '')
|
7
|
-
puts '---------------- LOGGABLE ACTIVITY -----------------'
|
8
|
-
puts msg
|
9
|
-
puts '----------------------------------------------------'
|
10
7
|
super(msg)
|
11
8
|
end
|
12
9
|
end
|
@@ -14,9 +11,6 @@ module LoggableActivity
|
|
14
11
|
# Error class for encryption.
|
15
12
|
class EncryptionError < StandardError
|
16
13
|
def initialize(msg = '')
|
17
|
-
puts '---------------- LOGGABLE ACTIVITY -----------------'
|
18
|
-
puts msg
|
19
|
-
puts '----------------------------------------------------'
|
20
14
|
super(msg)
|
21
15
|
end
|
22
16
|
end
|
@@ -24,10 +18,6 @@ module LoggableActivity
|
|
24
18
|
# This class is used to load the configuration file located at config/loggable_activity.yml
|
25
19
|
class ConfigurationError < StandardError
|
26
20
|
def initialize(msg = '')
|
27
|
-
# https://api.loggable_activity.com/msg
|
28
|
-
puts '---------------- LOGGABLE ACTIVITY -----------------'
|
29
|
-
puts msg
|
30
|
-
puts '----------------------------------------------------'
|
31
21
|
super(msg)
|
32
22
|
end
|
33
23
|
end
|