mirror of
https://github.com/denoland/deno.git
synced 2025-08-31 07:47:46 +00:00
fix(ext/node): enforce -RW perms on node:sqlite
(#27928)
require RW permission on the database path except when using in-memory mode.
This commit is contained in:
parent
540fe7d9e4
commit
3c56e6c7cd
3 changed files with 34 additions and 1 deletions
|
@ -6,6 +6,8 @@ use std::rc::Rc;
|
|||
|
||||
use deno_core::op2;
|
||||
use deno_core::GarbageCollected;
|
||||
use deno_core::OpState;
|
||||
use deno_permissions::PermissionsContainer;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::SqliteError;
|
||||
|
@ -41,6 +43,19 @@ pub struct DatabaseSync {
|
|||
|
||||
impl GarbageCollected for DatabaseSync {}
|
||||
|
||||
fn check_perms(state: &mut OpState, location: &str) -> Result<(), SqliteError> {
|
||||
if location != ":memory:" {
|
||||
state
|
||||
.borrow::<PermissionsContainer>()
|
||||
.check_read_with_api_name(location, Some("node:sqlite"))?;
|
||||
state
|
||||
.borrow::<PermissionsContainer>()
|
||||
.check_write_with_api_name(location, Some("node:sqlite"))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Represents a single connection to a SQLite database.
|
||||
#[op2]
|
||||
impl DatabaseSync {
|
||||
|
@ -53,12 +68,15 @@ impl DatabaseSync {
|
|||
#[constructor]
|
||||
#[cppgc]
|
||||
fn new(
|
||||
state: &mut OpState,
|
||||
#[string] location: String,
|
||||
#[serde] options: Option<DatabaseSyncOptions>,
|
||||
) -> Result<DatabaseSync, SqliteError> {
|
||||
let options = options.unwrap_or_default();
|
||||
|
||||
let db = if options.open {
|
||||
check_perms(state, &location)?;
|
||||
|
||||
let db = rusqlite::Connection::open(&location)?;
|
||||
if options.enable_foreign_key_constraints {
|
||||
db.execute("PRAGMA foreign_keys = ON", [])?;
|
||||
|
@ -81,11 +99,12 @@ impl DatabaseSync {
|
|||
// via the constructor. An exception is thrown if the database is
|
||||
// already opened.
|
||||
#[fast]
|
||||
fn open(&self) -> Result<(), SqliteError> {
|
||||
fn open(&self, state: &mut OpState) -> Result<(), SqliteError> {
|
||||
if self.conn.borrow().is_some() {
|
||||
return Err(SqliteError::AlreadyOpen);
|
||||
}
|
||||
|
||||
check_perms(state, &self.location)?;
|
||||
let db = rusqlite::Connection::open(&self.location)?;
|
||||
if self.options.enable_foreign_key_constraints {
|
||||
db.execute("PRAGMA foreign_keys = ON", [])?;
|
||||
|
|
|
@ -4,10 +4,14 @@ mod database;
|
|||
mod statement;
|
||||
|
||||
pub use database::DatabaseSync;
|
||||
use deno_permissions::PermissionCheckError;
|
||||
pub use statement::StatementSync;
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum SqliteError {
|
||||
#[class(inherit)]
|
||||
#[error(transparent)]
|
||||
Permission(#[from] PermissionCheckError),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
SqliteError(#[from] rusqlite::Error),
|
||||
|
|
|
@ -91,3 +91,13 @@ Deno.test("[node/sqlite] StatementSync blob are Uint8Array", () => {
|
|||
const row = obj[0] as Record<string, Uint8Array>;
|
||||
assert(row["cast('test' as blob)"] instanceof Uint8Array);
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "[node/sqlite] sqlite permissions",
|
||||
permissions: { read: false, write: false },
|
||||
fn() {
|
||||
assertThrows(() => {
|
||||
new DatabaseSync("test.db");
|
||||
}, Deno.errors.NotCapable);
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue