mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
refactored naming to conform to PEP 8
This commit is contained in:
parent
8a5ff3968b
commit
c9322465a5
4
setup.py
4
setup.py
@ -33,7 +33,7 @@ if password1 == password2:
|
|||||||
src.sql.setOption('password_verification_salt', base64.b64encode(os.urandom(32)))
|
src.sql.setOption('password_verification_salt', base64.b64encode(os.urandom(32)))
|
||||||
src.sql.setOption('password_derived_key_salt', base64.b64encode(os.urandom(32)))
|
src.sql.setOption('password_derived_key_salt', base64.b64encode(os.urandom(32)))
|
||||||
|
|
||||||
password_derived_key = src.my_scrypt.getPasswordDerivedKey(password1)
|
password_derived_key = src.my_scrypt.get_password_derived_key(password1)
|
||||||
|
|
||||||
aes = AES.new(password_derived_key, AES.MODE_CTR, counter=Counter.new(128, initial_value=5))
|
aes = AES.new(password_derived_key, AES.MODE_CTR, counter=Counter.new(128, initial_value=5))
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ if password1 == password2:
|
|||||||
|
|
||||||
src.sql.setOption('encrypted_data_key', base64.b64encode(encrypted_data_key))
|
src.sql.setOption('encrypted_data_key', base64.b64encode(encrypted_data_key))
|
||||||
|
|
||||||
verification_hash = src.my_scrypt.getVerificationHash(password1)
|
verification_hash = src.my_scrypt.get_verification_hash(password1)
|
||||||
|
|
||||||
src.sql.setOption('username', username)
|
src.sql.setOption('username', username)
|
||||||
src.sql.setOption('password_verification_hash', base64.b64encode(verification_hash))
|
src.sql.setOption('password_verification_hash', base64.b64encode(verification_hash))
|
||||||
|
@ -10,15 +10,15 @@ from notes_history_api import notes_history_api
|
|||||||
from notes_move_api import notes_move_api
|
from notes_move_api import notes_move_api
|
||||||
from password_api import password_api
|
from password_api import password_api
|
||||||
from settings_api import settings_api
|
from settings_api import settings_api
|
||||||
from sql import connect, getOption
|
from sql import connect, get_option
|
||||||
from tree_api import tree_api
|
from tree_api import tree_api
|
||||||
|
|
||||||
config = config_provider.getConfig()
|
config = config_provider.get_config()
|
||||||
|
|
||||||
documentPath = config['Document']['documentPath']
|
documentPath = config['Document']['documentPath']
|
||||||
connect(documentPath)
|
connect(documentPath)
|
||||||
|
|
||||||
flask_secret_key = getOption("flask_secret_key")
|
flask_secret_key = get_option("flask_secret_key")
|
||||||
|
|
||||||
if not flask_secret_key:
|
if not flask_secret_key:
|
||||||
print("Application has not been setup yet. Run 'python setup.py' to finish setup.")
|
print("Application has not been setup yet. Run 'python setup.py' to finish setup.")
|
||||||
|
@ -6,9 +6,10 @@ from sql import getSingleResult
|
|||||||
|
|
||||||
audit_api = Blueprint('audit_api', __name__)
|
audit_api = Blueprint('audit_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@audit_api.route('/api/audit/<int:full_load_time>', methods = ['GET'])
|
@audit_api.route('/api/audit/<int:full_load_time>', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getNote(full_load_time):
|
def get_note(full_load_time):
|
||||||
browser_id = request.headers['x-browser-id']
|
browser_id = request.headers['x-browser-id']
|
||||||
|
|
||||||
count = getSingleResult("SELECT COUNT(*) AS 'count' FROM audit_log WHERE browser_id != ? AND date_modified >= ?", [browser_id, full_load_time])['count']
|
count = getSingleResult("SELECT COUNT(*) AS 'count' FROM audit_log WHERE browser_id != ? AND date_modified >= ?", [browser_id, full_load_time])['count']
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import utils
|
|
||||||
from sql import getOption, setOption, commit
|
|
||||||
import config_provider
|
|
||||||
from shutil import copyfile
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from datetime import datetime
|
||||||
|
from shutil import copyfile
|
||||||
|
|
||||||
|
import config_provider
|
||||||
|
import utils
|
||||||
|
from sql import get_option, set_option, commit
|
||||||
|
|
||||||
|
|
||||||
def regular_backup():
|
def regular_backup():
|
||||||
now = utils.nowTimestamp()
|
now = utils.now_timestamp()
|
||||||
last_backup_date = int(getOption('last_backup_date'))
|
last_backup_date = int(get_option('last_backup_date'))
|
||||||
|
|
||||||
if now - last_backup_date > 43200:
|
if now - last_backup_date > 43200:
|
||||||
backup_now()
|
backup_now()
|
||||||
|
|
||||||
cleanup_old_backups()
|
cleanup_old_backups()
|
||||||
|
|
||||||
def backup_now():
|
|
||||||
now = utils.nowTimestamp()
|
|
||||||
|
|
||||||
config = config_provider.getConfig()
|
def backup_now():
|
||||||
|
now = utils.now_timestamp()
|
||||||
|
|
||||||
|
config = config_provider.get_config()
|
||||||
|
|
||||||
document_path = config['Document']['documentPath']
|
document_path = config['Document']['documentPath']
|
||||||
backup_directory = config['Backup']['backupDirectory']
|
backup_directory = config['Backup']['backupDirectory']
|
||||||
@ -28,12 +30,13 @@ def backup_now():
|
|||||||
|
|
||||||
copyfile(document_path, backup_directory + "/" + "backup-" + date_str + ".db")
|
copyfile(document_path, backup_directory + "/" + "backup-" + date_str + ".db")
|
||||||
|
|
||||||
setOption('last_backup_date', now)
|
set_option('last_backup_date', now)
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
|
|
||||||
def cleanup_old_backups():
|
def cleanup_old_backups():
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
config = config_provider.getConfig()
|
config = config_provider.get_config()
|
||||||
backup_directory = config['Backup']['backupDirectory']
|
backup_directory = config['Backup']['backupDirectory']
|
||||||
|
|
||||||
for file in os.listdir(backup_directory):
|
for file in os.listdir(backup_directory):
|
||||||
|
@ -3,24 +3,24 @@ import hashlib
|
|||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Util import Counter
|
from Crypto.Util import Counter
|
||||||
|
|
||||||
import sql
|
|
||||||
import my_scrypt
|
|
||||||
import audit_category
|
import audit_category
|
||||||
|
import my_scrypt
|
||||||
|
import sql
|
||||||
|
|
||||||
|
|
||||||
def change_password(current_password, new_password, request = None):
|
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.get_verification_hash(current_password))
|
||||||
|
|
||||||
if current_password_hash != sql.getOption('password_verification_hash'):
|
if current_password_hash != sql.get_option('password_verification_hash'):
|
||||||
return {
|
return {
|
||||||
'success': False,
|
'success': False,
|
||||||
'message': "Given current password doesn't match hash"
|
'message': "Given current password doesn't match hash"
|
||||||
}
|
}
|
||||||
|
|
||||||
current_password_derived_key = my_scrypt.getPasswordDerivedKey(current_password)
|
current_password_derived_key = my_scrypt.get_password_derived_key(current_password)
|
||||||
|
|
||||||
new_password_verification_key = base64.b64encode(my_scrypt.getVerificationHash(new_password))
|
new_password_verification_key = base64.b64encode(my_scrypt.get_verification_hash(new_password))
|
||||||
new_password_encryption_key = my_scrypt.getPasswordDerivedKey(new_password)
|
new_password_encryption_key = my_scrypt.get_password_derived_key(new_password)
|
||||||
|
|
||||||
def decrypt(encrypted_base64):
|
def decrypt(encrypted_base64):
|
||||||
encrypted_bytes = base64.b64decode(encrypted_base64)
|
encrypted_bytes = base64.b64decode(encrypted_base64)
|
||||||
@ -40,17 +40,17 @@ def change_password(current_password, new_password, request = None):
|
|||||||
def get_aes(key):
|
def get_aes(key):
|
||||||
return AES.new(key, AES.MODE_CTR, counter=Counter.new(128, initial_value=5))
|
return AES.new(key, AES.MODE_CTR, counter=Counter.new(128, initial_value=5))
|
||||||
|
|
||||||
encrypted_data_key = sql.getOption('encrypted_data_key')
|
encrypted_data_key = sql.get_option('encrypted_data_key')
|
||||||
|
|
||||||
decrypted_data_key = decrypt(encrypted_data_key)
|
decrypted_data_key = decrypt(encrypted_data_key)
|
||||||
|
|
||||||
new_encrypted_data_key = encrypt(decrypted_data_key)
|
new_encrypted_data_key = encrypt(decrypted_data_key)
|
||||||
|
|
||||||
sql.setOption('encrypted_data_key', new_encrypted_data_key)
|
sql.set_option('encrypted_data_key', new_encrypted_data_key)
|
||||||
|
|
||||||
sql.setOption('password_verification_hash', new_password_verification_key)
|
sql.set_option('password_verification_hash', new_password_verification_key)
|
||||||
|
|
||||||
sql.addAudit(audit_category.CHANGE_PASSWORD, request)
|
sql.add_audit(audit_category.CHANGE_PASSWORD, request)
|
||||||
|
|
||||||
sql.commit()
|
sql.commit()
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import configparser
|
import configparser
|
||||||
|
|
||||||
def getConfig():
|
def get_config():
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read('config.ini')
|
config.read('config.ini')
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import traceback
|
|||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from sql import getOption, setOption, commit, execute_script
|
from sql import get_option, set_option, commit, execute_script
|
||||||
|
|
||||||
import backup
|
import backup
|
||||||
|
|
||||||
@ -16,22 +16,24 @@ MIGRATIONS_DIR = "src/migrations"
|
|||||||
|
|
||||||
migration_api = Blueprint('migration_api', __name__)
|
migration_api = Blueprint('migration_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@migration_api.route('/api/migration', methods = ['GET'])
|
@migration_api.route('/api/migration', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getMigrationInfo():
|
def get_migration_info():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'db_version': int(getOption('db_version')),
|
'db_version': int(get_option('db_version')),
|
||||||
'app_db_version': APP_DB_VERSION
|
'app_db_version': APP_DB_VERSION
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@migration_api.route('/api/migration', methods = ['POST'])
|
@migration_api.route('/api/migration', methods = ['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def runMigration():
|
def run_migration():
|
||||||
migrations = []
|
migrations = []
|
||||||
|
|
||||||
backup.backup_now()
|
backup.backup_now()
|
||||||
|
|
||||||
current_db_version = int(getOption('db_version'))
|
current_db_version = int(get_option('db_version'))
|
||||||
|
|
||||||
for file in os.listdir(MIGRATIONS_DIR):
|
for file in os.listdir(MIGRATIONS_DIR):
|
||||||
match = re.search(r"([0-9]{4})__([a-zA-Z0-9_ ]+)\.sql", file)
|
match = re.search(r"([0-9]{4})__([a-zA-Z0-9_ ]+)\.sql", file)
|
||||||
@ -55,7 +57,7 @@ def runMigration():
|
|||||||
try:
|
try:
|
||||||
execute_script(sql)
|
execute_script(sql)
|
||||||
|
|
||||||
setOption('db_version', db_version)
|
set_option('db_version', db_version)
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
migration_record['success'] = True
|
migration_record['success'] = True
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
import scrypt # pip install scrypt
|
import scrypt # pip install scrypt
|
||||||
|
|
||||||
import sql
|
import sql
|
||||||
|
|
||||||
def getVerificationHash(password):
|
|
||||||
salt = sql.getOption('password_verification_salt')
|
|
||||||
|
|
||||||
return getScryptHash(password, salt)
|
def get_verification_hash(password):
|
||||||
|
salt = sql.get_option('password_verification_salt')
|
||||||
|
|
||||||
def getPasswordDerivedKey(password):
|
return get_scrypt_hash(password, salt)
|
||||||
salt = sql.getOption('password_derived_key_salt')
|
|
||||||
|
|
||||||
return getScryptHash(password, salt)
|
|
||||||
|
|
||||||
def getScryptHash(password, salt):
|
def get_password_derived_key(password):
|
||||||
|
salt = sql.get_option('password_derived_key_salt')
|
||||||
|
|
||||||
|
return get_scrypt_hash(password, salt)
|
||||||
|
|
||||||
|
|
||||||
|
def get_scrypt_hash(password, salt):
|
||||||
# scrypt doesn't like unicode strings
|
# scrypt doesn't like unicode strings
|
||||||
password = password.encode('ascii', 'ignore')
|
password = password.encode('ascii', 'ignore')
|
||||||
salt = salt.encode('ascii', 'ignore')
|
salt = salt.encode('ascii', 'ignore')
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
import base64
|
import base64
|
||||||
import math
|
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import time
|
|
||||||
|
|
||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
from flask import request
|
from flask import request
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
|
import audit_category
|
||||||
|
import utils
|
||||||
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, addAudit, deleteRecentAudits
|
from sql import getResults, getSingleResult, get_option, add_audit, deleteRecentAudits
|
||||||
|
|
||||||
import utils
|
|
||||||
import audit_category
|
|
||||||
|
|
||||||
notes_api = Blueprint('notes_api', __name__)
|
notes_api = Blueprint('notes_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@notes_api.route('/api/notes/<string:note_id>', methods = ['GET'])
|
@notes_api.route('/api/notes/<string:note_id>', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getNote(note_id):
|
def get_note(note_id):
|
||||||
execute("update options set opt_value = ? where opt_name = 'start_node'", [note_id])
|
execute("update options set opt_value = ? where opt_name = 'start_node'", [note_id])
|
||||||
|
|
||||||
detail = getSingleResult("select * from notes where note_id = ?", [note_id])
|
detail = getSingleResult("select * from notes where note_id = ?", [note_id])
|
||||||
@ -35,9 +33,10 @@ def getNote(note_id):
|
|||||||
'images': getResults("select * from images where note_id = ? order by note_offset", [note_id])
|
'images': getResults("select * from images where note_id = ? order by note_offset", [note_id])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@notes_api.route('/api/notes/<string:note_id>', methods = ['PUT'])
|
@notes_api.route('/api/notes/<string:note_id>', methods = ['PUT'])
|
||||||
@login_required
|
@login_required
|
||||||
def updateNote(note_id):
|
def update_note(note_id):
|
||||||
detail = getSingleResult("select * from notes where note_id = ?", [note_id])
|
detail = getSingleResult("select * from notes where note_id = ?", [note_id])
|
||||||
|
|
||||||
if detail['note_clone_id']:
|
if detail['note_clone_id']:
|
||||||
@ -45,9 +44,9 @@ def updateNote(note_id):
|
|||||||
|
|
||||||
note = request.get_json(force=True)
|
note = request.get_json(force=True)
|
||||||
|
|
||||||
now = utils.nowTimestamp()
|
now = utils.now_timestamp()
|
||||||
|
|
||||||
history_snapshot_time_interval = float(getOption('history_snapshot_time_interval'))
|
history_snapshot_time_interval = float(get_option('history_snapshot_time_interval'))
|
||||||
|
|
||||||
history_cutoff = now - history_snapshot_time_interval
|
history_cutoff = now - history_snapshot_time_interval
|
||||||
|
|
||||||
@ -71,14 +70,14 @@ def updateNote(note_id):
|
|||||||
|
|
||||||
if note['detail']['note_title'] != detail['note_title']:
|
if note['detail']['note_title'] != detail['note_title']:
|
||||||
deleteRecentAudits(audit_category.UPDATE_TITLE, request, note_id)
|
deleteRecentAudits(audit_category.UPDATE_TITLE, request, note_id)
|
||||||
addAudit(audit_category.UPDATE_TITLE, request, note_id)
|
add_audit(audit_category.UPDATE_TITLE, request, note_id)
|
||||||
|
|
||||||
if note['detail']['note_text'] != detail['note_text']:
|
if note['detail']['note_text'] != detail['note_text']:
|
||||||
deleteRecentAudits(audit_category.UPDATE_CONTENT, request, note_id)
|
deleteRecentAudits(audit_category.UPDATE_CONTENT, request, note_id)
|
||||||
addAudit(audit_category.UPDATE_CONTENT, request, note_id)
|
add_audit(audit_category.UPDATE_CONTENT, request, note_id)
|
||||||
|
|
||||||
if note['detail']['encryption'] != detail['encryption']:
|
if note['detail']['encryption'] != detail['encryption']:
|
||||||
addAudit(audit_category.ENCRYPTION, request, note_id, detail['encryption'], note['detail']['encryption'])
|
add_audit(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'],
|
||||||
@ -108,25 +107,27 @@ def updateNote(note_id):
|
|||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@notes_api.route('/api/notes/<string:note_id>', methods = ['DELETE'])
|
@notes_api.route('/api/notes/<string:note_id>', methods = ['DELETE'])
|
||||||
@login_required
|
@login_required
|
||||||
def deleteNote(note_id):
|
def delete_note(note_id):
|
||||||
children = getResults("select note_id from notes_tree where note_pid = ?", [note_id])
|
children = getResults("select note_id from notes_tree where note_pid = ?", [note_id])
|
||||||
|
|
||||||
for child in children:
|
for child in children:
|
||||||
deleteNote(child['note_id'])
|
delete_note(child['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)
|
add_audit(audit_category.DELETE_NOTE, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@notes_api.route('/api/notes/<string:parent_note_id>/children', methods = ['POST'])
|
@notes_api.route('/api/notes/<string:parent_note_id>/children', methods = ['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def createChild(parent_note_id):
|
def create_child(parent_note_id):
|
||||||
note = request.get_json(force=True)
|
note = request.get_json(force=True)
|
||||||
|
|
||||||
noteId = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(22))
|
noteId = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(22))
|
||||||
@ -153,9 +154,9 @@ 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)
|
add_audit(audit_category.CREATE_NOTE, request, noteId)
|
||||||
|
|
||||||
now = utils.nowTimestamp()
|
now = utils.now_timestamp()
|
||||||
|
|
||||||
insert("notes", {
|
insert("notes", {
|
||||||
'note_id': noteId,
|
'note_id': noteId,
|
||||||
@ -182,9 +183,10 @@ def createChild(parent_note_id):
|
|||||||
'note_id': noteId
|
'note_id': noteId
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@notes_api.route('/api/notes', methods = ['GET'])
|
@notes_api.route('/api/notes', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def searchNotes():
|
def search_notes():
|
||||||
search = '%' + request.args['search'] + '%'
|
search = '%' + request.args['search'] + '%'
|
||||||
|
|
||||||
result = getResults("select note_id from notes where note_title like ? or note_text like ?", [search, search])
|
result = getResults("select note_id from notes where note_title like ? or note_text like ?", [search, search])
|
||||||
|
@ -5,16 +5,18 @@ from sql import getResults
|
|||||||
|
|
||||||
notes_history_api = Blueprint('notes_history_api', __name__)
|
notes_history_api = Blueprint('notes_history_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@notes_history_api.route('/api/notes-history/<string:note_id>', methods = ['GET'])
|
@notes_history_api.route('/api/notes-history/<string:note_id>', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getNoteHistory(note_id):
|
def get_note_history(note_id):
|
||||||
history = getResults("select * from notes_history where note_id = ? order by date_modified desc", [note_id])
|
history = getResults("select * from notes_history where note_id = ? order by date_modified desc", [note_id])
|
||||||
|
|
||||||
return jsonify(history)
|
return jsonify(history)
|
||||||
|
|
||||||
|
|
||||||
@notes_history_api.route('/api/recent-changes/', methods = ['GET'])
|
@notes_history_api.route('/api/recent-changes/', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getRecentChanges():
|
def get_recent_changes():
|
||||||
recent_changes = getResults("select * from notes_history order by date_modified desc limit 1000")
|
recent_changes = getResults("select * from notes_history order by date_modified desc limit 1000")
|
||||||
|
|
||||||
return jsonify(recent_changes)
|
return jsonify(recent_changes)
|
@ -3,14 +3,14 @@ from flask import request
|
|||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
import audit_category
|
import audit_category
|
||||||
from sql import execute, commit, addAudit
|
from sql import execute, commit, add_audit
|
||||||
from sql import getSingleResult
|
from sql import getSingleResult
|
||||||
|
|
||||||
notes_move_api = Blueprint('notes_move_api', __name__)
|
notes_move_api = Blueprint('notes_move_api', __name__)
|
||||||
|
|
||||||
@notes_move_api.route('/api/notes/<string:note_id>/moveTo/<string:parent_id>', methods = ['PUT'])
|
@notes_move_api.route('/api/notes/<string:note_id>/moveTo/<string:parent_id>', methods = ['PUT'])
|
||||||
@login_required
|
@login_required
|
||||||
def moveToNote(note_id, parent_id):
|
def move_to_note(note_id, parent_id):
|
||||||
res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_id])
|
res = getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parent_id])
|
||||||
max_note_pos = res['max_note_pos']
|
max_note_pos = res['max_note_pos']
|
||||||
new_note_pos = 0
|
new_note_pos = 0
|
||||||
@ -22,13 +22,14 @@ 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)
|
add_audit(audit_category.CHANGE_PARENT, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@notes_move_api.route('/api/notes/<string:note_id>/moveBefore/<string:before_note_id>', methods = ['PUT'])
|
@notes_move_api.route('/api/notes/<string:note_id>/moveBefore/<string:before_note_id>', methods = ['PUT'])
|
||||||
def moveBeforeNote(note_id, before_note_id):
|
def move_before_note(note_id, before_note_id):
|
||||||
before_note = getSingleResult("select * from notes_tree where note_id = ?", [before_note_id])
|
before_note = getSingleResult("select * from notes_tree where note_id = ?", [before_note_id])
|
||||||
|
|
||||||
if before_note <> None:
|
if before_note <> None:
|
||||||
@ -36,14 +37,15 @@ 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)
|
add_audit(audit_category.CHANGE_POSITION, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@notes_move_api.route('/api/notes/<string:note_id>/moveAfter/<string:after_note_id>', methods = ['PUT'])
|
@notes_move_api.route('/api/notes/<string:note_id>/moveAfter/<string:after_note_id>', methods = ['PUT'])
|
||||||
def moveAfterNote(note_id, after_note_id):
|
def move_after_note(note_id, after_note_id):
|
||||||
after_note = getSingleResult("select * from notes_tree where note_id = ?", [after_note_id])
|
after_note = getSingleResult("select * from notes_tree where note_id = ?", [after_note_id])
|
||||||
|
|
||||||
if after_note <> None:
|
if after_note <> None:
|
||||||
@ -51,14 +53,15 @@ 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)
|
add_audit(audit_category.CHANGE_POSITION, request, note_id)
|
||||||
|
|
||||||
commit()
|
commit()
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@notes_move_api.route('/api/notes/<string:note_id>/expanded/<int:expanded>', methods = ['PUT'])
|
@notes_move_api.route('/api/notes/<string:note_id>/expanded/<int:expanded>', methods = ['PUT'])
|
||||||
def setExpandedNote(note_id, expanded):
|
def set_expanded_note(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
|
# no audit here, not really important
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
from flask import Blueprint, jsonify, request
|
from flask import Blueprint, jsonify, request
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
import hashlib
|
|
||||||
import binascii
|
|
||||||
import sql
|
|
||||||
import change_password
|
import change_password
|
||||||
|
|
||||||
password_api = Blueprint('password_api', __name__)
|
password_api = Blueprint('password_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@password_api.route('/api/password/change', methods = ['POST'])
|
@password_api.route('/api/password/change', methods = ['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def changePassword():
|
def change_password():
|
||||||
req = request.get_json(force=True)
|
req = request.get_json(force=True)
|
||||||
|
|
||||||
result = change_password.change_password(req['current_password'], req['new_password'])
|
result = change_password.change_password(req['current_password'], req['new_password'])
|
||||||
|
@ -8,7 +8,7 @@ from flask_login import login_required
|
|||||||
|
|
||||||
import my_scrypt
|
import my_scrypt
|
||||||
from migration_api import APP_DB_VERSION
|
from migration_api import APP_DB_VERSION
|
||||||
from sql import getOption
|
from sql import get_option
|
||||||
|
|
||||||
|
|
||||||
class User(UserMixin):
|
class User(UserMixin):
|
||||||
@ -23,7 +23,7 @@ def init(app):
|
|||||||
login_manager.init_app(app)
|
login_manager.init_app(app)
|
||||||
login_manager.login_view = 'login_form'
|
login_manager.login_view = 'login_form'
|
||||||
|
|
||||||
user.id = getOption('username')
|
user.id = get_option('username')
|
||||||
|
|
||||||
|
|
||||||
routes = Blueprint('routes', __name__)
|
routes = Blueprint('routes', __name__)
|
||||||
@ -37,7 +37,7 @@ def login_form():
|
|||||||
@routes.route('/app', methods=['GET'])
|
@routes.route('/app', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def show_app():
|
def show_app():
|
||||||
db_version = int(getOption('db_version'))
|
db_version = int(get_option('db_version'))
|
||||||
|
|
||||||
if db_version < APP_DB_VERSION:
|
if db_version < APP_DB_VERSION:
|
||||||
return redirect('migration')
|
return redirect('migration')
|
||||||
@ -59,9 +59,9 @@ def logout():
|
|||||||
|
|
||||||
|
|
||||||
def verify_password(guessed_password):
|
def verify_password(guessed_password):
|
||||||
hashed_password = base64.b64decode(getOption('password_verification_hash'))
|
hashed_password = base64.b64decode(get_option('password_verification_hash'))
|
||||||
|
|
||||||
guess_hashed = my_scrypt.getVerificationHash(guessed_password)
|
guess_hashed = my_scrypt.get_verification_hash(guessed_password)
|
||||||
|
|
||||||
return guess_hashed == hashed_password
|
return guess_hashed == hashed_password
|
||||||
|
|
||||||
|
@ -6,29 +6,31 @@ import audit_category
|
|||||||
|
|
||||||
settings_api = Blueprint('settings_api', __name__)
|
settings_api = Blueprint('settings_api', __name__)
|
||||||
|
|
||||||
allowed_options = [ 'encryption_session_timeout', 'history_snapshot_time_interval' ]
|
ALLOWED_OPTIONS = ['encryption_session_timeout', 'history_snapshot_time_interval']
|
||||||
|
|
||||||
|
|
||||||
@settings_api.route('/api/settings', methods = ['GET'])
|
@settings_api.route('/api/settings', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def get_settings():
|
def get_settings():
|
||||||
dict = {}
|
dict = {}
|
||||||
|
|
||||||
settings = sql.getResults("SELECT opt_name, opt_value FROM options WHERE opt_name IN (%s)" % ',' . join('?'*len(allowed_options)), allowed_options)
|
settings = sql.getResults("SELECT opt_name, opt_value FROM options WHERE opt_name IN (%s)" % ',' . join('?' * len(ALLOWED_OPTIONS)), ALLOWED_OPTIONS)
|
||||||
|
|
||||||
for set in settings:
|
for set in settings:
|
||||||
dict[set['opt_name']] = set['opt_value']
|
dict[set['opt_name']] = set['opt_value']
|
||||||
|
|
||||||
return jsonify(dict)
|
return jsonify(dict)
|
||||||
|
|
||||||
|
|
||||||
@settings_api.route('/api/settings', methods = ['POST'])
|
@settings_api.route('/api/settings', methods = ['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def set_settings():
|
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.add_audit(audit_category.SETTINGS, request, None, sql.get_option(req['name']), req['value'], req['name'])
|
||||||
|
|
||||||
sql.setOption(req['name'], req['value'])
|
sql.set_option(req['name'], req['value'])
|
||||||
|
|
||||||
sql.commit()
|
sql.commit()
|
||||||
|
|
||||||
|
34
src/sql.py
34
src/sql.py
@ -1,13 +1,11 @@
|
|||||||
import base64
|
import base64
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
import math
|
|
||||||
import time
|
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
conn = None
|
conn = None
|
||||||
|
|
||||||
|
|
||||||
def dict_factory(cursor, row):
|
def dict_factory(cursor, row):
|
||||||
d = {}
|
d = {}
|
||||||
for idx, col in enumerate(cursor.description):
|
for idx, col in enumerate(cursor.description):
|
||||||
@ -18,27 +16,32 @@ def dict_factory(cursor, row):
|
|||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def connect(documentPath):
|
|
||||||
|
def connect(document_path):
|
||||||
global conn
|
global conn
|
||||||
conn = sqlite3.connect(documentPath)
|
conn = sqlite3.connect(document_path)
|
||||||
conn.row_factory = dict_factory
|
conn.row_factory = dict_factory
|
||||||
|
|
||||||
def insert(tablename, rec):
|
|
||||||
|
def insert(table_name, rec):
|
||||||
# FIXME: SQL injection!
|
# FIXME: SQL injection!
|
||||||
keys = ','.join(rec.keys())
|
keys = ','.join(rec.keys())
|
||||||
question_marks = ','.join(list('?' * len(rec)))
|
question_marks = ','.join(list('?' * len(rec)))
|
||||||
values = tuple(rec.values())
|
values = tuple(rec.values())
|
||||||
cursor = execute('INSERT INTO '+tablename+' ('+keys+') VALUES ('+question_marks+')', values)
|
cursor = execute('INSERT INTO ' + table_name + ' (' + keys + ') VALUES (' + question_marks + ')', values)
|
||||||
return cursor.lastrowid
|
return cursor.lastrowid
|
||||||
|
|
||||||
def setOption(name, value):
|
|
||||||
|
def set_option(name, value):
|
||||||
execute("UPDATE options SET opt_value = ? WHERE opt_name = ?", [value, name])
|
execute("UPDATE options SET opt_value = ? WHERE opt_name = ?", [value, name])
|
||||||
|
|
||||||
def getOption(name):
|
|
||||||
|
def get_option(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 = utils.nowTimestamp()
|
def add_audit(category, request=None, note_id=None, change_from=None, change_to=None, comment=None):
|
||||||
|
now = utils.now_timestamp()
|
||||||
|
|
||||||
browser_id = None
|
browser_id = None
|
||||||
|
|
||||||
@ -48,36 +51,43 @@ def addAudit(category, request = None, note_id = None, change_from = None, chang
|
|||||||
execute("INSERT INTO audit_log (date_modified, category, browser_id, note_id, change_from, change_to, comment)"
|
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])
|
" VALUES (?, ?, ?, ?, ?, ?, ?)", [now, category, browser_id, note_id, change_from, change_to, comment])
|
||||||
|
|
||||||
|
|
||||||
def deleteRecentAudits(category, request, note_id):
|
def deleteRecentAudits(category, request, note_id):
|
||||||
browser_id = request.headers['x-browser-id']
|
browser_id = request.headers['x-browser-id']
|
||||||
|
|
||||||
delete_cutoff = utils.nowTimestamp() - 10 * 60;
|
delete_cutoff = utils.now_timestamp() - 10 * 60;
|
||||||
|
|
||||||
execute("DELETE FROM audit_log WHERE category = ? AND browser_id = ? AND note_id = ? AND date_modified > ?",
|
execute("DELETE FROM audit_log WHERE category = ? AND browser_id = ? AND note_id = ? AND date_modified > ?",
|
||||||
[category, browser_id, note_id, delete_cutoff])
|
[category, browser_id, note_id, delete_cutoff])
|
||||||
|
|
||||||
|
|
||||||
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])
|
||||||
|
|
||||||
|
|
||||||
def execute(sql, params=[]):
|
def execute(sql, params=[]):
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(sql, params)
|
cursor.execute(sql, params)
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
|
|
||||||
def execute_script(sql):
|
def execute_script(sql):
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.executescript(sql)
|
cursor.executescript(sql)
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
|
|
||||||
def getResults(sql, params=[]):
|
def getResults(sql, params=[]):
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
query = cursor.execute(sql, params)
|
query = cursor.execute(sql, params)
|
||||||
return query.fetchall()
|
return query.fetchall()
|
||||||
|
|
||||||
|
|
||||||
def getSingleResult(sql, params=()):
|
def getSingleResult(sql, params=()):
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
query = cursor.execute(sql, params)
|
query = cursor.execute(sql, params)
|
||||||
return query.fetchone()
|
return query.fetchone()
|
||||||
|
|
||||||
|
|
||||||
def commit():
|
def commit():
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
@ -4,15 +4,16 @@ import os
|
|||||||
from flask import Blueprint, jsonify
|
from flask import Blueprint, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from sql import getResults, getSingleResult, getOption
|
from sql import getResults, getSingleResult, get_option
|
||||||
import utils
|
import utils
|
||||||
import backup
|
import backup
|
||||||
|
|
||||||
tree_api = Blueprint('tree_api', __name__)
|
tree_api = Blueprint('tree_api', __name__)
|
||||||
|
|
||||||
|
|
||||||
@tree_api.route('/api/tree', methods = ['GET'])
|
@tree_api.route('/api/tree', methods = ['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def getTree():
|
def get_tree():
|
||||||
backup.regular_backup()
|
backup.regular_backup()
|
||||||
|
|
||||||
notes = getResults("select "
|
notes = getResults("select "
|
||||||
@ -26,32 +27,32 @@ def getTree():
|
|||||||
"left join notes as clone on notes.note_clone_id = clone.note_id "
|
"left join notes as clone on notes.note_clone_id = clone.note_id "
|
||||||
"order by note_pid, note_pos")
|
"order by note_pid, note_pos")
|
||||||
|
|
||||||
rootNotes = []
|
root_notes = []
|
||||||
notesMap = {}
|
notes_map = {}
|
||||||
|
|
||||||
for note in notes:
|
for note in notes:
|
||||||
note['children'] = []
|
note['children'] = []
|
||||||
|
|
||||||
if not note['note_pid']:
|
if not note['note_pid']:
|
||||||
rootNotes.append(note)
|
root_notes.append(note)
|
||||||
|
|
||||||
notesMap[note['note_id']] = note
|
notes_map[note['note_id']] = note
|
||||||
|
|
||||||
for note in notes:
|
for note in notes:
|
||||||
if note['note_pid'] != "":
|
if note['note_pid'] != "":
|
||||||
parent = notesMap[note['note_pid']]
|
parent = notes_map[note['note_pid']]
|
||||||
|
|
||||||
parent['children'].append(note)
|
parent['children'].append(note)
|
||||||
parent['folder'] = True
|
parent['folder'] = True
|
||||||
|
|
||||||
retObject = {}
|
ret_object = {
|
||||||
retObject['notes'] = rootNotes
|
'notes': root_notes,
|
||||||
retObject['start_note_id'] = getSingleResult('select * from options where opt_name = "start_node"')['opt_value'];
|
'start_note_id': getSingleResult('select * from options where opt_name = "start_node"')['opt_value'],
|
||||||
retObject['password_verification_salt'] = getOption('password_verification_salt')
|
'password_verification_salt': get_option('password_verification_salt'),
|
||||||
retObject['password_derived_key_salt'] = getOption('password_derived_key_salt')
|
'password_derived_key_salt': get_option('password_derived_key_salt'),
|
||||||
retObject['encrypted_data_key'] = getOption('encrypted_data_key')
|
'encrypted_data_key': get_option('encrypted_data_key'),
|
||||||
retObject['encryption_session_timeout'] = getOption('encryption_session_timeout')
|
'encryption_session_timeout': get_option('encryption_session_timeout'),
|
||||||
retObject['browser_id'] = base64.b64encode(os.urandom(8))
|
'browser_id': base64.b64encode(os.urandom(8)), 'full_load_time': utils.now_timestamp()
|
||||||
retObject['full_load_time'] = utils.nowTimestamp()
|
}
|
||||||
|
|
||||||
return jsonify(retObject)
|
return jsonify(ret_object)
|
@ -1,5 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def nowTimestamp():
|
|
||||||
|
def now_timestamp():
|
||||||
return int(time.mktime(datetime.utcnow().timetuple()))
|
return int(time.mktime(datetime.utcnow().timetuple()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user