-
Notifications
You must be signed in to change notification settings - Fork 21
Electron support #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Electron support #68
Changes from all commits
a34b5f2
e3bd2d6
ffcac70
27a7437
902b77d
12096e0
5b05194
c4c2acc
c4ecda0
96897d6
fd8e0ea
c0088ee
af85e08
5c2008a
c1d8372
d64ba13
df8c0be
2665975
596adfc
2b43606
4b738d5
dcb98a8
b7deaca
32a2b3f
4435480
97025db
9d4b36a
fbee2f0
45bcb61
b5534d2
0d40fa9
5fe2934
0ed84a3
fdb912e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,3 +88,5 @@ gradle-app.setting | |
| .vs/ | ||
| # generated by bob | ||
| lib/ | ||
|
|
||
| .vscode | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| module.exports = { | ||
| presets: ["module:@react-native/babel-preset"] | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export declare const db: { | ||
| main: { | ||
| init(): void; | ||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,328 @@ | ||||||||||||||||||||||||||||||
| import { ipcMain, app } from "electron"; | ||||||||||||||||||||||||||||||
| import sqlite3 from "@journeyapps/sqlcipher"; | ||||||||||||||||||||||||||||||
| import path from "path"; | ||||||||||||||||||||||||||||||
| import { existsSync, unlinkSync } from "fs"; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @import {Database, Statement, RunResult} from "@journeyapps/sqlcipher" | ||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||
| * @typedef {object} RunResultWithRows | ||||||||||||||||||||||||||||||
| * @prop {number} lastID | ||||||||||||||||||||||||||||||
| * @prop {number} changes | ||||||||||||||||||||||||||||||
| * @prop {Array<any>} rows | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| class SQLite { | ||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @type {Map<string, AsyncDatabase>} | ||||||||||||||||||||||||||||||
| * @private | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| #databases = new Map(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @type {string} | ||||||||||||||||||||||||||||||
| * @private | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| #dbLocation = app.getPath("userData"); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Event} event | ||||||||||||||||||||||||||||||
| * @param {{name: string, key: string}} options | ||||||||||||||||||||||||||||||
| * @returns {Promise<void>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| open = async (event, options) => { | ||||||||||||||||||||||||||||||
| const openPath = path.resolve(path.join(this.#dbLocation, options.name)); | ||||||||||||||||||||||||||||||
| const db = await AsyncDatabase.newDatabase(openPath); | ||||||||||||||||||||||||||||||
| if (options.key) { | ||||||||||||||||||||||||||||||
| await db.run(`PRAGMA key = '${options.key}'`); | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Encryption keys containing single quotes break database openingThe encryption key is directly interpolated into the PRAGMA statement without escaping single quotes. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: SQL injection vulnerability in database key parameterThe encryption key is interpolated directly into the SQL string using template literals without sanitization. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: SQL injection via unsanitized key in PRAGMAThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SQL injection vulnerability in PRAGMA key statementMedium Severity The encryption key is directly interpolated into the SQL string using template literals: |
||||||||||||||||||||||||||||||
| await db.run("PRAGMA cipher_migrate"); | ||||||||||||||||||||||||||||||
|
Comment on lines
+37
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SQL injection in PRAGMA key. String interpolation in Unfortunately, SQLite PRAGMA statements don't support bound parameters. Instead, validate and escape the key: if (options.key) {
- await db.run(`PRAGMA key = '${options.key}'`);
+ const key = String(options.key).replace(/'/g, "''");
+ await db.run(`PRAGMA key = '${key}'`);
await db.run("PRAGMA cipher_migrate");
}Better yet, validate that the key doesn't contain quotes: if (options.key) {
+ if (typeof options.key !== 'string' || options.key.includes("'")) {
+ throw new Error("Invalid key format");
+ }
await db.run(`PRAGMA key = '${options.key}'`);
await db.run("PRAGMA cipher_migrate");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| this.#databases.set(options.name, db); | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Database connection leaked when PRAGMA commands failMedium Severity In the |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Event} event | ||||||||||||||||||||||||||||||
| * @param {{path: string}} options | ||||||||||||||||||||||||||||||
| * @returns {Promise<void>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| close = async (event, options) => { | ||||||||||||||||||||||||||||||
| const db = this.#databases.get(options.path); | ||||||||||||||||||||||||||||||
| if (db) { | ||||||||||||||||||||||||||||||
| await db.close(); | ||||||||||||||||||||||||||||||
| this.#databases.delete(options.path); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
cursor[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Event} event | ||||||||||||||||||||||||||||||
| * @param {{path: string}} options | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| delete = async (event, options) => { | ||||||||||||||||||||||||||||||
| if (this.#databases.has(options.path)) { | ||||||||||||||||||||||||||||||
| await this.close(event, options); | ||||||||||||||||||||||||||||||
| this.#deleteDatabase(options.path); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Event} event | ||||||||||||||||||||||||||||||
| * @param {{dbargs: {dbname: string}, executes: Array<{qid: string, sql: string, params: any[]}>}} options | ||||||||||||||||||||||||||||||
| * @returns {Promise<{ | ||||||||||||||||||||||||||||||
| * qid: string, | ||||||||||||||||||||||||||||||
| * type: "success" | "error", | ||||||||||||||||||||||||||||||
| * result: string | { | ||||||||||||||||||||||||||||||
| * rowsAffected: number, | ||||||||||||||||||||||||||||||
| * rows: any[] | ||||||||||||||||||||||||||||||
| * } | ||||||||||||||||||||||||||||||
| * }[]>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| backgroundExecuteSqlBatch = async (event, options) => { | ||||||||||||||||||||||||||||||
| const db = this.#databases.get(options.dbargs.dbname); | ||||||||||||||||||||||||||||||
| if (!db) { | ||||||||||||||||||||||||||||||
| throw new Error("Database does not exist"); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const results = []; | ||||||||||||||||||||||||||||||
| const executes = options.executes; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| for (const e of executes) { | ||||||||||||||||||||||||||||||
| const execute = e; | ||||||||||||||||||||||||||||||
| const qid = execute.qid; | ||||||||||||||||||||||||||||||
| const sql = execute.sql; | ||||||||||||||||||||||||||||||
| const params = execute.params; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let resultInfo = { qid }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||
| const { rows, rowsAffected, insertId } = await this.#all( | ||||||||||||||||||||||||||||||
| db, | ||||||||||||||||||||||||||||||
| sql, | ||||||||||||||||||||||||||||||
| params | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const hasInsertId = rowsAffected > 0 && insertId !== 0; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| resultInfo = { | ||||||||||||||||||||||||||||||
| ...resultInfo, | ||||||||||||||||||||||||||||||
| type: "success", | ||||||||||||||||||||||||||||||
| result: { | ||||||||||||||||||||||||||||||
| rowsAffected, | ||||||||||||||||||||||||||||||
| rows, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
| if (hasInsertId) { | ||||||||||||||||||||||||||||||
| resultInfo.result.insertId = insertId; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||
| resultInfo = { | ||||||||||||||||||||||||||||||
| ...resultInfo, | ||||||||||||||||||||||||||||||
| type: "error", | ||||||||||||||||||||||||||||||
| message: err, | ||||||||||||||||||||||||||||||
| result: err, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| results.push(resultInfo); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| return results; | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {AsyncDatabase} db | ||||||||||||||||||||||||||||||
| * @param {string} sql | ||||||||||||||||||||||||||||||
| * @param {any[]} params | ||||||||||||||||||||||||||||||
| * @returns {Promise<{rows: any[], rowsAffected: number, insertId: number}>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| async #all(db, sql, params) { | ||||||||||||||||||||||||||||||
| const statement = await db.prepare(sql); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let result; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (sql.toLocaleLowerCase().startsWith("select")) { | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: SELECT detection fails for queries with leading whitespaceThe |
||||||||||||||||||||||||||||||
| const all = await statement.all(params); | ||||||||||||||||||||||||||||||
| result = { | ||||||||||||||||||||||||||||||
| rowsAffected: all.changes, | ||||||||||||||||||||||||||||||
| insertId: all.lastID, | ||||||||||||||||||||||||||||||
| rows: all.rows, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| const all = await statement.run(params); | ||||||||||||||||||||||||||||||
| result = { | ||||||||||||||||||||||||||||||
| rowsAffected: all.changes, | ||||||||||||||||||||||||||||||
| insertId: all.insertId, | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name causes undefined insertId for non-SELECT queriesThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name causes undefined insertId for writesThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name for insert ID in run resultThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name causes undefined insertIdThe non-SELECT branch of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name causes undefined insertId for writesIn the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Wrong property name causes undefined insertId for writesThe code accesses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong property name causes undefined insertId for writesHigh Severity The |
||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Missing rows property for non-SELECT query resultsFor non-SELECT queries, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Non-SELECT queries return undefined rows instead of arrayThe |
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Type Contract Broken: Non-SELECT Queries Lack Expected DataNon-SELECT query results are missing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing rows property for non-SELECT query resultsMedium Severity The |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| await statement.finalize(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| return result; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prepared statement leaked when query execution failsMedium Severity In the |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {string} dbname | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| #deleteDatabase(dbname) { | ||||||||||||||||||||||||||||||
| const dbPath = path.resolve(path.join(this.#dbLocation, dbname)); | ||||||||||||||||||||||||||||||
| if (existsSync(dbPath)) { | ||||||||||||||||||||||||||||||
| unlinkSync(dbPath); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| class AsyncDatabase { | ||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @type {Database} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| #db; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Database} db | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| constructor(db) { | ||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @type {Database} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| this.#db = db; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {string} openPath | ||||||||||||||||||||||||||||||
| * @returns {Promise<AsyncDatabase>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| static newDatabase(openPath) { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| const db = new sqlite3.Database(openPath, (err) => { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(new AsyncDatabase(db)); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {string} sql | ||||||||||||||||||||||||||||||
| * @returns {{Promise<RunResult>}} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| run(sql) { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#db.run(sql, function (err) { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(this); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @returns {Promise<void>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| close() { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#db.close((err) => { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {string} sql | ||||||||||||||||||||||||||||||
| * @returns {AsyncStatement} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| prepare(sql) { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#db.prepare(sql, function (err) { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(new AsyncStatement(this)); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| class AsyncStatement { | ||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @type {Statement} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| #statement; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {Statement} statement | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| constructor(statement) { | ||||||||||||||||||||||||||||||
| this.#statement = statement; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {any[]} params | ||||||||||||||||||||||||||||||
| * @returns {Promise<RunResultWithRows>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| all(params) { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#statement.all(params, function (err, rows) { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve({ lastID: this.lastID, changes: this.changes, rows }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @param {any[]} params | ||||||||||||||||||||||||||||||
| * @returns {Promise<RunResult>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| run(params) { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#statement.run(params, function (err) { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(this); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||
| * @returns {Promise<void>} | ||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||
| finalize() { | ||||||||||||||||||||||||||||||
| return new Promise((resolve, reject) => { | ||||||||||||||||||||||||||||||
| this.#statement.finalize((err) => { | ||||||||||||||||||||||||||||||
| if (err) { | ||||||||||||||||||||||||||||||
| reject(err); | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| resolve(); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| const sqlite = new SQLite(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| export const db = { | ||||||||||||||||||||||||||||||
| main: { | ||||||||||||||||||||||||||||||
| init() { | ||||||||||||||||||||||||||||||
| ipcMain.handle("sqlite:open", sqlite.open); | ||||||||||||||||||||||||||||||
| ipcMain.handle("sqlite:close", sqlite.close); | ||||||||||||||||||||||||||||||
| ipcMain.handle("sqlite:delete", sqlite.delete); | ||||||||||||||||||||||||||||||
| ipcMain.handle( | ||||||||||||||||||||||||||||||
| "sqlite:backgroundExecuteSqlBatch", | ||||||||||||||||||||||||||||||
| sqlite.backgroundExecuteSqlBatch | ||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export declare const db: { | ||
| preload: { | ||
| init(): void; | ||
| }; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Encryption Key Opens Door to SQL Injection
Database encryption key is directly interpolated into SQL string using template literals, creating a SQL injection vulnerability. If the key contains quotes or SQL syntax, it could break out and inject arbitrary commands. The key should be passed through a parameterized approach or properly escaped.