aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--server/helpers/audit-logger.ts123
-rw-r--r--server/helpers/logger.ts2
-rw-r--r--yarn.lock14
4 files changed, 140 insertions, 1 deletions
diff --git a/package.json b/package.json
index 2952bfbfc..cd0a3c5b8 100644
--- a/package.json
+++ b/package.json
@@ -91,10 +91,12 @@
91 "cookie-parser": "^1.4.3", 91 "cookie-parser": "^1.4.3",
92 "cors": "^2.8.1", 92 "cors": "^2.8.1",
93 "create-torrent": "^3.24.5", 93 "create-torrent": "^3.24.5",
94 "deep-object-diff": "^1.1.0",
94 "express": "^4.12.4", 95 "express": "^4.12.4",
95 "express-oauth-server": "^2.0.0", 96 "express-oauth-server": "^2.0.0",
96 "express-rate-limit": "^2.11.0", 97 "express-rate-limit": "^2.11.0",
97 "express-validator": "^5.0.0", 98 "express-validator": "^5.0.0",
99 "flat": "^4.1.0",
98 "fluent-ffmpeg": "^2.1.0", 100 "fluent-ffmpeg": "^2.1.0",
99 "helmet": "^3.12.1", 101 "helmet": "^3.12.1",
100 "ipaddr.js": "https://github.com/whitequark/ipaddr.js.git#8e69afeb4053ee32447a101845f860848280eca5", 102 "ipaddr.js": "https://github.com/whitequark/ipaddr.js.git#8e69afeb4053ee32447a101845f860848280eca5",
diff --git a/server/helpers/audit-logger.ts b/server/helpers/audit-logger.ts
new file mode 100644
index 000000000..4b237316f
--- /dev/null
+++ b/server/helpers/audit-logger.ts
@@ -0,0 +1,123 @@
1import * as path from 'path'
2import { diff } from 'deep-object-diff'
3import { chain } from 'lodash'
4import * as flatten from 'flat'
5import * as winston from 'winston'
6import { CONFIG } from '../initializers'
7import { jsonLoggerFormat, labelFormatter } from './logger'
8import { VideoDetails } from '../../shared'
9
10enum AUDIT_TYPE {
11 CREATE = 'create',
12 UPDATE = 'update',
13 DELETE = 'delete'
14}
15
16const colors = winston.config.npm.colors
17colors.audit = winston.config.npm.colors.info
18
19winston.addColors(colors)
20
21const auditLogger = winston.createLogger({
22 levels: { audit: 0 },
23 transports: [
24 new winston.transports.File({
25 filename: path.join(CONFIG.STORAGE.LOG_DIR, 'peertube-audit.log'),
26 level: 'audit',
27 maxsize: 5242880,
28 maxFiles: 5,
29 format: winston.format.combine(
30 winston.format.timestamp(),
31 labelFormatter,
32 winston.format.splat(),
33 jsonLoggerFormat
34 )
35 })
36 ],
37 exitOnError: true
38})
39
40function auditLoggerWrapper (domain: string, user: string, action: AUDIT_TYPE, entity: EntityAuditView, oldEntity: EntityAuditView = null) {
41 let entityInfos: object
42 if (action === AUDIT_TYPE.UPDATE && oldEntity) {
43 const oldEntityKeys = oldEntity.toLogKeys()
44 const diffObject = diff(oldEntityKeys, entity.toLogKeys())
45 const diffKeys = Object.entries(diffObject).reduce((newKeys, entry) => {
46 newKeys[`new-${entry[0]}`] = entry[1]
47 return newKeys
48 }, {})
49 entityInfos = { ...oldEntityKeys, ...diffKeys }
50 } else {
51 entityInfos = { ...entity.toLogKeys() }
52 }
53 auditLogger.log('audit', JSON.stringify({
54 user,
55 domain,
56 action,
57 ...entityInfos
58 }))
59}
60
61function auditLoggerFactory (domain: string) {
62 return {
63 create (user: string, entity: EntityAuditView) {
64 auditLoggerWrapper(domain, user, AUDIT_TYPE.CREATE, entity)
65 },
66 update (user: string, entity: EntityAuditView, oldEntity: EntityAuditView) {
67 auditLoggerWrapper(domain, user, AUDIT_TYPE.UPDATE, entity, oldEntity)
68 },
69 delete (user: string, entity: EntityAuditView) {
70 auditLoggerWrapper(domain, user, AUDIT_TYPE.DELETE, entity)
71 }
72 }
73}
74
75abstract class EntityAuditView {
76 constructor (private keysToKeep: Array<string>, private prefix: string, private entityInfos: object) { }
77 toLogKeys (): object {
78 return chain(flatten(this.entityInfos, { delimiter: '-', safe: true }))
79 .pick(this.keysToKeep)
80 .mapKeys((value, key) => `${this.prefix}-${key}`)
81 .value()
82 }
83}
84
85const videoKeysToKeep = [
86 'tags',
87 'uuid',
88 'id',
89 'uuid',
90 'createdAt',
91 'updatedAt',
92 'publishedAt',
93 'category',
94 'licence',
95 'language',
96 'privacy',
97 'description',
98 'duration',
99 'isLocal',
100 'name',
101 'thumbnailPath',
102 'previewPath',
103 'nsfw',
104 'waitTranscoding',
105 'account-id',
106 'account-uuid',
107 'account-name',
108 'channel-id',
109 'channel-uuid',
110 'channel-name',
111 'support',
112 'commentsEnabled'
113]
114class VideoAuditView extends AuditEntity {
115 constructor (private video: VideoDetails) {
116 super(videoKeysToKeep, 'video', video)
117 }
118}
119
120export {
121 auditLoggerFactory,
122 VideoAuditView
123}
diff --git a/server/helpers/logger.ts b/server/helpers/logger.ts
index 6d369a8fb..04a19a9c6 100644
--- a/server/helpers/logger.ts
+++ b/server/helpers/logger.ts
@@ -96,13 +96,13 @@ const bunyanLogger = {
96 error: bunyanLogFactory('error'), 96 error: bunyanLogFactory('error'),
97 fatal: bunyanLogFactory('error') 97 fatal: bunyanLogFactory('error')
98} 98}
99
100// --------------------------------------------------------------------------- 99// ---------------------------------------------------------------------------
101 100
102export { 101export {
103 timestampFormatter, 102 timestampFormatter,
104 labelFormatter, 103 labelFormatter,
105 consoleLoggerFormat, 104 consoleLoggerFormat,
105 jsonLoggerFormat,
106 logger, 106 logger,
107 bunyanLogger 107 bunyanLogger
108} 108}
diff --git a/yarn.lock b/yarn.lock
index 5124992db..ec261e025 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1773,6 +1773,10 @@ deep-is@~0.1.3:
1773 version "0.1.3" 1773 version "0.1.3"
1774 resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 1774 resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
1775 1775
1776deep-object-diff@^1.1.0:
1777 version "1.1.0"
1778 resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a"
1779
1776defaults@^1.0.3: 1780defaults@^1.0.3:
1777 version "1.0.3" 1781 version "1.0.3"
1778 resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" 1782 resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
@@ -2573,6 +2577,12 @@ flat-cache@^1.2.1:
2573 graceful-fs "^4.1.2" 2577 graceful-fs "^4.1.2"
2574 write "^0.2.1" 2578 write "^0.2.1"
2575 2579
2580flat@^4.1.0:
2581 version "4.1.0"
2582 resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2"
2583 dependencies:
2584 is-buffer "~2.0.3"
2585
2576flatten@^1.0.2: 2586flatten@^1.0.2:
2577 version "1.0.2" 2587 version "1.0.2"
2578 resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" 2588 resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
@@ -3593,6 +3603,10 @@ is-buffer@^1.1.5, is-buffer@~1.1.1:
3593 version "1.1.6" 3603 version "1.1.6"
3594 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 3604 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
3595 3605
3606is-buffer@~2.0.3:
3607 version "2.0.3"
3608 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
3609
3596is-builtin-module@^1.0.0: 3610is-builtin-module@^1.0.0:
3597 version "1.0.0" 3611 version "1.0.0"
3598 resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" 3612 resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"