1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 15:49:44 -05:00

Add --allow-read (#1689)

Co-authored-by: Greg Altman <g.s.altman@gmail.com>
This commit is contained in:
Dmitry Sharshakov 2019-02-08 23:59:38 +03:00 committed by Ryan Dahl
parent 3abaf9edb6
commit 9ab03389f0
25 changed files with 395 additions and 118 deletions

View file

@ -4,7 +4,7 @@ import * as deno from "deno";
const isNotWindows = deno.platform.os !== "win";
testPerm({ write: true }, function chmodSyncSuccess() {
testPerm({ read: true, write: true }, function chmodSyncSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const tempDir = deno.makeTempDirSync();
@ -23,7 +23,7 @@ testPerm({ write: true }, function chmodSyncSuccess() {
// Check symlink when not on windows
if (isNotWindows) {
testPerm({ write: true }, function chmodSyncSymlinkSuccess() {
testPerm({ read: true, write: true }, function chmodSyncSymlinkSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const tempDir = deno.makeTempDirSync();
@ -69,7 +69,7 @@ testPerm({ write: false }, function chmodSyncPerm() {
assertEqual(err.name, "PermissionDenied");
});
testPerm({ write: true }, async function chmodSuccess() {
testPerm({ read: true, write: true }, async function chmodSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const tempDir = deno.makeTempDirSync();
@ -88,7 +88,7 @@ testPerm({ write: true }, async function chmodSuccess() {
// Check symlink when not on windows
if (isNotWindows) {
testPerm({ write: true }, async function chmodSymlinkSuccess() {
testPerm({ read: true, write: true }, async function chmodSymlinkSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const tempDir = deno.makeTempDirSync();

View file

@ -20,7 +20,7 @@ function assertSameContent(filename1: string, filename2: string) {
assertEqual(data1, data2);
}
testPerm({ write: true }, function copyFileSyncSuccess() {
testPerm({ read: true, write: true }, function copyFileSyncSuccess() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -32,7 +32,7 @@ testPerm({ write: true }, function copyFileSyncSuccess() {
assertSameContent(fromFilename, toFilename);
});
testPerm({ write: true }, function copyFileSyncFailure() {
testPerm({ write: true, read: true }, function copyFileSyncFailure() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -48,7 +48,31 @@ testPerm({ write: true }, function copyFileSyncFailure() {
assertEqual(err.name, "NotFound");
});
testPerm({ write: true }, function copyFileSyncOverwrite() {
testPerm({ write: true, read: false }, function copyFileSyncPerm1() {
let caughtError = false;
try {
deno.copyFileSync("/from.txt", "/to.txt");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ write: false, read: true }, function copyFileSyncPerm2() {
let caughtError = false;
try {
deno.copyFileSync("/from.txt", "/to.txt");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true, write: true }, function copyFileSyncOverwrite() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -62,19 +86,7 @@ testPerm({ write: true }, function copyFileSyncOverwrite() {
assertSameContent(fromFilename, toFilename);
});
testPerm({ write: false }, function copyFileSyncPerm() {
let err;
try {
deno.copyFileSync("/from.txt", "/to.txt");
} catch (e) {
err = e;
}
assert(!!err);
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
});
testPerm({ write: true }, async function copyFileSuccess() {
testPerm({ read: true, write: true }, async function copyFileSuccess() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -86,7 +98,7 @@ testPerm({ write: true }, async function copyFileSuccess() {
assertSameContent(fromFilename, toFilename);
});
testPerm({ write: true }, async function copyFileFailure() {
testPerm({ read: true, write: true }, async function copyFileFailure() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -102,7 +114,7 @@ testPerm({ write: true }, async function copyFileFailure() {
assertEqual(err.name, "NotFound");
});
testPerm({ write: true }, async function copyFileOverwrite() {
testPerm({ read: true, write: true }, async function copyFileOverwrite() {
const tempDir = deno.makeTempDirSync();
const fromFilename = tempDir + "/from.txt";
const toFilename = tempDir + "/to.txt";
@ -116,14 +128,26 @@ testPerm({ write: true }, async function copyFileOverwrite() {
assertSameContent(fromFilename, toFilename);
});
testPerm({ write: false }, async function copyFilePerm() {
let err;
testPerm({ read: false, write: true }, async function copyFilePerm1() {
let caughtError = false;
try {
await deno.copyFile("/from.txt", "/to.txt");
} catch (e) {
err = e;
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(!!err);
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
assert(caughtError);
});
testPerm({ read: true, write: false }, async function copyFilePerm2() {
let caughtError = false;
try {
await deno.copyFile("/from.txt", "/to.txt");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});

View file

@ -8,7 +8,7 @@ test(function filesStdioFileDescriptors() {
assertEqual(deno.stderr.rid, 2);
});
test(async function filesCopyToStdout() {
testPerm({ read: true }, async function filesCopyToStdout() {
const filename = "package.json";
const file = await deno.open(filename);
assert(file.rid > 2);
@ -18,7 +18,7 @@ test(async function filesCopyToStdout() {
console.log("bytes written", bytesWritten);
});
test(async function filesToAsyncIterator() {
testPerm({ read: true }, async function filesToAsyncIterator() {
const filename = "tests/hello.txt";
const file = await deno.open(filename);
@ -32,7 +32,7 @@ test(async function filesToAsyncIterator() {
testPerm({ write: false }, async function writePermFailure() {
const filename = "tests/hello.txt";
const writeModes: deno.OpenMode[] = ["r+", "w", "w+", "a", "a+", "x", "x+"];
const writeModes: deno.OpenMode[] = ["w", "a", "x"];
for (const mode of writeModes) {
let err;
try {
@ -46,7 +46,35 @@ testPerm({ write: false }, async function writePermFailure() {
}
});
testPerm({ write: true }, async function createFile() {
testPerm({ read: false }, async function readPermFailure() {
let caughtError = false;
try {
await deno.open("package.json", "r");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ write: false, read: false }, async function readWritePermFailure() {
const filename = "tests/hello.txt";
const writeModes: deno.OpenMode[] = ["r+", "w+", "a+", "x+"];
for (const mode of writeModes) {
let err;
try {
await deno.open(filename, mode);
} catch (e) {
err = e;
}
assert(!!err);
assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
assertEqual(err.name, "PermissionDenied");
}
});
testPerm({ read: true, write: true }, async function createFile() {
const tempDir = await deno.makeTempDir();
const filename = tempDir + "/test.txt";
const f = await deno.open(filename, "w");
@ -64,7 +92,7 @@ testPerm({ write: true }, async function createFile() {
await deno.remove(tempDir, { recursive: true });
});
testPerm({ write: true }, async function openModeWrite() {
testPerm({ read: true, write: true }, async function openModeWrite() {
const tempDir = deno.makeTempDirSync();
const encoder = new TextEncoder();
const filename = tempDir + "hello.txt";
@ -98,7 +126,7 @@ testPerm({ write: true }, async function openModeWrite() {
await deno.remove(tempDir, { recursive: true });
});
testPerm({ write: true }, async function openModeWriteRead() {
testPerm({ read: true, write: true }, async function openModeWriteRead() {
const tempDir = deno.makeTempDirSync();
const encoder = new TextEncoder();
const filename = tempDir + "hello.txt";

View file

@ -2,14 +2,14 @@
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function mkdirSyncSuccess() {
testPerm({ read: true, write: true }, function mkdirSyncSuccess() {
const path = deno.makeTempDirSync() + "/dir";
deno.mkdirSync(path);
const pathInfo = deno.statSync(path);
assert(pathInfo.isDirectory());
});
testPerm({ write: true }, function mkdirSyncMode() {
testPerm({ read: true, write: true }, function mkdirSyncMode() {
const path = deno.makeTempDirSync() + "/dir";
deno.mkdirSync(path, false, 0o755); // no perm for x
const pathInfo = deno.statSync(path);
@ -30,7 +30,7 @@ testPerm({ write: false }, function mkdirSyncPerm() {
assertEqual(err.name, "PermissionDenied");
});
testPerm({ write: true }, async function mkdirSuccess() {
testPerm({ read: true, write: true }, async function mkdirSuccess() {
const path = deno.makeTempDirSync() + "/dir";
await deno.mkdir(path);
const pathInfo = deno.statSync(path);
@ -48,14 +48,14 @@ testPerm({ write: true }, function mkdirErrIfExists() {
assertEqual(err.name, "AlreadyExists");
});
testPerm({ write: true }, function mkdirSyncRecursive() {
testPerm({ read: true, write: true }, function mkdirSyncRecursive() {
const path = deno.makeTempDirSync() + "/nested/directory";
deno.mkdirSync(path, true);
const pathInfo = deno.statSync(path);
assert(pathInfo.isDirectory());
});
testPerm({ write: true }, async function mkdirRecursive() {
testPerm({ read: true, write: true }, async function mkdirRecursive() {
const path = deno.makeTempDirSync() + "/nested/directory";
await deno.mkdir(path, true);
const pathInfo = deno.statSync(path);

View file

@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
import { FileInfo } from "deno";
@ -22,12 +22,24 @@ function assertSameContent(files: FileInfo[]) {
assertEqual(counter, 2);
}
test(function readDirSyncSuccess() {
testPerm({ read: true }, function readDirSyncSuccess() {
const files = deno.readDirSync("tests/");
assertSameContent(files);
});
test(function readDirSyncNotDir() {
testPerm({ read: false }, function readDirSyncPerm() {
let caughtError = false;
try {
const files = deno.readDirSync("tests/");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, function readDirSyncNotDir() {
let caughtError = false;
let src;
@ -41,7 +53,7 @@ test(function readDirSyncNotDir() {
assertEqual(src, undefined);
});
test(function readDirSyncNotFound() {
testPerm({ read: true }, function readDirSyncNotFound() {
let caughtError = false;
let src;
@ -55,7 +67,19 @@ test(function readDirSyncNotFound() {
assertEqual(src, undefined);
});
test(async function readDirSuccess() {
testPerm({ read: true }, async function readDirSuccess() {
const files = await deno.readDir("tests/");
assertSameContent(files);
});
testPerm({ read: false }, async function readDirPerm() {
let caughtError = false;
try {
const files = await deno.readDir("tests/");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, assert, assertEqual } from "./test_util.ts";
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
test(function readFileSyncSuccess() {
testPerm({ read: true }, function readFileSyncSuccess() {
const data = deno.readFileSync("package.json");
assert(data.byteLength > 0);
const decoder = new TextDecoder("utf-8");
@ -11,7 +11,19 @@ test(function readFileSyncSuccess() {
assertEqual(pkg.name, "deno");
});
test(function readFileSyncNotFound() {
testPerm({ read: false }, function readFileSyncPerm() {
let caughtError = false;
try {
const data = deno.readFileSync("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, function readFileSyncNotFound() {
let caughtError = false;
let data;
try {
@ -24,7 +36,7 @@ test(function readFileSyncNotFound() {
assert(data === undefined);
});
test(async function readFileSuccess() {
testPerm({ read: true }, async function readFileSuccess() {
const data = await deno.readFile("package.json");
assert(data.byteLength > 0);
const decoder = new TextDecoder("utf-8");
@ -32,3 +44,15 @@ test(async function readFileSuccess() {
const pkg = JSON.parse(json);
assertEqual(pkg.name, "deno");
});
testPerm({ read: false }, async function readFilePerm() {
let caughtError = false;
try {
await deno.readFile("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function readlinkSyncSuccess() {
testPerm({ write: true, read: true }, function readlinkSyncSuccess() {
const testDir = deno.makeTempDirSync();
const target = testDir + "/target";
const symlink = testDir + "/symln";
@ -16,7 +16,19 @@ testPerm({ write: true }, function readlinkSyncSuccess() {
}
});
test(function readlinkSyncNotFound() {
testPerm({ read: false }, async function readlinkSyncPerm() {
let caughtError = false;
try {
deno.readlinkSync("/symlink");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, function readlinkSyncNotFound() {
let caughtError = false;
let data;
try {
@ -29,7 +41,7 @@ test(function readlinkSyncNotFound() {
assertEqual(data, undefined);
});
testPerm({ write: true }, async function readlinkSuccess() {
testPerm({ write: true, read: true }, async function readlinkSuccess() {
const testDir = deno.makeTempDirSync();
const target = testDir + "/target";
const symlink = testDir + "/symln";
@ -42,3 +54,15 @@ testPerm({ write: true }, async function readlinkSuccess() {
assertEqual(targetPath, target);
}
});
testPerm({ read: false }, async function readlinkPerm() {
let caughtError = false;
try {
await deno.readlink("/symlink");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});

View file

@ -2,7 +2,7 @@
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function renameSyncSuccess() {
testPerm({ read: true, write: true }, function renameSyncSuccess() {
const testDir = deno.makeTempDirSync();
const oldpath = testDir + "/oldpath";
const newpath = testDir + "/newpath";
@ -24,7 +24,7 @@ testPerm({ write: true }, function renameSyncSuccess() {
assertEqual(oldPathInfo, undefined);
});
testPerm({ write: false }, function renameSyncPerm() {
testPerm({ read: true, write: false }, function renameSyncPerm() {
let err;
try {
const oldpath = "/oldbaddir";
@ -37,7 +37,7 @@ testPerm({ write: false }, function renameSyncPerm() {
assertEqual(err.name, "PermissionDenied");
});
testPerm({ write: true }, async function renameSuccess() {
testPerm({ read: true, write: true }, async function renameSuccess() {
const testDir = deno.makeTempDirSync();
const oldpath = testDir + "/oldpath";
const newpath = testDir + "/newpath";

View file

@ -26,7 +26,7 @@ testPerm({ net: true }, async function resourcesNet() {
listener.close();
});
test(async function resourcesFile() {
testPerm({ read: true }, async function resourcesFile() {
const resourcesBefore = deno.resources();
await deno.open("tests/hello.txt");
const resourcesAfter = deno.resources();

View file

@ -1,10 +1,10 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, assert, assertEqual } from "./test_util.ts";
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
// TODO Add tests for modified, accessed, and created fields once there is a way
// to create temp files.
test(async function statSyncSuccess() {
testPerm({ read: true }, async function statSyncSuccess() {
const packageInfo = deno.statSync("package.json");
assert(packageInfo.isFile());
assert(!packageInfo.isSymlink());
@ -18,7 +18,19 @@ test(async function statSyncSuccess() {
assert(!srcInfo.isSymlink());
});
test(async function statSyncNotFound() {
testPerm({ read: false }, async function statSyncPerm() {
let caughtError = false;
try {
deno.statSync("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, async function statSyncNotFound() {
let caughtError = false;
let badInfo;
@ -34,7 +46,7 @@ test(async function statSyncNotFound() {
assertEqual(badInfo, undefined);
});
test(async function lstatSyncSuccess() {
testPerm({ read: true }, async function lstatSyncSuccess() {
const packageInfo = deno.lstatSync("package.json");
assert(packageInfo.isFile());
assert(!packageInfo.isSymlink());
@ -48,7 +60,19 @@ test(async function lstatSyncSuccess() {
assert(!srcInfo.isSymlink());
});
test(async function lstatSyncNotFound() {
testPerm({ read: false }, async function lstatSyncPerm() {
let caughtError = false;
try {
deno.lstatSync("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, async function lstatSyncNotFound() {
let caughtError = false;
let badInfo;
@ -64,7 +88,7 @@ test(async function lstatSyncNotFound() {
assertEqual(badInfo, undefined);
});
test(async function statSuccess() {
testPerm({ read: true }, async function statSuccess() {
const packageInfo = await deno.stat("package.json");
assert(packageInfo.isFile());
assert(!packageInfo.isSymlink());
@ -78,7 +102,19 @@ test(async function statSuccess() {
assert(!srcInfo.isSymlink());
});
test(async function statNotFound() {
testPerm({ read: false }, async function statPerm() {
let caughtError = false;
try {
await deno.stat("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, async function statNotFound() {
let caughtError = false;
let badInfo;
@ -94,7 +130,7 @@ test(async function statNotFound() {
assertEqual(badInfo, undefined);
});
test(async function lstatSuccess() {
testPerm({ read: true }, async function lstatSuccess() {
const packageInfo = await deno.lstat("package.json");
assert(packageInfo.isFile());
assert(!packageInfo.isSymlink());
@ -108,7 +144,19 @@ test(async function lstatSuccess() {
assert(!srcInfo.isSymlink());
});
test(async function lstatNotFound() {
testPerm({ read: false }, async function lstatPerm() {
let caughtError = false;
try {
await deno.lstat("package.json");
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});
testPerm({ read: true }, async function lstatNotFound() {
let caughtError = false;
let badInfo;

View file

@ -1,8 +1,8 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { testPerm, assert, assertEqual } from "./test_util.ts";
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function symlinkSyncSuccess() {
testPerm({ read: true, write: true }, function symlinkSyncSuccess() {
const testDir = deno.makeTempDirSync();
const oldname = testDir + "/oldname";
const newname = testDir + "/newname";
@ -25,7 +25,7 @@ testPerm({ write: true }, function symlinkSyncSuccess() {
}
});
testPerm({ write: false }, function symlinkSyncPerm() {
test(function symlinkSyncPerm() {
let err;
try {
deno.symlinkSync("oldbaddir", "newbaddir");
@ -47,7 +47,7 @@ testPerm({ write: true }, function symlinkSyncNotImplemented() {
assertEqual(err.message, "Not implemented");
});
testPerm({ write: true }, async function symlinkSuccess() {
testPerm({ read: true, write: true }, async function symlinkSuccess() {
const testDir = deno.makeTempDirSync();
const oldname = testDir + "/oldname";
const newname = testDir + "/newname";

View file

@ -18,6 +18,7 @@ export {
testing.setFilter(deno.args[1]);
interface DenoPermissions {
read?: boolean;
write?: boolean;
net?: boolean;
env?: boolean;
@ -25,24 +26,26 @@ interface DenoPermissions {
}
function permToString(perms: DenoPermissions): string {
const r = perms.read ? 1 : 0;
const w = perms.write ? 1 : 0;
const n = perms.net ? 1 : 0;
const e = perms.env ? 1 : 0;
const r = perms.run ? 1 : 0;
return `permW${w}N${n}E${e}R${r}`;
const u = perms.run ? 1 : 0;
return `permR${r}W${w}N${n}E${e}U${u}`;
}
function permFromString(s: string): DenoPermissions {
const re = /^permW([01])N([01])E([01])R([01])$/;
const re = /^permR([01])W([01])N([01])E([01])U([01])$/;
const found = s.match(re);
if (!found) {
throw Error("Not a permission string");
}
return {
write: Boolean(Number(found[1])),
net: Boolean(Number(found[2])),
env: Boolean(Number(found[3])),
run: Boolean(Number(found[4]))
read: Boolean(Number(found[1])),
write: Boolean(Number(found[2])),
net: Boolean(Number(found[3])),
env: Boolean(Number(found[4])),
run: Boolean(Number(found[5]))
};
}
@ -52,7 +55,10 @@ export function testPerm(perms: DenoPermissions, fn: testing.TestFunction) {
}
export function test(fn: testing.TestFunction) {
testPerm({ write: false, net: false, env: false, run: false }, fn);
testPerm(
{ read: false, write: false, net: false, env: false, run: false },
fn
);
}
test(function permSerialization() {
@ -60,8 +66,10 @@ test(function permSerialization() {
for (const net of [true, false]) {
for (const env of [true, false]) {
for (const run of [true, false]) {
const perms: DenoPermissions = { write, net, env, run };
testing.assertEqual(perms, permFromString(permToString(perms)));
for (const read of [true, false]) {
const perms: DenoPermissions = { write, net, env, run, read };
testing.assertEqual(perms, permFromString(permToString(perms)));
}
}
}
}

View file

@ -16,7 +16,7 @@ async function readData(name: string): Promise<string> {
return text;
}
testPerm({ write: true }, function truncateSyncSuccess() {
testPerm({ read: true, write: true }, function truncateSyncSuccess() {
const enc = new TextEncoder();
const d = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test_truncateSync.txt";
@ -33,7 +33,7 @@ testPerm({ write: true }, function truncateSyncSuccess() {
deno.removeSync(filename);
});
testPerm({ write: true }, async function truncateSuccess() {
testPerm({ read: true, write: true }, async function truncateSuccess() {
const enc = new TextEncoder();
const d = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test_truncate.txt";

View file

@ -2,7 +2,7 @@
import { testPerm, assert, assertEqual } from "./test_util.ts";
import * as deno from "deno";
testPerm({ write: true }, function writeFileSyncSuccess() {
testPerm({ read: true, write: true }, function writeFileSyncSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";
@ -45,7 +45,7 @@ testPerm({ write: false }, function writeFileSyncPerm() {
assert(caughtError);
});
testPerm({ write: true }, function writeFileSyncUpdatePerm() {
testPerm({ read: true, write: true }, function writeFileSyncUpdatePerm() {
if (deno.platform.os !== "win") {
const enc = new TextEncoder();
const data = enc.encode("Hello");
@ -57,7 +57,7 @@ testPerm({ write: true }, function writeFileSyncUpdatePerm() {
}
});
testPerm({ write: true }, function writeFileSyncCreate() {
testPerm({ read: true, write: true }, function writeFileSyncCreate() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";
@ -81,7 +81,7 @@ testPerm({ write: true }, function writeFileSyncCreate() {
assertEqual("Hello", actual);
});
testPerm({ write: true }, function writeFileSyncAppend() {
testPerm({ read: true, write: true }, function writeFileSyncAppend() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";
@ -103,7 +103,7 @@ testPerm({ write: true }, function writeFileSyncAppend() {
assertEqual("Hello", actual);
});
testPerm({ write: true }, async function writeFileSuccess() {
testPerm({ read: true, write: true }, async function writeFileSuccess() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";
@ -114,7 +114,7 @@ testPerm({ write: true }, async function writeFileSuccess() {
assertEqual("Hello", actual);
});
testPerm({ write: true }, async function writeFileNotFound() {
testPerm({ read: true, write: true }, async function writeFileNotFound() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = "/baddir/test.txt";
@ -130,7 +130,7 @@ testPerm({ write: true }, async function writeFileNotFound() {
assert(caughtError);
});
testPerm({ write: false }, async function writeFilePerm() {
testPerm({ read: true, write: false }, async function writeFilePerm() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = "/baddir/test.txt";
@ -146,7 +146,7 @@ testPerm({ write: false }, async function writeFilePerm() {
assert(caughtError);
});
testPerm({ write: true }, async function writeFileUpdatePerm() {
testPerm({ read: true, write: true }, async function writeFileUpdatePerm() {
if (deno.platform.os !== "win") {
const enc = new TextEncoder();
const data = enc.encode("Hello");
@ -158,7 +158,7 @@ testPerm({ write: true }, async function writeFileUpdatePerm() {
}
});
testPerm({ write: true }, async function writeFileCreate() {
testPerm({ read: true, write: true }, async function writeFileCreate() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";
@ -182,7 +182,7 @@ testPerm({ write: true }, async function writeFileCreate() {
assertEqual("Hello", actual);
});
testPerm({ write: true }, async function writeFileAppend() {
testPerm({ read: true, write: true }, async function writeFileAppend() {
const enc = new TextEncoder();
const data = enc.encode("Hello");
const filename = deno.makeTempDirSync() + "/test.txt";

View file

@ -23,6 +23,7 @@ pub struct DenoFlags {
pub version: bool,
pub reload: bool,
pub recompile: bool,
pub allow_read: bool,
pub allow_write: bool,
pub allow_net: bool,
pub allow_env: bool,
@ -89,6 +90,9 @@ fn set_recognized_flags(
if matches.opt_present("recompile") {
flags.recompile = true;
}
if matches.opt_present("allow-read") {
flags.allow_read = true;
}
if matches.opt_present("allow-write") {
flags.allow_write = true;
}
@ -102,9 +106,11 @@ fn set_recognized_flags(
flags.allow_run = true;
}
if matches.opt_present("allow-all") {
flags.allow_read = true;
flags.allow_env = true;
flags.allow_net = true;
flags.allow_run = true;
flags.allow_read = true;
flags.allow_write = true;
}
if matches.opt_present("types") {
@ -142,6 +148,7 @@ pub fn set_flags(
// TODO(kevinkassimo): v8_set_flags intercepts '-help' with single '-'
// Resolve that and then uncomment line below (enabling Go style -long-flag)
// opts.long_only(true);
opts.optflag("", "allow-read", "Allow file system read access.");
opts.optflag("", "allow-write", "Allow file system write access.");
opts.optflag("", "allow-net", "Allow network access.");
opts.optflag("", "allow-env", "Allow environment access.");
@ -262,12 +269,27 @@ fn test_set_flags_7() {
allow_net: true,
allow_env: true,
allow_run: true,
allow_read: true,
allow_write: true,
..DenoFlags::default()
}
)
}
#[test]
fn test_set_flags_8() {
let (flags, rest, _) =
set_flags(svec!["deno", "gist.ts", "--allow-read"]).unwrap();
assert_eq!(rest, svec!["deno", "gist.ts"]);
assert_eq!(
flags,
DenoFlags {
allow_read: true,
..DenoFlags::default()
}
)
}
// Returns args passed to V8, followed by args passed to JS
fn v8_set_flags_preprocess(args: Vec<String>) -> (Vec<String>, Vec<String>) {
let (rest, mut v8_args) =

View file

@ -113,6 +113,11 @@ impl IsolateState {
Arc::new(IsolateState::new(flags, rest_argv, None))
}
#[inline]
pub fn check_read(&self, filename: &str) -> DenoResult<()> {
self.permissions.check_read(filename)
}
#[inline]
pub fn check_write(&self, filename: &str) -> DenoResult<()> {
self.permissions.check_write(filename)

View file

@ -86,6 +86,7 @@ fn main() {
if flags.fmt {
rest_argv.insert(1, "https://deno.land/x/std/prettier/main.ts".to_string());
flags.allow_read = true;
flags.allow_write = true;
}

View file

@ -685,10 +685,24 @@ fn op_open(
}
}
if mode != "r" {
// Write permission is needed except "r" mode
if let Err(e) = state.check_write(&filename_str) {
return odd_future(e);
match mode {
"r" => {
if let Err(e) = state.check_read(&filename_str) {
return odd_future(e);
}
}
"w" | "a" | "x" => {
if let Err(e) = state.check_write(&filename_str) {
return odd_future(e);
}
}
&_ => {
if let Err(e) = state.check_read(&filename_str) {
return odd_future(e);
}
if let Err(e) = state.check_write(&filename_str) {
return odd_future(e);
}
}
}
@ -862,15 +876,19 @@ fn op_remove(
// Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184
fn op_read_file(
_state: &Arc<IsolateState>,
state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_read_file().unwrap();
let cmd_id = base.cmd_id();
let filename = PathBuf::from(inner.filename().unwrap());
let filename_ = inner.filename().unwrap();
let filename = PathBuf::from(filename_);
debug!("op_read_file {}", filename.display());
if let Err(e) = state.check_read(&filename_) {
return odd_future(e);
}
blocking(base.sync(), move || {
let vec = fs::read(&filename)?;
// Build the response message. memcpy data into inner.
@ -902,10 +920,14 @@ fn op_copy_file(
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_copy_file().unwrap();
let from = PathBuf::from(inner.from().unwrap());
let from_ = inner.from().unwrap();
let from = PathBuf::from(from_);
let to_ = inner.to().unwrap();
let to = PathBuf::from(to_);
if let Err(e) = state.check_read(&from_) {
return odd_future(e);
}
if let Err(e) = state.check_write(&to_) {
return odd_future(e);
}
@ -974,16 +996,21 @@ fn op_cwd(
}
fn op_stat(
_state: &Arc<IsolateState>,
state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_stat().unwrap();
let cmd_id = base.cmd_id();
let filename = PathBuf::from(inner.filename().unwrap());
let filename_ = inner.filename().unwrap();
let filename = PathBuf::from(filename_);
let lstat = inner.lstat();
if let Err(e) = state.check_read(&filename_) {
return odd_future(e);
}
blocking(base.sync(), move || {
let builder = &mut FlatBufferBuilder::new();
debug!("op_stat {} {}", filename.display(), lstat);
@ -1021,7 +1048,7 @@ fn op_stat(
}
fn op_read_dir(
_state: &Arc<IsolateState>,
state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
@ -1030,6 +1057,10 @@ fn op_read_dir(
let cmd_id = base.cmd_id();
let path = String::from(inner.path().unwrap());
if let Err(e) = state.check_read(&path) {
return odd_future(e);
}
blocking(base.sync(), move || -> OpResult {
debug!("op_read_dir {}", path);
let builder = &mut FlatBufferBuilder::new();
@ -1157,14 +1188,19 @@ fn op_symlink(
}
fn op_read_link(
_state: &Arc<IsolateState>,
state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_readlink().unwrap();
let cmd_id = base.cmd_id();
let name = PathBuf::from(inner.name().unwrap());
let name_ = inner.name().unwrap();
let name = PathBuf::from(name_);
if let Err(e) = state.check_read(&name_) {
return odd_future(e);
}
blocking(base.sync(), move || -> OpResult {
debug!("op_read_link {}", name.display());

View file

@ -12,6 +12,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[derive(Debug, Default)]
pub struct DenoPermissions {
pub allow_read: AtomicBool,
pub allow_write: AtomicBool,
pub allow_net: AtomicBool,
pub allow_env: AtomicBool,
@ -21,6 +22,7 @@ pub struct DenoPermissions {
impl DenoPermissions {
pub fn new(flags: &DenoFlags) -> Self {
Self {
allow_read: AtomicBool::new(flags.allow_read),
allow_write: AtomicBool::new(flags.allow_write),
allow_env: AtomicBool::new(flags.allow_env),
allow_net: AtomicBool::new(flags.allow_net),
@ -40,6 +42,21 @@ impl DenoPermissions {
r
}
pub fn check_read(&self, filename: &str) -> DenoResult<()> {
if self.allow_read.load(Ordering::SeqCst) {
return Ok(());
};
// TODO get location (where access occurred)
let r = permission_prompt(&format!(
"Deno requests read access to \"{}\".",
filename
));;
if r.is_ok() {
self.allow_read.store(true, Ordering::SeqCst);
}
r
}
pub fn check_write(&self, filename: &str) -> DenoResult<()> {
if self.allow_write.load(Ordering::SeqCst) {
return Ok(());

View file

@ -1,2 +1,2 @@
args: tests/016_double_await.ts --reload
args: tests/016_double_await.ts --allow-read --reload
output: tests/016_double_await.ts.out

View file

@ -18,7 +18,9 @@ def fmt_test(deno_exe):
# Set DENO_DIR to //js/ so we don't have to rely on an intenet
# connection to download https://deno.land/x/std/prettier/main.ts
deno_dir = os.path.join(root_path, "js")
run([deno_exe, dst, "--fmt"], merge_env={"DENO_DIR": deno_dir})
run(
[deno_exe, dst, "--fmt", "--allow-read"],
merge_env={"DENO_DIR": deno_dir})
with open(fixed_filename) as f:
expected = f.read()
with open(dst) as f:
@ -31,4 +33,3 @@ def fmt_test(deno_exe):
if __name__ == "__main__":
fmt_test(sys.argv[1])

View file

@ -30,7 +30,7 @@ def main():
print "No available deno executable."
sys.exit(1)
util.run([deno_path, "--allow-run", "tools/format.ts"])
util.run([deno_path, "--allow-read", "--allow-run", "tools/format.ts"])
output = util.run_output(
["git", "status", "-uno", "--porcelain", "--ignore-submodules"])
if len(output) > 0:

View file

@ -19,7 +19,7 @@ ADDR = "127.0.0.1:4544"
def cat(deno_exe, megs):
size = megs * MB
start = time.time()
cmd = deno_exe + " tests/cat.ts /dev/zero | head -c %s " % size
cmd = deno_exe + " tests/cat.ts --allow-read /dev/zero | head -c %s " % size
print cmd
subprocess.check_output(cmd, shell=True)
end = time.time()

View file

@ -43,12 +43,14 @@ def run_unit_test(deno_exe, permStr, flags=None):
# tests by the special string. permW0N0 means allow-write but not allow-net.
# See js/test_util.ts for more details.
def unit_tests(deno_exe):
run_unit_test(deno_exe, "permW0N0E0R0")
run_unit_test(deno_exe, "permW1N0E0R0", ["--allow-write"])
run_unit_test(deno_exe, "permW0N1E0R0", ["--allow-net"])
run_unit_test(deno_exe, "permW0N0E1R0", ["--allow-env"])
run_unit_test(deno_exe, "permW0N0E0R1", ["--allow-run"])
run_unit_test(deno_exe, "permW1N0E0R1", ["--allow-run", "--allow-write"])
run_unit_test(deno_exe, "permR0W0N0E0U0")
run_unit_test(deno_exe, "permR1W0N0E0U0", ["--allow-read"])
run_unit_test(deno_exe, "permR0W1N0E0U0", ["--allow-write"])
run_unit_test(deno_exe, "permR1W1N0E0U0", ["--allow-read", "--allow-write"])
run_unit_test(deno_exe, "permR1W0N1E0U0", ["--allow-read", "--allow-net"])
run_unit_test(deno_exe, "permR0W0N0E1U0", ["--allow-env"])
run_unit_test(deno_exe, "permR0W0N0E0U1", ["--allow-run"])
run_unit_test(deno_exe, "permR0W1N0E0U1", ["--allow-run", "--allow-write"])
# TODO We might accidentally miss some. We should be smarter about which we
# run. Maybe we can use the "filtered out" number to check this.

View file

@ -1,5 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, assertEqual } from "../js/test_util.ts";
import * as deno from "deno";
import { assert, testPerm, assertEqual } from "../js/test_util.ts";
import { findFiles } from "./util.ts";
const testDir = "tools/testdata/find_files_testdata";
@ -7,7 +8,7 @@ const testDir = "tools/testdata/find_files_testdata";
// Sorts and replace backslashes with slashes.
const normalize = files => files.map(f => f.replace(/\\/g, "/")).sort();
test(function testFindFiles() {
testPerm({ read: true }, function testFindFiles() {
const files = findFiles([testDir], [".ts", ".md"]);
assertEqual(normalize(files), [
`${testDir}/bar.md`,
@ -23,7 +24,7 @@ test(function testFindFiles() {
]);
});
test(function testFindFilesDepth() {
testPerm({ read: true }, function testFindFilesDepth() {
const files = findFiles([testDir], [".ts", ".md"], { depth: 1 });
assertEqual(normalize(files), [
`${testDir}/bar.md`,
@ -33,7 +34,7 @@ test(function testFindFilesDepth() {
]);
});
test(function testFindFilesSkip() {
testPerm({ read: true }, function testFindFilesSkip() {
const files = findFiles([testDir], [".ts", ".md"], {
skip: ["foo.md", "subdir1"]
});
@ -47,3 +48,15 @@ test(function testFindFilesSkip() {
`${testDir}/subdir0/subdir0/foo.ts`
]);
});
testPerm({ read: false }, function testFindFilesPerm() {
let caughtError = false;
try {
const files = findFiles([testDir], [".ts", ".md"]);
} catch (e) {
caughtError = true;
assertEqual(e.kind, deno.ErrorKind.PermissionDenied);
assertEqual(e.name, "PermissionDenied");
}
assert(caughtError);
});