mirror of
https://github.com/zadam/trilium.git
synced 2024-12-25 16:51:16 +08:00
API auth (untested)
This commit is contained in:
parent
eb6f9f8f81
commit
c28b7775a5
4 changed files with 73 additions and 15 deletions
2
app.js
2
app.js
|
@ -27,6 +27,7 @@ const settingsApiRoute = require('./routes/api/settings');
|
|||
const passwordApiRoute = require('./routes/api/password');
|
||||
const migrationApiRoute = require('./routes/api/migration');
|
||||
const syncApiRoute = require('./routes/api/sync');
|
||||
const loginApiRoute = require('./routes/api/login');
|
||||
|
||||
const dataDir = require('./services/data_dir');
|
||||
const sessionSecret = require('./services/session_secret');
|
||||
|
@ -94,6 +95,7 @@ app.use('/api/settings', settingsApiRoute);
|
|||
app.use('/api/password', passwordApiRoute);
|
||||
app.use('/api/migration', migrationApiRoute);
|
||||
app.use('/api/sync', syncApiRoute);
|
||||
app.use('/api/login', loginApiRoute);
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use((req, res, next) => {
|
||||
|
|
|
@ -2,17 +2,43 @@
|
|||
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const auth = require('../../services/auth');
|
||||
const sql = require('../../services/sql');
|
||||
const migration = require('../../services/migration');
|
||||
const utils = require('../../services/utils');
|
||||
const crypto = require('crypto');
|
||||
|
||||
router.post('', async (req, res, next) => {
|
||||
const timestamp = req.body.timestamp;
|
||||
|
||||
const now = utils.nowTimestamp();
|
||||
|
||||
res.send({
|
||||
'db_version': parseInt(await sql.getOption('db_version')),
|
||||
'app_db_version': migration.APP_DB_VERSION
|
||||
});
|
||||
if (Math.abs(timestamp - now) > 5) {
|
||||
res.status(400);
|
||||
res.send({ message: 'Auth request time is out of sync' });
|
||||
}
|
||||
|
||||
const dbVersion = res.body.dbVersion;
|
||||
|
||||
if (dbVersion !== migration.APP_DB_VERSION) {
|
||||
res.status(400);
|
||||
res.send({ message: 'Non-matching db versions, local is version ' + migration.APP_DB_VERSION });
|
||||
}
|
||||
|
||||
const documentSecret = await sql.getOption('document_secret');
|
||||
|
||||
const hmac = crypto.createHmac('sha256', documentSecret);
|
||||
hmac.update(timestamp);
|
||||
const expectedHash = hmac.digest('base64');
|
||||
|
||||
const givenHash = req.body.hash;
|
||||
|
||||
if (expectedHash !== givenHash) {
|
||||
res.status(400);
|
||||
res.send({ message: "Hash doesn't match" });
|
||||
}
|
||||
|
||||
req.session.loggedIn = true;
|
||||
|
||||
res.send({});
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -25,7 +25,7 @@ async function checkAuthWithoutMigration(req, res, next) {
|
|||
}
|
||||
|
||||
async function checkApiAuth(req, res, next) {
|
||||
if (!req.session.loggedIn && req.header("auth") !== "sync") {
|
||||
if (!req.session.loggedIn) {
|
||||
res.sendStatus(401);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ async function checkApiAuth(req, res, next) {
|
|||
}
|
||||
|
||||
async function checkApiAuthWithoutMigration(req, res, next) {
|
||||
if (!req.session.loggedIn && req.header("auth") !== "sync") {
|
||||
if (!req.session.loggedIn) {
|
||||
res.sendStatus(401);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -7,13 +7,14 @@ const migration = require('./migration');
|
|||
const utils = require('./utils');
|
||||
const config = require('./config');
|
||||
const audit_category = require('./audit_category');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const SYNC_SERVER = config['Sync']['syncServerHost'];
|
||||
|
||||
|
||||
let syncInProgress = false;
|
||||
|
||||
async function pullSync() {
|
||||
async function pullSync(cookieJar) {
|
||||
const lastSyncedPull = parseInt(await sql.getOption('last_synced_pull'));
|
||||
|
||||
const resp = await rp({
|
||||
|
@ -35,7 +36,8 @@ async function pullSync() {
|
|||
headers: {
|
||||
auth: 'sync'
|
||||
},
|
||||
json: true
|
||||
json: true,
|
||||
jar: cookieJar
|
||||
});
|
||||
|
||||
|
||||
|
@ -53,7 +55,7 @@ async function pullSync() {
|
|||
}
|
||||
}
|
||||
|
||||
async function pushSync() {
|
||||
async function pushSync(cookieJar) {
|
||||
const lastSyncedPush = parseInt(await sql.getOption('last_synced_push'));
|
||||
const syncStarted = utils.nowTimestamp();
|
||||
|
||||
|
@ -66,7 +68,8 @@ async function pushSync() {
|
|||
auth: 'sync'
|
||||
},
|
||||
body: changed,
|
||||
json: true
|
||||
json: true,
|
||||
jar: cookieJar
|
||||
});
|
||||
|
||||
for (const noteId of changed.notes) {
|
||||
|
@ -79,13 +82,38 @@ async function pushSync() {
|
|||
auth: 'sync'
|
||||
},
|
||||
body: note,
|
||||
json: true
|
||||
json: true,
|
||||
jar: cookieJar
|
||||
});
|
||||
}
|
||||
|
||||
await sql.setOption('last_synced_push', syncStarted);
|
||||
}
|
||||
|
||||
async function login() {
|
||||
const timestamp = utils.nowTimestamp();
|
||||
|
||||
const hmac = crypto.createHmac('sha256', documentSecret);
|
||||
hmac.update(timestamp);
|
||||
const hash = hmac.digest('base64');
|
||||
|
||||
const cookieJar = rp.jar();
|
||||
|
||||
await rp({
|
||||
method: 'POST',
|
||||
uri: SYNC_SERVER + '/api/login',
|
||||
body: {
|
||||
timestamp: timestamp,
|
||||
dbVersion: migration.APP_DB_VERSION,
|
||||
hash: hash
|
||||
},
|
||||
json: true,
|
||||
jar: cookieJar
|
||||
});
|
||||
|
||||
return cookieJar;
|
||||
}
|
||||
|
||||
async function sync() {
|
||||
if (syncInProgress) {
|
||||
return;
|
||||
|
@ -98,9 +126,11 @@ async function sync() {
|
|||
return;
|
||||
}
|
||||
|
||||
await pushSync();
|
||||
const cookieJar = await login();
|
||||
|
||||
await pullSync();
|
||||
await pushSync(cookieJar);
|
||||
|
||||
await pullSync(cookieJar);
|
||||
}
|
||||
catch (e) {
|
||||
log.error("sync failed: " + e.stack);
|
||||
|
|
Loading…
Reference in a new issue