relation between notes and images

This commit is contained in:
azivner 2018-01-06 21:49:02 -05:00
parent 784cd62df1
commit c0e45a73a8
12 changed files with 117 additions and 7 deletions

View File

@ -0,0 +1,16 @@
DROP TABLE images;
CREATE TABLE images
(
image_id TEXT PRIMARY KEY NOT NULL,
note_id TEXT NOT NULL,
format TEXT NOT NULL,
checksum TEXT NOT NULL,
name TEXT NOT NULL,
data BLOB,
is_deleted INT NOT NULL DEFAULT 0,
date_modified TEXT NOT NULL,
date_created TEXT NOT NULL
);
CREATE INDEX images_note_id_index ON images (note_id);

View File

@ -0,0 +1,26 @@
DROP TABLE images;
CREATE TABLE images
(
image_id TEXT PRIMARY KEY NOT NULL,
format TEXT NOT NULL,
checksum TEXT NOT NULL,
name TEXT NOT NULL,
data BLOB,
is_deleted INT NOT NULL DEFAULT 0,
date_modified TEXT NOT NULL,
date_created TEXT NOT NULL
);
CREATE TABLE notes_image
(
note_image_id TEXT PRIMARY KEY NOT NULL,
note_id TEXT NOT NULL,
image_id TEXT NOT NULL,
is_deleted INT NOT NULL DEFAULT 0,
date_modified TEXT NOT NULL,
date_created TEXT NOT NULL
);
CREATE INDEX notes_image_note_id_index ON notes_image (note_id);
CREATE INDEX notes_image_note_id_image_id_index ON notes_image (note_id, image_id);

File diff suppressed because one or more lines are too long

View File

