mirror of
https://github.com/denoland/deno.git
synced 2024-12-27 01:29:14 -05:00
22e0ee92a6
Allowlist checking already uses hosts but for some reason requests, revokes and the runtime permissions API use URLs. - BREAKING(lib.deno.unstable.d.ts): Change NetPermissionDescriptor::url to NetPermissionDescriptor::host - fix(runtime/permissions): Don't add whole URLs to the allowlist on request - fix(runtime/permissions): Harden strength semantics: ({ name: "net", host: "127.0.0.1" } is stronger than { name: "net", host: "127.0.0.1:8000" }) for blocklisting - refactor(runtime/permissions): Use tuples for hosts, make the host optional in Permissions::{query_net, request_net, revoke_net}()
124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
|
|
|
const { PermissionDenied } = Deno.errors;
|
|
|
|
function getPermissionString(descriptors: Deno.PermissionDescriptor[]): string {
|
|
return descriptors.length
|
|
? ` ${
|
|
descriptors
|
|
.map((pd) => {
|
|
switch (pd.name) {
|
|
case "read":
|
|
case "write":
|
|
return pd.path
|
|
? `--allow-${pd.name}=${pd.path}`
|
|
: `--allow-${pd.name}`;
|
|
case "net":
|
|
return pd.host
|
|
? `--allow-${pd.name}=${pd.host}`
|
|
: `--allow-${pd.name}`;
|
|
default:
|
|
return `--allow-${pd.name}`;
|
|
}
|
|
})
|
|
.join("\n ")
|
|
}`
|
|
: "";
|
|
}
|
|
|
|
/** Attempts to grant a set of permissions, resolving with the descriptors of
|
|
* the permissions that are granted.
|
|
*
|
|
* const perms = await grant({ name: "net" }, { name: "read" });
|
|
* if (perms && perms.length === 2) {
|
|
* // do something cool that connects to the net and reads files
|
|
* } else {
|
|
* // notify user of missing permissions
|
|
* }
|
|
*
|
|
* If one of the permissions requires a prompt, the function will attempt to
|
|
* prompt for it. The function resolves with all of the granted permissions. */
|
|
export async function grant(
|
|
...descriptors: Deno.PermissionDescriptor[]
|
|
): Promise<void | Deno.PermissionDescriptor[]>;
|
|
/** Attempts to grant a set of permissions, resolving with the descriptors of
|
|
* the permissions that are granted.
|
|
*
|
|
* const perms = await grant([{ name: "net" }, { name: "read" }]);
|
|
* if (perms && perms.length === 2) {
|
|
* // do something cool that connects to the net and reads files
|
|
* } else {
|
|
* // notify user of missing permissions
|
|
* }
|
|
*
|
|
* If one of the permissions requires a prompt, the function will attempt to
|
|
* prompt for it. The function resolves with all of the granted permissions. */
|
|
export async function grant(
|
|
descriptors: Deno.PermissionDescriptor[],
|
|
): Promise<void | Deno.PermissionDescriptor[]>;
|
|
export async function grant(
|
|
descriptor: Deno.PermissionDescriptor[] | Deno.PermissionDescriptor,
|
|
...descriptors: Deno.PermissionDescriptor[]
|
|
): Promise<void | Deno.PermissionDescriptor[]> {
|
|
const result: Deno.PermissionDescriptor[] = [];
|
|
descriptors = Array.isArray(descriptor)
|
|
? descriptor
|
|
: [descriptor, ...descriptors];
|
|
for (const descriptor of descriptors) {
|
|
let state = (await Deno.permissions.query(descriptor)).state;
|
|
if (state === "prompt") {
|
|
state = (await Deno.permissions.request(descriptor)).state;
|
|
}
|
|
if (state === "granted") {
|
|
result.push(descriptor);
|
|
}
|
|
}
|
|
return result.length ? result : undefined;
|
|
}
|
|
|
|
/** Attempts to grant a set of permissions or rejects.
|
|
*
|
|
* await grantOrThrow({ name: "env" }, { name: "net" });
|
|
*
|
|
* If the permission can be prompted for, the function will attempt to prompt.
|
|
* If any of the permissions are denied, the function will reject for the first
|
|
* permission that is denied. If all permissions are granted, the function
|
|
* will resolve. */
|
|
export async function grantOrThrow(
|
|
...descriptors: Deno.PermissionDescriptor[]
|
|
): Promise<void>;
|
|
/** Attempts to grant a set of permissions or rejects.
|
|
*
|
|
* await grantOrThrow([{ name: "env" }, { name: "net" }]);
|
|
*
|
|
* If the permission can be prompted for, the function will attempt to prompt.
|
|
* If any of the permissions are denied, the function will reject mentioning the
|
|
* the denied permissions. If all permissions are granted, the function will
|
|
* resolve. */
|
|
export async function grantOrThrow(
|
|
descriptors: Deno.PermissionDescriptor[],
|
|
): Promise<void>;
|
|
export async function grantOrThrow(
|
|
descriptor: Deno.PermissionDescriptor[] | Deno.PermissionDescriptor,
|
|
...descriptors: Deno.PermissionDescriptor[]
|
|
): Promise<void> {
|
|
const denied: Deno.PermissionDescriptor[] = [];
|
|
descriptors = Array.isArray(descriptor)
|
|
? descriptor
|
|
: [descriptor, ...descriptors];
|
|
for (const descriptor of descriptors) {
|
|
const { state } = await Deno.permissions.request(descriptor);
|
|
if (state !== "granted") {
|
|
denied.push(descriptor);
|
|
}
|
|
}
|
|
if (denied.length) {
|
|
throw new PermissionDenied(
|
|
`The following permissions have not been granted:\n${
|
|
getPermissionString(
|
|
denied,
|
|
)
|
|
}`,
|
|
);
|
|
}
|
|
}
|