loggable_activity 0.2.1 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +29 -42
- data/.vscode/commands.json +2 -2
- data/.vscode/terminals.json +8 -8
- data/CHEAT_SHEET.md +31 -0
- data/MIT-LICENSE +21 -0
- data/README.md +31 -45
- data/Rakefile +6 -4
- data/app/assets/config/loggable_activity_manifest.js +4 -0
- data/app/assets/javascripts/loggable_activity/application.js +2 -0
- data/app/assets/stylesheets/loggable_activity/application.scss +20 -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/kaminari-turbo-bootstrap/_first_page.html.erb +14 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_gap.html.erb +8 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_last_page.html.erb +13 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_next_page.html.erb +13 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_page.html.erb +14 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_paginator.html.erb +27 -0
- data/app/views/kaminari/kaminari-turbo-bootstrap/_prev_page.html.erb +14 -0
- data/app/views/layouts/loggable_activity/application.html.erb +19 -0
- data/app/views/loggable_activity/activities/_activities.html.erb +56 -0
- data/app/views/loggable_activity/activities/index.html.erb +7 -0
- data/app/views/loggable_activity/activities/show.html.erb +2 -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 +3 -3
- data/lib/{schemas → loggable_activity}/config_schema.json +3 -3
- data/lib/loggable_activity/configuration.rb +51 -75
- 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 +27 -0
- data/lib/loggable_activity/error.rb +0 -10
- data/lib/loggable_activity/hooks.rb +10 -5
- 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 +9 -2
- data/lib/loggable_activity/services/update_payloads_builder.rb +30 -2
- data/lib/loggable_activity/version.rb +1 -1
- data/lib/loggable_activity.rb +51 -14
- data/lib/tasks/loggable_activity_tasks.rake +6 -0
- metadata +129 -117
- 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,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
|
@@ -5,7 +5,7 @@
|
|
5
5
|
"current_user_model_name": {
|
6
6
|
"type": "string"
|
7
7
|
},
|
8
|
-
"
|
8
|
+
"current_user_name": {
|
9
9
|
"type": "string"
|
10
10
|
},
|
11
11
|
"task_for_sanitization": {
|
@@ -13,7 +13,7 @@
|
|
13
13
|
}
|
14
14
|
},
|
15
15
|
"patternProperties": {
|
16
|
-
"^(?!current_user_model_name$|
|
16
|
+
"^(?!current_user_model_name$|current_user_name$|task_for_sanitization)[A-Za-z0-9_:]+$": {
|
17
17
|
"type": "object",
|
18
18
|
"properties": {
|
19
19
|
"data_owner": {
|
@@ -91,6 +91,6 @@
|
|
91
91
|
"additionalProperties": false,
|
92
92
|
"required": [
|
93
93
|
"current_user_model_name",
|
94
|
-
"
|
94
|
+
"current_user_name"
|
95
95
|
]
|
96
96
|
}
|
@@ -2,94 +2,70 @@
|
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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?
|
11
|
+
class << self
|
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
|
42
17
|
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
46
22
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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?
|
51
28
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
attr_reader :config_data
|
56
|
-
end
|
29
|
+
raise ConfigurationError,
|
30
|
+
"config/loggable_activity.yaml is invalid: #{errors.join(', ')}"
|
31
|
+
end
|
57
32
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
79
54
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
55
|
+
# Returns the name of the field or method to use for the actor's display name.
|
56
|
+
def current_user_name
|
57
|
+
config_data['current_user_name']
|
58
|
+
end
|
84
59
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
60
|
+
# Returns the name of the model to use for the current user.
|
61
|
+
def current_user_model_name
|
62
|
+
config_data['current_user_model_name']
|
63
|
+
end
|
89
64
|
|
90
|
-
|
91
|
-
|
92
|
-
|
65
|
+
# Returns whatever models should be sanitized on delete.
|
66
|
+
def task_for_sanitization
|
67
|
+
config_data['task_for_sanitization']
|
68
|
+
end
|
93
69
|
end
|
94
70
|
end
|
95
71
|
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,27 @@
|
|
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
|
+
|
22
|
+
# initializer 'loggable_activity.assets.precompile' do |app|
|
23
|
+
# app.config.assets.precompile += %w( loggable_activity/application.css )
|
24
|
+
# app.config.assets.precompile += %w( loggable_activity/bootstrap.css )
|
25
|
+
# end
|
26
|
+
end
|
27
|
+
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
|
@@ -24,6 +24,7 @@ module LoggableActivity
|
|
24
24
|
|
25
25
|
# Initializes attributes based on configuration.
|
26
26
|
self.loggable_attrs = config&.fetch('loggable_attrs', []) || []
|
27
|
+
self.public_attrs = config&.fetch('public_attrs', []) || []
|
27
28
|
self.relations = config&.fetch('relations', []) || []
|
28
29
|
self.auto_log = config&.fetch('auto_log', []) || []
|
29
30
|
self.fetch_record_name_from = config&.fetch('fetch_record_name_from', nil)
|
@@ -60,6 +61,10 @@ module LoggableActivity
|
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
64
|
+
def disable_hooks!
|
65
|
+
self.disable_hooks = true
|
66
|
+
end
|
67
|
+
|
63
68
|
private
|
64
69
|
|
65
70
|
# Logs an activity for the current action.
|
@@ -134,6 +139,7 @@ module LoggableActivity
|
|
134
139
|
# Logs a create activity automatically if configured.
|
135
140
|
def log_create_activity
|
136
141
|
return unless hooks_enabled?
|
142
|
+
return if id.nil?
|
137
143
|
|
138
144
|
log(:create) if self.class.auto_log.include?('create')
|
139
145
|
end
|
@@ -159,13 +165,13 @@ module LoggableActivity
|
|
159
165
|
|
160
166
|
# Returns the encrypted name of the actor.
|
161
167
|
def encrypted_actor_name
|
162
|
-
name = @actor.send(
|
168
|
+
name = @actor.send(current_user_name)
|
163
169
|
::LoggableActivity::Encryption.encrypt(name, actor_secret_key)
|
164
170
|
end
|
165
171
|
|
166
172
|
# Reads the field to feetch the record name from.
|
167
|
-
def
|
168
|
-
::LoggableActivity::Configuration.
|
173
|
+
def current_user_name
|
174
|
+
::LoggableActivity::Configuration.current_user_name
|
169
175
|
end
|
170
176
|
|
171
177
|
# Returns the action key for the current action.
|
@@ -200,13 +206,12 @@ module LoggableActivity
|
|
200
206
|
|
201
207
|
class_methods do
|
202
208
|
# The loggable_attrs attribute is used read the configuration for the model that included LoggableActivity::Hooks.
|
203
|
-
attr_accessor :loggable_attrs, :relations, :auto_log, :fetch_record_name_from, :route
|
209
|
+
attr_accessor :loggable_attrs, :relations, :auto_log, :fetch_record_name_from, :route, :public_attrs
|
204
210
|
|
205
211
|
# Convert the model name and name space in to 'base_action'.
|
206
212
|
def base_action
|
207
213
|
name.downcase.gsub('::', '/')
|
208
214
|
end
|
209
|
-
|
210
215
|
end
|
211
216
|
end
|
212
217
|
end
|