mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 21:11:30 +08:00 
			
		
		
		
	converted image and maintainance routes
This commit is contained in:
		
							parent
							
								
									e36a81e189
								
							
						
					
					
						commit
						aa57a64c61
					
				| @ -1,15 +1,11 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const anonymization = require('../../services/anonymization'); | const anonymization = require('../../services/anonymization'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.post('/anonymize', auth.checkApiAuth, wrap(async (req, res, next) => { | async function anonymize() { | ||||||
|     await anonymization.anonymize(); |     await anonymization.anonymize(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     res.send({}); | module.exports = { | ||||||
| })); |     anonymize | ||||||
| 
 | }; | ||||||
| module.exports = router; |  | ||||||
| @ -1,83 +1,73 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const utils = require('../../services/utils'); | const utils = require('../../services/utils'); | ||||||
| const sync_table = require('../../services/sync_table'); | const sync_table = require('../../services/sync_table'); | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const log = require('../../services/log'); | const log = require('../../services/log'); | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, wrap(async (req, res, next) => { | async function cleanupSoftDeletedItems() { | ||||||
|     await sql.doInTransaction(async () => { |     const noteIdsToDelete = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1"); | ||||||
|         const noteIdsToDelete = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1"); |     const noteIdsSql = noteIdsToDelete | ||||||
|         const noteIdsSql = noteIdsToDelete |         .map(noteId => "'" + utils.sanitizeSql(noteId) + "'") | ||||||
|             .map(noteId => "'" + utils.sanitizeSql(noteId) + "'") |         .join(', '); | ||||||
|             .join(', '); |  | ||||||
| 
 | 
 | ||||||
|         await sql.execute(`DELETE FROM event_log WHERE noteId IN (${noteIdsSql})`); |     await sql.execute(`DELETE FROM event_log WHERE noteId IN (${noteIdsSql})`); | ||||||
| 
 | 
 | ||||||
|         await sql.execute(`DELETE FROM note_revisions WHERE noteId IN (${noteIdsSql})`); |     await sql.execute(`DELETE FROM note_revisions WHERE noteId IN (${noteIdsSql})`); | ||||||
| 
 | 
 | ||||||
|         await sql.execute(`DELETE FROM note_images WHERE noteId IN (${noteIdsSql})`); |     await sql.execute(`DELETE FROM note_images WHERE noteId IN (${noteIdsSql})`); | ||||||
| 
 | 
 | ||||||
|         await sql.execute(`DELETE FROM labels WHERE noteId IN (${noteIdsSql})`); |     await sql.execute(`DELETE FROM labels WHERE noteId IN (${noteIdsSql})`); | ||||||
| 
 | 
 | ||||||
|         await sql.execute("DELETE FROM branches WHERE isDeleted = 1"); |     await sql.execute("DELETE FROM branches WHERE isDeleted = 1"); | ||||||
| 
 | 
 | ||||||
|         await sql.execute("DELETE FROM note_images WHERE isDeleted = 1"); |     await sql.execute("DELETE FROM note_images WHERE isDeleted = 1"); | ||||||
| 
 | 
 | ||||||
|         await sql.execute("DELETE FROM images WHERE isDeleted = 1"); |     await sql.execute("DELETE FROM images WHERE isDeleted = 1"); | ||||||
| 
 | 
 | ||||||
|         await sql.execute("DELETE FROM notes WHERE isDeleted = 1"); |     await sql.execute("DELETE FROM notes WHERE isDeleted = 1"); | ||||||
| 
 | 
 | ||||||
|         await sql.execute("DELETE FROM recent_notes"); |     await sql.execute("DELETE FROM recent_notes"); | ||||||
| 
 | 
 | ||||||
|         await sync_table.cleanupSyncRowsForMissingEntities("notes", "noteId"); |     await sync_table.cleanupSyncRowsForMissingEntities("notes", "noteId"); | ||||||
|         await sync_table.cleanupSyncRowsForMissingEntities("branches", "branchId"); |     await sync_table.cleanupSyncRowsForMissingEntities("branches", "branchId"); | ||||||
|         await sync_table.cleanupSyncRowsForMissingEntities("note_revisions", "noteRevisionId"); |     await sync_table.cleanupSyncRowsForMissingEntities("note_revisions", "noteRevisionId"); | ||||||
|         await sync_table.cleanupSyncRowsForMissingEntities("recent_notes", "branchId"); |     await sync_table.cleanupSyncRowsForMissingEntities("recent_notes", "branchId"); | ||||||
| 
 | 
 | ||||||
|         log.info("Following notes has been completely cleaned from database: " + noteIdsSql); |     log.info("Following notes has been completely cleaned from database: " + noteIdsSql); | ||||||
|     }); | } | ||||||
| 
 | 
 | ||||||
|     res.send({}); | async function cleanupUnusedImages() { | ||||||
| })); |  | ||||||
| 
 |  | ||||||
| router.post('/cleanup-unused-images', auth.checkApiAuth, wrap(async (req, res, next) => { |  | ||||||
|     const sourceId = req.headers.source_id; |     const sourceId = req.headers.source_id; | ||||||
| 
 | 
 | ||||||
|     await sql.doInTransaction(async () => { |     const unusedImageIds = await sql.getColumn(` | ||||||
|         const unusedImageIds = await sql.getColumn(` |       SELECT images.imageId  | ||||||
|           SELECT images.imageId  |       FROM images  | ||||||
|           FROM images  |         LEFT JOIN note_images ON note_images.imageId = images.imageId AND note_images.isDeleted = 0 | ||||||
|             LEFT JOIN note_images ON note_images.imageId = images.imageId AND note_images.isDeleted = 0 |       WHERE | ||||||
|           WHERE |         images.isDeleted = 0 | ||||||
|             images.isDeleted = 0 |         AND note_images.noteImageId IS NULL`);
 | ||||||
|             AND note_images.noteImageId IS NULL`);
 |  | ||||||
| 
 | 
 | ||||||
|         const now = utils.nowDate(); |     const now = utils.nowDate(); | ||||||
| 
 | 
 | ||||||
|         for (const imageId of unusedImageIds) { |     for (const imageId of unusedImageIds) { | ||||||
|             log.info(`Deleting unused image: ${imageId}`); |         log.info(`Deleting unused image: ${imageId}`); | ||||||
| 
 | 
 | ||||||
|             await sql.execute("UPDATE images SET isDeleted = 1, data = null, dateModified = ? WHERE imageId = ?", |         await sql.execute("UPDATE images SET isDeleted = 1, data = null, dateModified = ? WHERE imageId = ?", | ||||||
|                 [now, imageId]); |             [now, imageId]); | ||||||
| 
 | 
 | ||||||
|             await sync_table.addImageSync(imageId, sourceId); |         await sync_table.addImageSync(imageId, sourceId); | ||||||
|         } |     } | ||||||
|     }); | } | ||||||
| 
 | 
 | ||||||
|     res.send({}); | async function vacuumDatabase() { | ||||||
| })); |  | ||||||
| 
 |  | ||||||
| router.post('/vacuum-database', auth.checkApiAuth, wrap(async (req, res, next) => { |  | ||||||
|     await sql.execute("VACUUM"); |     await sql.execute("VACUUM"); | ||||||
| 
 | 
 | ||||||
|     log.info("Database has been vacuumed."); |     log.info("Database has been vacuumed."); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     res.send({}); | module.exports = { | ||||||
| })); |     cleanupSoftDeletedItems, | ||||||
| 
 |     cleanupUnusedImages, | ||||||
| module.exports = router; |     vacuumDatabase | ||||||
|  | }; | ||||||
| @ -10,7 +10,7 @@ const wrap = require('express-promise-wrap').wrap; | |||||||
| const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; | const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; | ||||||
| const fs = require('fs'); | const fs = require('fs'); | ||||||
| 
 | 
 | ||||||
| router.get('/:imageId/:filename', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => { | async function returnImage(req, res) { | ||||||
|     const image = await sql.getRow("SELECT * FROM images WHERE imageId = ?", [req.params.imageId]); |     const image = await sql.getRow("SELECT * FROM images WHERE imageId = ?", [req.params.imageId]); | ||||||
| 
 | 
 | ||||||
|     if (!image) { |     if (!image) { | ||||||
| @ -24,9 +24,9 @@ router.get('/:imageId/:filename', auth.checkApiAuthOrElectron, wrap(async (req, | |||||||
|     res.set('Content-Type', 'image/' + image.format); |     res.set('Content-Type', 'image/' + image.format); | ||||||
| 
 | 
 | ||||||
|     res.send(image.data); |     res.send(image.data); | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| router.post('', auth.checkApiAuthOrElectron, multer.single('upload'), wrap(async (req, res, next) => { | async function uploadImage(req, res) { | ||||||
|     const sourceId = req.headers.source_id; |     const sourceId = req.headers.source_id; | ||||||
|     const noteId = req.query.noteId; |     const noteId = req.query.noteId; | ||||||
|     const file = req.file; |     const file = req.file; | ||||||
| @ -47,6 +47,9 @@ router.post('', auth.checkApiAuthOrElectron, multer.single('upload'), wrap(async | |||||||
|         uploaded: true, |         uploaded: true, | ||||||
|         url: `/api/images/${imageId}/${fileName}` |         url: `/api/images/${imageId}/${fileName}` | ||||||
|     }); |     }); | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     returnImage, | ||||||
|  |     uploadImage | ||||||
|  | }; | ||||||
| @ -1,33 +1,27 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const options = require('../../services/options'); | const options = require('../../services/options'); | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const utils = require('../../services/utils'); | const utils = require('../../services/utils'); | ||||||
| const my_scrypt = require('../../services/my_scrypt'); | const my_scrypt = require('../../services/my_scrypt'); | ||||||
| const password_encryption = require('../../services/password_encryption'); | const password_encryption = require('../../services/password_encryption'); | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.post('', auth.checkAppNotInitialized, wrap(async (req, res, next) => { | async function setup(req) { | ||||||
|     const { username, password } = req.body; |     const { username, password } = req.body; | ||||||
| 
 | 
 | ||||||
|     await sql.doInTransaction(async () => { |     await options.setOption('username', username); | ||||||
|         await options.setOption('username', username); |  | ||||||
| 
 | 
 | ||||||
|         await options.setOption('password_verification_salt', utils.randomSecureToken(32)); |     await options.setOption('password_verification_salt', utils.randomSecureToken(32)); | ||||||
|         await options.setOption('password_derived_key_salt', utils.randomSecureToken(32)); |     await options.setOption('password_derived_key_salt', utils.randomSecureToken(32)); | ||||||
| 
 | 
 | ||||||
|         const passwordVerificationKey = utils.toBase64(await my_scrypt.getVerificationHash(password)); |     const passwordVerificationKey = utils.toBase64(await my_scrypt.getVerificationHash(password)); | ||||||
|         await options.setOption('password_verification_hash', passwordVerificationKey); |     await options.setOption('password_verification_hash', passwordVerificationKey); | ||||||
| 
 | 
 | ||||||
|         await password_encryption.setDataKey(password, utils.randomSecureToken(16)); |     await password_encryption.setDataKey(password, utils.randomSecureToken(16)); | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|     sql.setDbReadyAsResolved(); |     sql.setDbReadyAsResolved(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     res.send({}); | module.exports = { | ||||||
| })); |     setup | ||||||
| 
 | }; | ||||||
| module.exports = router; |  | ||||||
| @ -1,26 +1,24 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| const express = require('express'); |  | ||||||
| const router = express.Router(); |  | ||||||
| const auth = require('../../services/auth'); |  | ||||||
| const sql = require('../../services/sql'); | const sql = require('../../services/sql'); | ||||||
| const wrap = require('express-promise-wrap').wrap; |  | ||||||
| 
 | 
 | ||||||
| router.post('/execute', auth.checkApiAuth, wrap(async (req, res, next) => { | async function execute(req) { | ||||||
|     const query = req.body.query; |     const query = req.body.query; | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|         res.send({ |         return { | ||||||
|             success: true, |             success: true, | ||||||
|             rows: await sql.getRows(query) |             rows: await sql.getRows(query) | ||||||
|         }); |         }; | ||||||
|     } |     } | ||||||
|     catch (e) { |     catch (e) { | ||||||
|         res.send({ |         return { | ||||||
|             success: false, |             success: false, | ||||||
|             error: e.message |             error: e.message | ||||||
|         }); |         }; | ||||||
|     } |     } | ||||||
| })); | } | ||||||
| 
 | 
 | ||||||
| module.exports = router; | module.exports = { | ||||||
|  |     execute | ||||||
|  | }; | ||||||
| @ -40,44 +40,35 @@ const auth = require('../services/auth'); | |||||||
| const cls = require('../services/cls'); | const cls = require('../services/cls'); | ||||||
| const sql = require('../services/sql'); | const sql = require('../services/sql'); | ||||||
| 
 | 
 | ||||||
| function apiRoute(method, path, routeHandler) { | function apiResultHandler(res, result) { | ||||||
|     route({ |     // if it's an array and first element is integer then we consider this to be [statusCode, response] format
 | ||||||
|         method, |     if (Array.isArray(result) && result.length > 0 && Number.isInteger(result[0])) { | ||||||
|         path, |         const [statusCode, response] = result; | ||||||
|         middleware: [auth.checkApiAuth], |  | ||||||
|         routeHandler, |  | ||||||
|         resultHandler: (res, result) => { |  | ||||||
|             // if it's an array and first element is integer then we consider this to be [statusCode, response] format
 |  | ||||||
|             if (Array.isArray(result) && result.length > 0 && Number.isInteger(result[0])) { |  | ||||||
|                 const [statusCode, response] = result; |  | ||||||
| 
 | 
 | ||||||
|                 res.status(statusCode).send(response); |         res.status(statusCode).send(response); | ||||||
| 
 | 
 | ||||||
|                 if (statusCode !== 200) { |         if (statusCode !== 200) { | ||||||
|                     log.info(`${method} ${path} returned ${statusCode} with response ${JSON.stringify(response)}`); |             log.info(`${method} ${path} returned ${statusCode} with response ${JSON.stringify(response)}`); | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else if (result === undefined) { |  | ||||||
|                 res.status(200).send(); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 res.status(200).send(result); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     }); |     } | ||||||
|  |     else if (result === undefined) { | ||||||
|  |         res.status(200).send(); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         res.status(200).send(result); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function apiRoute(method, path, routeHandler) { | ||||||
|  |     route(method, path, [auth.checkApiAuth], routeHandler, apiResultHandler); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // API routes requiring HTTP protocol. This means we ignore route return value and make an electron auth exception
 | // API routes requiring HTTP protocol. This means we ignore route return value and make an electron auth exception
 | ||||||
| function httpApiRoute(method, path, routeHandler) { | function httpApiRoute(method, path, routeHandler) { | ||||||
|     route({ |     route(method, path, [auth.checkApiAuth, multer.single('upload')], routeHandler); | ||||||
|         method, |  | ||||||
|         path, |  | ||||||
|         middleware: [auth.checkApiAuth, multer.single('upload')], |  | ||||||
|         routeHandler |  | ||||||
|     }) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function route({ method, path, middleware, routeHandler, resultHandler }) { | function route(method, path, middleware, routeHandler, resultHandler) { | ||||||
|     router[method](path, ...middleware, async (req, res, next) => { |     router[method](path, ...middleware, async (req, res, next) => { | ||||||
|         try { |         try { | ||||||
|             const result = await cls.init(async () => { |             const result = await cls.init(async () => { | ||||||
| @ -176,14 +167,19 @@ function register(app) { | |||||||
|     apiRoute(GET, '/api/app-info', appInfoRoute.getAppInfo); |     apiRoute(GET, '/api/app-info', appInfoRoute.getAppInfo); | ||||||
| 
 | 
 | ||||||
|     httpApiRoute(GET, '/api/export/:noteId', exportRoute.exportNote); |     httpApiRoute(GET, '/api/export/:noteId', exportRoute.exportNote); | ||||||
| 
 |  | ||||||
|     httpApiRoute(POST, '/api/import/:parentNoteId', importRoute.importTar); |     httpApiRoute(POST, '/api/import/:parentNoteId', importRoute.importTar); | ||||||
| 
 | 
 | ||||||
|     app.use('/api/setup', setupApiRoute); |     route(POST, '/api/setup', [auth.checkAppNotInitialized], setupApiRoute.setup, apiResultHandler); | ||||||
|     app.use('/api/sql', sqlRoute); | 
 | ||||||
|     app.use('/api/anonymization', anonymizationRoute); |     apiRoute(POST, '/api/sql/execute', sqlRoute.execute); | ||||||
|     app.use('/api/cleanup', cleanupRoute); |     apiRoute(POST, '/api/anonymization/anonymize', anonymizationRoute.anonymize); | ||||||
|     app.use('/api/images', imageRoute); | 
 | ||||||
|  |     apiRoute(POST, '/api/cleanup/cleanup-soft-deleted-items', cleanupRoute.cleanupSoftDeletedItems); | ||||||
|  |     apiRoute(POST, '/api/cleanup/cleanup-unused-images', cleanupRoute.cleanupUnusedImages); | ||||||
|  |     apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase); | ||||||
|  | 
 | ||||||
|  |     httpApiRoute(GET, '/api/images/:imageId/:filename', imageRoute.returnImage); | ||||||
|  |     httpApiRoute(POST, '/api/images', imageRoute.uploadImage); | ||||||
|     app.use('/api/script', scriptRoute); |     app.use('/api/script', scriptRoute); | ||||||
|     app.use('/api/sender', senderRoute); |     app.use('/api/sender', senderRoute); | ||||||
|     app.use('/api/files', filesRoute); |     app.use('/api/files', filesRoute); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 azivner
						azivner