mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
basic implementation of audit logging
This commit is contained in:
parent
47d296cf12
commit
a9698d362f
13
setup.py
13
setup.py
@ -1,18 +1,15 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import binascii
|
|
||||||
import getpass
|
|
||||||
import os
|
|
||||||
import base64
|
import base64
|
||||||
|
import getpass
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Util import Counter
|
||||||
|
|
||||||
from builtins import input
|
from builtins import input
|
||||||
|
|
||||||
import src.config_provider
|
|
||||||
import src.sql
|
|
||||||
import src.my_scrypt
|
import src.my_scrypt
|
||||||
from Crypto.Cipher import AES
|
|
||||||
from Crypto.Util import Counter
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
config = src.config_provider.getConfig()
|
config = src.config_provider.getConfig()
|
||||||
src.sql.connect(config['Document']['documentPath'])
|
src.sql.connect(config['Document']['documentPath'])
|
||||||
|
8
src/audit_category.py
Normal file
8
src/audit_category.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
UPDATE_CONTENT = 'CONTENT'
|
||||||
|
CHANGE_POSITION = 'POSITION'
|
||||||
|
CREATE_NOTE = 'CREATE'
|
||||||
|
DELETE_NOTE = 'DELETE'
|
||||||
|
CHANGE_PARENT = 'PARENT'
|
||||||
|
ENCRYPTION = 'ENCRYPTION'
|
||||||
|
CHANGE_PASSWORD = 'PASSWORD'
|
||||||
|
SETTINGS = 'SETTINGS'
|
@ -5,9 +5,10 @@ from Crypto.Util import Counter
|
|||||||
|
|
||||||
import sql
|
import sql
|
||||||
import my_scrypt
|
import my_scrypt
|
||||||
|
import audit_category
|
||||||
|
|
||||||
|
|
||||||
def change_password(current_password, new_password):
|
def change_password(current_password, new_password, request = None):
|
||||||
current_password_hash = base64.b64encode(my_scrypt.getVerificationHash(current_password))
|
current_password_hash = base64.b64encode(my_scrypt.getVerificationHash(current_password))
|
||||||
|
|
||||||
if current_password_hash != sql.getOption('password_verification_hash'):
|
if current_password_hash != sql.getOption('password_verification_hash'):
|
||||||
@ -49,6 +50,8 @@ def change_password(current_password, new_password):
|
|||||||
|
|
||||||
sql.setOption('password_verification_hash', new_password_verification_key)
|
sql.setOption('password_verification_hash', new_password_verification_key)
|
||||||
|
|
||||||
|
sql.addAudit(audit_category.CHANGE_PASSWORD, request)
|
||||||
|
|
||||||
sql.commit()
|
sql.commit()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -10,7 +10,9 @@ from flask_login import login_required
|
|||||||
|
|
||||||
from sql import delete
|
from sql import delete
|
||||||
from sql import execute, insert, commit
|
from sql import execute, insert, commit
|
||||||
from sql import getResults, getSingleResult, getOption
|
from sql import getResults, getSingleResult, getOption, addAudit
|
||||||
|
|
||||||
|
import audit_category
|
||||||
|
|
||||||
notes_api = Blueprint('notes_api', __name__)
|
notes_api = Blueprint('notes_api', __name__)
|
||||||
|
|
||||||
@ -66,6 +68,9 @@ def updateNote(note_id):
|
|||||||
now
|
now
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if note['detail']['encryption'] != detail['encryption']:
|
||||||
|
addAudit(audit_category.ENCRYPTION, request, note_id, detail['encryption'], note['detail']['encryption'])
|
||||||
|
|
||||||
execute("update notes set note_title = ?, note_text = ?, encryption = ?, date_modified = ? where note_id = ?", [
|
execute("update notes set note_title = ?, note_text = ?, encryption = ?, date_modified = ? where note_id = ?", [
|
||||||
note['detail']['note_title'],
|
note['detail']['note_title'],
|
||||||
note['detail']['note_text'],
|
note['detail']['note_text'],
|
||||||
@ -105,6 +110,8 @@ def deleteNote(note_id):
|
|||||||
delete("notes_tree", note_id)
|
delete("notes_tree", note_id)
|
||||||
delete("notes", note_id)
|
delete("notes", note_id)
|
||||||
|
|
||||||
|
addAudit(audit_category.DELETE_NOTE, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@ -137,6 +144,8 @@ def createChild(parent_note_id):
|
|||||||
else:
|
else:
|
||||||
raise Exception('Unknown target: ' + note['target'])
|
raise Exception('Unknown target: ' + note['target'])
|
||||||
|
|
||||||
|
addAudit(audit_category.CREATE_NOTE, request, noteId)
|
||||||
|
|
||||||
now = math.floor(time.time())
|
now = math.floor(time.time())
|
||||||
|
|
||||||
insert("notes", {
|
insert("notes", {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
|
from flask import request
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from sql import execute, commit
|
import audit_category
|
||||||
|
from sql import execute, commit, addAudit
|
||||||
from sql import getSingleResult
|
from sql import getSingleResult
|
||||||
|
|
||||||
notes_move_api = Blueprint('notes_move_api', __name__)
|
notes_move_api = Blueprint('notes_move_api', __name__)
|
||||||
@ -20,6 +22,8 @@ def moveToNote(note_id, parent_id):
|
|||||||
|
|
||||||
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [parent_id, new_note_pos, note_id])
|
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [parent_id, new_note_pos, note_id])
|
||||||
|
|
||||||
|
addAudit(audit_category.CHANGE_PARENT, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@ -32,6 +36,8 @@ def moveBeforeNote(note_id, before_note_id):
|
|||||||
|
|
||||||
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [before_note['note_pid'], before_note['note_pos'], note_id])
|
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [before_note['note_pid'], before_note['note_pos'], note_id])
|
||||||
|
|
||||||
|
addAudit(audit_category.CHANGE_POSITION, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
@ -45,6 +51,8 @@ def moveAfterNote(note_id, after_note_id):
|
|||||||
|
|
||||||
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [after_note['note_pid'], after_note['note_pos'] + 1, note_id])
|
execute("update notes_tree set note_pid = ?, note_pos = ? where note_id = ?", [after_note['note_pid'], after_note['note_pos'] + 1, note_id])
|
||||||
|
|
||||||
|
addAudit(audit_category.CHANGE_POSITION, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
@ -53,5 +61,7 @@ def moveAfterNote(note_id, after_note_id):
|
|||||||
def setExpandedNote(note_id, expanded):
|
def setExpandedNote(note_id, expanded):
|
||||||
execute("update notes_tree set is_expanded = ? where note_id = ?", [expanded, note_id])
|
execute("update notes_tree set is_expanded = ? where note_id = ?", [expanded, note_id])
|
||||||
|
|
||||||
|
# no audit here, not really important
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
return jsonify({})
|
return jsonify({})
|
@ -2,6 +2,7 @@ from flask import Blueprint, jsonify, request
|
|||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
import sql
|
import sql
|
||||||
|
import audit_category
|
||||||
|
|
||||||
settings_api = Blueprint('settings_api', __name__)
|
settings_api = Blueprint('settings_api', __name__)
|
||||||
|
|
||||||
@ -25,7 +26,10 @@ def set_settings():
|
|||||||
req = request.get_json(force=True)
|
req = request.get_json(force=True)
|
||||||
|
|
||||||
if req['name'] in allowed_options:
|
if req['name'] in allowed_options:
|
||||||
|
sql.addAudit(audit_category.SETTINGS, request, None, sql.getOption(req['name']), req['value'], req['name'])
|
||||||
|
|
||||||
sql.setOption(req['name'], req['value'])
|
sql.setOption(req['name'], req['value'])
|
||||||
|
|
||||||
sql.commit()
|
sql.commit()
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
14
src/sql.py
14
src/sql.py
@ -1,6 +1,9 @@
|
|||||||
import base64
|
import base64
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
|
import math
|
||||||
|
import time
|
||||||
|
|
||||||
conn = None
|
conn = None
|
||||||
|
|
||||||
def dict_factory(cursor, row):
|
def dict_factory(cursor, row):
|
||||||
@ -32,6 +35,17 @@ def setOption(name, value):
|
|||||||
def getOption(name):
|
def getOption(name):
|
||||||
return getSingleResult("SELECT opt_value FROM options WHERE opt_name = ?", [name])['opt_value']
|
return getSingleResult("SELECT opt_value FROM options WHERE opt_name = ?", [name])['opt_value']
|
||||||
|
|
||||||
|
def addAudit(category, request = None, note_id = None, change_from = None, change_to = None, comment = None):
|
||||||
|
now = math.floor(time.time())
|
||||||
|
|
||||||
|
browser_id = None
|
||||||
|
|
||||||
|
if request:
|
||||||
|
browser_id = request.headers['x-browser-id']
|
||||||
|
|
||||||
|
execute("INSERT INTO audit_log (date_modified, category, browser_id, note_id, change_from, change_to, comment)"
|
||||||
|
" VALUES (?, ?, ?, ?, ?, ?, ?)", [now, category, browser_id, note_id, change_from, change_to, comment])
|
||||||
|
|
||||||
def delete(tablename, note_id):
|
def delete(tablename, note_id):
|
||||||
execute("DELETE FROM " + tablename + " WHERE note_id = ?", [note_id])
|
execute("DELETE FROM " + tablename + " WHERE note_id = ?", [note_id])
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import base64
|
||||||
|
import os
|
||||||
|
|
||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
@ -44,5 +47,6 @@ def getTree():
|
|||||||
retObject['password_derived_key_salt'] = getOption('password_derived_key_salt')
|
retObject['password_derived_key_salt'] = getOption('password_derived_key_salt')
|
||||||
retObject['encrypted_data_key'] = getOption('encrypted_data_key')
|
retObject['encrypted_data_key'] = getOption('encrypted_data_key')
|
||||||
retObject['encryption_session_timeout'] = getOption('encryption_session_timeout')
|
retObject['encryption_session_timeout'] = getOption('encryption_session_timeout')
|
||||||
|
retObject['browser_id'] = base64.b64encode(os.urandom(8))
|
||||||
|
|
||||||
return jsonify(retObject)
|
return jsonify(retObject)
|
@ -95,6 +95,11 @@ $(function(){
|
|||||||
globalEncryptionSessionTimeout = resp.encryption_session_timeout;
|
globalEncryptionSessionTimeout = resp.encryption_session_timeout;
|
||||||
globalEncryptedDataKey = resp.encrypted_data_key;
|
globalEncryptedDataKey = resp.encrypted_data_key;
|
||||||
|
|
||||||
|
// add browser ID header to all AJAX requests
|
||||||
|
$.ajaxSetup({
|
||||||
|
headers: { 'x-browser-id': resp.browser_id }
|
||||||
|
});
|
||||||
|
|
||||||
if (document.location.hash) {
|
if (document.location.hash) {
|
||||||
startNoteId = document.location.hash.substr(1); // strip initial #
|
startNoteId = document.location.hash.substr(1); // strip initial #
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user