@ -24,11 +24,16 @@ router.get('/:imageId/:filename', auth.checkApiAuth, async (req, res, next) => {
res.send(image.data); res.send(image.data);
}); });
router.post('/upload', auth.checkApiAuth, multer.single('upload'), async (req, res, next) => { router.post('', auth.checkApiAuth, multer.single('upload'), async (req, res, next) => {
const sourceId = req.headers.source_id; const sourceId = req.headers.source_id;
const noteId = req.query.noteId;
const file = req.file; const file = req.file;
const imageId = utils.newNoteId(); const note = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId]);
if (!note) {
return req.status(404).send(`Note ${noteId} doesn't exist.`);
}
if (!file.mimetype.startsWith("image/")) { if (!file.mimetype.startsWith("image/")) {
return req.send("Unknown image type: " + file.mimetype); return req.send("Unknown image type: " + file.mimetype);
@ -39,6 +44,8 @@ router.post('/upload', auth.checkApiAuth, multer.single('upload'), async (req, r
const resizedImage = await resize(file.buffer); const resizedImage = await resize(file.buffer);
const optimizedImage = await optimize(resizedImage); const optimizedImage = await optimize(resizedImage);
const imageId = utils.newImageId();
await sql.doInTransaction(async () => { await sql.doInTransaction(async () => {
await sql.insert("images", { await sql.insert("images", {
image_id: imageId, image_id: imageId,
@ -52,11 +59,24 @@ router.post('/upload', auth.checkApiAuth, multer.single('upload'), async (req, r
}); });
await sync_table.addImageSync(imageId, sourceId); await sync_table.addImageSync(imageId, sourceId);
const noteImageId = utils.newNoteImageId();
await sql.insert("notes_image", {
note_image_id: noteImageId,
note_id: noteId,
image_id: imageId,
is_deleted: 0,
date_modified: now,
date_created: now
});
await sync_table.addNoteImageSync(noteImageId, sourceId);
}); });
res.send({ res.send({
uploaded: true, uploaded: true,
url: `/api/image/${imageId}/${file.originalname}` url: `/api/images/${imageId}/${file.originalname}`
}); });
}); });

View File

@ -133,6 +133,12 @@ router.get('/images/:imageId', auth.checkApiAuth, async (req, res, next) => {
res.send(entity); res.send(entity);
}); });
router.get('/notes_image/:noteImageId', auth.checkApiAuth, async (req, res, next) => {
const noteImageId = req.params.noteImageId;
res.send(await sql.getFirst("SELECT * FROM notes_image WHERE note_image_id = ?", [noteImageId]));
});
router.put('/notes', auth.checkApiAuth, async (req, res, next) => { router.put('/notes', auth.checkApiAuth, async (req, res, next) => {
await syncUpdate.updateNote(req.body.entity, req.body.sourceId); await syncUpdate.updateNote(req.body.entity, req.body.sourceId);
@ -175,4 +181,10 @@ router.put('/images', auth.checkApiAuth, async (req, res, next) => {
res.send({}); res.send({});
}); });
router.put('/notes_image', auth.checkApiAuth, async (req, res, next) => {
await syncUpdate.updateNoteImage(req.body.entity, req.body.sourceId);
res.send({});
});
module.exports = router; module.exports = router;

View File

@ -52,7 +52,7 @@ function register(app) {
app.use('/api/sql', sqlRoute); app.use('/api/sql', sqlRoute);
app.use('/api/anonymization', anonymizationRoute); app.use('/api/anonymization', anonymizationRoute);
app.use('/api/cleanup', cleanupRoute); app.use('/api/cleanup', cleanupRoute);
app.use('/api/image', imageRoute); app.use('/api/images', imageRoute);
} }
module.exports = { module.exports = {

View File

@ -3,7 +3,7 @@
const build = require('./build'); const build = require('./build');
const packageJson = require('../package'); const packageJson = require('../package');
const APP_DB_VERSION = 63; const APP_DB_VERSION = 65;
module.exports = { module.exports = {
app_version: packageJson.version, app_version: packageJson.version,

View File

@ -181,6 +181,8 @@ async function runAllChecks() {
await runSyncRowChecks("notes_history", "note_history_id", errorList); await runSyncRowChecks("notes_history", "note_history_id", errorList);
await runSyncRowChecks("notes_tree", "note_tree_id", errorList); await runSyncRowChecks("notes_tree", "note_tree_id", errorList);
await runSyncRowChecks("recent_notes", "note_tree_id", errorList); await runSyncRowChecks("recent_notes", "note_tree_id", errorList);
await runSyncRowChecks("images", "image_id", errorList);
await runSyncRowChecks("notes_image", "note_image_id", errorList);
if (errorList.length === 0) { if (errorList.length === 0) {
// we run this only if basic checks passed since this assumes basic data consistency // we run this only if basic checks passed since this assumes basic data consistency

View File

@ -224,6 +224,9 @@ async function pushEntity(sync, syncContext) {
entity.data = entity.data.toString('base64'); entity.data = entity.data.toString('base64');
} }
} }
else if (sync.entity_name === 'notes_image') {
entity = await sql.getFirst('SELECT * FROM notes_image WHERE note_image_id = ?', [sync.entity_id]);
}
else { else {
throw new Error(`Unrecognized entity type ${sync.entity_name} in sync #${sync.id}`); throw new Error(`Unrecognized entity type ${sync.entity_name} in sync #${sync.id}`);
} }

View File

@ -32,6 +32,10 @@ async function addImageSync(imageId, sourceId) {
await addEntitySync("images", imageId, sourceId); await addEntitySync("images", imageId, sourceId);
} }
async function addNoteImageSync(imageId, sourceId) {
await addEntitySync("notes_image", imageId, sourceId);
}
async function addEntitySync(entityName, entityId, sourceId) { async function addEntitySync(entityName, entityId, sourceId) {
await sql.replace("sync", { await sql.replace("sync", {
entity_name: entityName, entity_name: entityName,
@ -83,6 +87,7 @@ async function fillAllSyncRows() {
await fillSyncRows("notes_history", "note_history_id"); await fillSyncRows("notes_history", "note_history_id");
await fillSyncRows("recent_notes", "note_tree_id"); await fillSyncRows("recent_notes", "note_tree_id");
await fillSyncRows("images", "image_id"); await fillSyncRows("images", "image_id");
await fillSyncRows("notes_image", "note_image_id");
} }
module.exports = { module.exports = {
@ -93,6 +98,7 @@ module.exports = {
addOptionsSync, addOptionsSync,
addRecentNoteSync, addRecentNoteSync,
addImageSync, addImageSync,
addNoteImageSync,
cleanupSyncRowsForMissingEntities, cleanupSyncRowsForMissingEntities,
fillAllSyncRows fillAllSyncRows
}; };

View File

@ -110,6 +110,20 @@ async function updateImage(entity, sourceId) {
} }
} }
async function updateNoteImage(entity, sourceId) {
const origNoteImage = await sql.getFirst("SELECT * FROM notes_image WHERE note_image_id = ?", [entity.note_image_id]);
if (!origNoteImage || origNoteImage.date_modified <= entity.date_modified) {
await sql.doInTransaction(async () => {
await sql.replace("notes_image", entity);
await sync_table.addNoteImageSync(entity.note_image_id, sourceId);
});
log.info("Update/sync note image " + entity.note_image_id);
}
}
module.exports = { module.exports = {
updateNote, updateNote,
updateNoteTree, updateNoteTree,
@ -117,5 +131,6 @@ module.exports = {
updateNoteReordering, updateNoteReordering,
updateOptions, updateOptions,
updateRecentNotes, updateRecentNotes,
updateImage updateImage,
updateNoteImage
}; };

View File

@ -15,6 +15,14 @@ function newNoteHistoryId() {
return randomString(12); return randomString(12);
} }
function newImageId() {
return randomString(12);
}
function newNoteImageId() {
return randomString(12);
}
function randomString(length) { function randomString(length) {
return randtoken.generate(length); return randtoken.generate(length);
} }
@ -96,6 +104,8 @@ module.exports = {
newNoteId, newNoteId,
newNoteTreeId, newNoteTreeId,
newNoteHistoryId, newNoteHistoryId,
newImageId,
newNoteImageId,
toBase64, toBase64,
fromBase64, fromBase64,
hmac, hmac,