Drop privileges to respective uid

This commit is contained in:
Radon Rosborough 2020-06-22 15:28:27 -06:00
parent afad563d56
commit 91fe6ffd65
25 changed files with 716 additions and 243 deletions

View File

@ -2,6 +2,9 @@ FROM ubuntu:focal
ARG UID ARG UID
COPY scripts/docker-install-phase0.bash /tmp/
RUN /tmp/docker-install-phase0.bash
COPY scripts/docker-install-phase1.bash /tmp/ COPY scripts/docker-install-phase1.bash /tmp/
RUN /tmp/docker-install-phase1.bash RUN /tmp/docker-install-phase1.bash
@ -31,6 +34,7 @@ RUN /tmp/docker-install-phase6.bash "$UID"
USER docker USER docker
WORKDIR /home/docker WORKDIR /home/docker
RUN chmod go-rwx /home/docker
EXPOSE 6119 EXPOSE 6119
EXPOSE 6120 EXPOSE 6120

View File

@ -4,6 +4,9 @@ FROM ubuntu:focal
# prod, it's not actually read by anything. # prod, it's not actually read by anything.
ARG UID ARG UID
COPY scripts/docker-install-phase0.bash /tmp/
RUN /tmp/docker-install-phase0.bash
COPY scripts/docker-install-phase1.bash /tmp/ COPY scripts/docker-install-phase1.bash /tmp/
RUN /tmp/docker-install-phase1.bash RUN /tmp/docker-install-phase1.bash
@ -33,6 +36,7 @@ RUN /tmp/docker-install-phase6.bash
USER docker USER docker
WORKDIR /home/docker WORKDIR /home/docker
RUN chmod go-rwx /home/docker
EXPOSE 6119 EXPOSE 6119
EXPOSE 6120 EXPOSE 6120
@ -40,7 +44,7 @@ ENTRYPOINT ["/usr/local/bin/pid1.bash"]
COPY scripts/pid1.bash /usr/local/bin/ COPY scripts/pid1.bash /usr/local/bin/
CMD ["yarn", "run", "server"] CMD ["yarn", "run", "server"]
RUN mkdir /tmp/riju RUN mkdir /tmp/riju /tmp/riju/scripts
COPY --chown=docker:docker package.json yarn.lock /tmp/riju/ COPY --chown=docker:docker package.json yarn.lock /tmp/riju/
RUN cd /tmp/riju && yarn install RUN cd /tmp/riju && yarn install
COPY --chown=docker:docker webpack.config.js tsconfig.json tsconfig-webpack.json /tmp/riju/ COPY --chown=docker:docker webpack.config.js tsconfig.json tsconfig-webpack.json /tmp/riju/
@ -48,10 +52,11 @@ COPY --chown=docker:docker frontend /tmp/riju/frontend
RUN cd /tmp/riju && yarn run frontend RUN cd /tmp/riju && yarn run frontend
COPY --chown=docker:docker backend /tmp/riju/backend COPY --chown=docker:docker backend /tmp/riju/backend
RUN cd /tmp/riju && yarn run backend RUN cd /tmp/riju && yarn run backend
COPY --chown=docker:docker scripts/compile-system.bash /tmp/riju/scripts
COPY --chown=docker:docker system /tmp/riju/system COPY --chown=docker:docker system /tmp/riju/system
RUN cd /tmp/riju && RIJU_PRIVILEGED=1 yarn run system RUN cd /tmp/riju && RIJU_PRIVILEGED=1 yarn run system
COPY --chown=docker:docker . /home/docker/src COPY --chown=docker:docker . /home/docker/src
RUN cp -R /tmp/riju/* /home/docker/src/ && rm -rf /tmp/riju RUN sudo cp -a /tmp/riju/* /home/docker/src/ && rm -rf /tmp/riju
WORKDIR /home/docker/src WORKDIR /home/docker/src
RUN sudo deluser docker sudo RUN sudo deluser docker sudo

View File

@ -18,7 +18,7 @@ image-prod: ## Build Docker image for production
.PHONY: docker .PHONY: docker
docker: image-dev ## Run shell with source code and deps inside Docker docker: image-dev ## Run shell with source code and deps inside Docker
scripts/docker.bash run -it --rm -v "$(PWD):/home/docker/src" -p 6119:6119 -p 6120:6120 riju bash scripts/docker.bash run -it --rm -v "$(PWD):/home/docker/src" -p 6119:6119 -p 6120:6120 -h riju riju bash
.PHONY: deploy .PHONY: deploy
deploy: ## Deploy current master from GitHub to production deploy: ## Deploy current master from GitHub to production

View File

@ -18,18 +18,18 @@ documenting it until it has reached feature-completeness.
To run the webserver, all you need is Yarn. Just run `yarn install` as To run the webserver, all you need is Yarn. Just run `yarn install` as
usual to install dependencies. For production, it's: usual to install dependencies. For production, it's:
$ yarn backend $ yarn backend |- or run all three with 'yarn build'
$ yarn frontend $ yarn frontend |
$ yarn system $ yarn system |
$ yarn server $ yarn server
For development with file watching and automatic server rebooting and For development with file watching and automatic server rebooting and
all that, it's: all that, it's:
$ yarn backend-dev $ yarn backend-dev |- or run all four with 'yarn dev'
$ yarn frontend-dev $ yarn frontend-dev |
$ yarn system-dev $ yarn system-dev |
$ yarn server-dev $ yarn server-dev |
The webserver listens on `localhost:6119`. Now, although the server The webserver listens on `localhost:6119`. Now, although the server
itself will work, the only languages that will work are the ones that itself will work, the only languages that will work are the ones that

View File

@ -1,49 +1,48 @@
import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as WebSocket from "ws"; import * as WebSocket from "ws";
import * as mkdirp from "mkdirp";
import * as nodeCleanup from "node-cleanup";
import * as pty from "node-pty"; import * as pty from "node-pty";
import { IPty } from "node-pty"; import { IPty } from "node-pty";
import * as tmp from "tmp";
import { v4 as getUUID } from "uuid"; import { v4 as getUUID } from "uuid";
import { PRIVILEGED } from "./config";
import { LangConfig, langs } from "./langs"; import { LangConfig, langs } from "./langs";
import { borrowUser } from "./users"; import { borrowUser } from "./users";
import { callPrivileged, getEnv, spawnPrivileged } from "./util";
export class Session { export class Session {
id: string; uuid: string;
code: string; code: string;
config: LangConfig; config: LangConfig;
term: { pty: IPty | null; live: boolean }; term: { pty: IPty | null; live: boolean };
ws: WebSocket; ws: WebSocket;
tmpdir: string | null; homedir: string | null;
tmpdirCleanup: (() => void) | null;
uid: number | null; uid: number | null;
uidCleanup: (() => Promise<void>) | null; uidCleanup: (() => Promise<void>) | null;
log = (msg: string) => console.log(`[${this.id}] ${msg}`); log = (msg: string) => console.log(`[${this.uuid}] ${msg}`);
constructor(ws: WebSocket, lang: string) { constructor(ws: WebSocket, lang: string) {
this.id = getUUID(); this.uuid = getUUID();
this.log(`Creating session, language ${lang}`); this.log(`Creating session, language ${lang}`);
this.ws = ws; this.ws = ws;
this.config = langs[lang]; this.config = langs[lang];
this.term = { pty: null, live: false }; this.term = { pty: null, live: false };
this.code = ""; this.code = "";
this.tmpdir = null; this.homedir = null;
this.tmpdirCleanup = null;
this.uid = null; this.uid = null;
this.uidCleanup = null; this.uidCleanup = null;
ws.on("message", this.handleClientMessage); ws.on("message", this.handleClientMessage);
ws.on("close", () => ws.on("close", () =>
this.cleanup().catch((err) => this.cleanup().catch((err) => {
this.log(`Error during session cleanup: ${err}`) this.log(`Error during session cleanup`);
) console.log(err);
})
); );
nodeCleanup(); this.run().catch((err) => {
this.run().catch((err) => this.log(`Error while running: ${err}`)); this.log(`Error while setting up environment for pty`);
console.log(err);
});
} }
handleClientMessage = (event: string) => { handleClientMessage = (event: string) => {
let msg: any; let msg: any;
@ -81,9 +80,18 @@ export class Session {
({ uid: this.uid, cleanup: this.uidCleanup } = await borrowUser( ({ uid: this.uid, cleanup: this.uidCleanup } = await borrowUser(
this.log this.log
)); ));
this.log(`Borrowed uid ${this.uid}`);
} }
this.log(`Borrowed uid ${this.uid}`); const {
const { name, repl, main, suffix, compile, run, hacks } = this.config; name,
repl,
main,
suffix,
alwaysCreate,
compile,
run,
hacks,
} = this.config;
if (this.term.pty) { if (this.term.pty) {
this.term.pty.kill(); this.term.pty.kill();
this.term.live = false; this.term.live = false;
@ -93,20 +101,9 @@ export class Session {
} catch (err) { } catch (err) {
// //
} }
if (this.tmpdir == null) { if (this.homedir == null) {
({ path: this.tmpdir, cleanup: this.tmpdirCleanup } = await new Promise( this.homedir = `/tmp/riju/${this.uuid}`;
(resolve, reject) => await callPrivileged(["setup", `${this.uid}`, this.uuid], this.log);
tmp.dir(
{ unsafeCleanup: true, dir: "riju" },
(err, path, cleanup) => {
if (err) {
reject(err);
} else {
resolve({ path, cleanup });
}
}
)
));
} }
let cmdline: string; let cmdline: string;
if (!run) { if (!run) {
@ -117,22 +114,33 @@ export class Session {
code += suffix; code += suffix;
} }
if (main.includes("/")) { if (main.includes("/")) {
await mkdirp(path.dirname(path.resolve(this.tmpdir!, main))); await spawnPrivileged(
this.uid,
this.uuid,
["mkdir", "-p", path.dirname(path.resolve(this.homedir, main))],
this.log
);
} }
await new Promise((resolve, reject) => await spawnPrivileged(
fs.writeFile(path.resolve(this.tmpdir!, main), code, (err) => { this.uid,
if (err) { this.uuid,
reject(err); ["sh", "-c", `cat > ${path.resolve(this.homedir, main)}`],
} else { this.log,
resolve(); { input: code }
}
})
); );
cmdline = run; cmdline = run;
if (compile) { if (compile) {
cmdline = `( ${compile} ) && ( ${run} )`; cmdline = `( ${compile} ) && ( ${run} )`;
} }
} else if (repl) { } else if (repl) {
if (alwaysCreate) {
await spawnPrivileged(
this.uid,
this.uuid,
["touch", `${path.resolve(this.homedir, main)}`],
this.log
);
}
cmdline = repl; cmdline = repl;
} else { } else {
cmdline = `echo '${name} has no REPL, press Run to see it in action'`; cmdline = `echo '${name} has no REPL, press Run to see it in action'`;
@ -140,32 +148,38 @@ export class Session {
if (hacks && hacks.includes("ghci-config") && run) { if (hacks && hacks.includes("ghci-config") && run) {
if (this.code) { if (this.code) {
const contents = ":load Main\nmain\n"; const contents = ":load Main\nmain\n";
await new Promise((resolve, reject) => { await spawnPrivileged(
fs.writeFile(path.resolve(this.tmpdir!, ".ghci"), contents, (err) => { this.uid,
if (err) { this.uuid,
reject(err); ["sh", "-c", `cat > ${path.resolve(this.homedir, ".ghci")}`],
} else { this.log,
resolve(); { input: contents }
} );
});
});
} else { } else {
await new Promise((resolve, reject) => await spawnPrivileged(
fs.unlink(path.resolve(this.tmpdir!, ".ghci"), (err) => { this.uid,
if (err && err.code !== "ENOENT") { this.uuid,
reject(err); ["rm", "-f", path.resolve(this.homedir, ".ghci")],
} else { this.log
resolve();
}
})
); );
} }
} }
const args = PRIVILEGED
? [
"/home/docker/src/system/out/riju-system-privileged",
"spawn",
`${this.uid}`,
`${this.uuid}`,
"bash",
"-c",
cmdline,
]
: ["bash", "-c", cmdline];
const env = getEnv(this.uuid);
const term = { const term = {
pty: pty.spawn("bash", ["-c", cmdline], { pty: pty.spawn(args[0], args.slice(1), {
name: "xterm-color", name: "xterm-color",
cwd: this.tmpdir!, env,
env: process.env as { [key: string]: string },
}), }),
live: true, live: true,
}; };
@ -186,8 +200,8 @@ export class Session {
}; };
cleanup = async () => { cleanup = async () => {
this.log(`Cleaning up session`); this.log(`Cleaning up session`);
if (this.tmpdirCleanup) { if (this.homedir) {
this.tmpdirCleanup(); await callPrivileged(["teardown", this.uuid], this.log);
} }
if (this.uidCleanup) { if (this.uidCleanup) {
await this.uidCleanup(); await this.uidCleanup();

3
backend/src/config.ts Normal file
View File

@ -0,0 +1,3 @@
import * as process from "process";
export const PRIVILEGED = process.env.RIJU_PRIVILEGED ? true : false;

View File

@ -6,6 +6,7 @@ export interface LangConfig {
main: string; main: string;
prefix?: string; prefix?: string;
suffix?: string; suffix?: string;
alwaysCreate?: boolean;
compile?: string; compile?: string;
run: string; run: string;
template: string; template: string;
@ -220,7 +221,7 @@ int main() {
monacoLang: "csharp", monacoLang: "csharp",
main: "main.cs", main: "main.cs",
compile: "mcs main.cs", compile: "mcs main.cs",
run: "./main.exe", run: "mono main.exe",
template: `class main { template: `class main {
static void Main(string[] args) { static void Main(string[] args) {
System.Console.WriteLine("Hello, world!"); System.Console.WriteLine("Hello, world!");
@ -326,9 +327,9 @@ output = "Hello, world!"
aliases: ["elv"], aliases: ["elv"],
name: "Elvish", name: "Elvish",
monacoLang: "plaintext", monacoLang: "plaintext",
repl: "SHELL=/usr/bin/elvish HOME=. elvish", repl: `SHELL=/usr/bin/elvish HOME="$PWD" elvish`,
main: ".elvish/rc.elv", main: ".elvish/rc.elv",
run: "SHELL=/usr/bin/elvish HOME=. elvish", run: `SHELL=/usr/bin/elvish HOME="$PWD" elvish`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
}, },
@ -451,8 +452,8 @@ main = putStrLn "Hello, world!"
repl: "ink", repl: "ink",
main: "main.ink", main: "main.ink",
run: "ink main.ink; ink", run: "ink main.ink; ink",
template: `std := load('../../opt/ink/std') template: `std := load('../../../opt/ink/std')
str := load('../../opt/ink/str') str := load('../../../opt/ink/str')
log := std.log log := std.log
@ -535,9 +536,9 @@ PLEASE GIVE UP
aliases: ["kshell"], aliases: ["kshell"],
name: "Ksh", name: "Ksh",
monacoLang: "shell", monacoLang: "shell",
repl: "SHELL=/usr/bin/ksh HOME=. ksh", repl: `SHELL=/usr/bin/ksh HOME="$PWD" ksh`,
main: ".kshrc", main: ".kshrc",
run: "SHELL=/usr/bin/ksh HOME=. ksh", run: `SHELL=/usr/bin/ksh HOME="$PWD" ksh`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
}, },
@ -830,9 +831,9 @@ binding_irb.run(IRB.conf)
aliases: ["shell", "posix", "posixsh", "ash", "dash", "posh"], aliases: ["shell", "posix", "posixsh", "ash", "dash", "posh"],
name: "Sh", name: "Sh",
monacoLang: "shell", monacoLang: "shell",
repl: "SHELL=/usr/bin/sh HOME=. posh -l", repl: `SHELL=/usr/bin/sh HOME="$PWD" posh -l`,
main: ".profile", main: ".profile",
run: "SHELL=/usr/bin/sh HOME=. posh -l", run: `SHELL=/usr/bin/sh HOME="$PWD" posh -l`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
}, },
@ -992,7 +993,7 @@ END
monacoLang: "tcl", monacoLang: "tcl",
repl: "tclsh", repl: "tclsh",
main: ".tclshrc", main: ".tclshrc",
run: "HOME=. tclsh", run: `HOME="$PWD" tclsh`,
template: `puts {Hello, world!} template: `puts {Hello, world!}
`, `,
}, },
@ -1000,9 +1001,9 @@ END
aliases: ["tcshell", "tcshrc"], aliases: ["tcshell", "tcshrc"],
name: "Tcsh", name: "Tcsh",
monacoLang: "shell", monacoLang: "shell",
repl: "SHELL=/usr/bin/tcsh HOME=. tcsh", repl: `SHELL=/usr/bin/tcsh HOME="$PWD" tcsh`,
main: ".tcshrc", main: ".tcshrc",
run: "SHELL=/usr/bin/tcsh HOME=. tcsh", run: `SHELL=/usr/bin/tcsh HOME="$PWD" tcsh`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
}, },
@ -1104,7 +1105,8 @@ message:
monacoLang: "shell", monacoLang: "shell",
repl: "SHELL=/usr/bin/zsh zsh", repl: "SHELL=/usr/bin/zsh zsh",
main: ".zshrc", main: ".zshrc",
run: "SHELL=/usr/bin/zsh ZDOTDIR=. zsh", alwaysCreate: true,
run: `SHELL=/usr/bin/zsh ZDOTDIR="$PWD" zsh`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
}, },

View File

@ -1,16 +1,17 @@
import { spawn } from "child_process"; import { spawn } from "child_process";
import * as fs from "fs"; import * as fs from "fs";
import * as process from "process";
import * as AsyncLock from "async-lock"; import * as AsyncLock from "async-lock";
import * as _ from "lodash"; import * as _ from "lodash";
import * as parsePasswd from "parse-passwd"; import * as parsePasswd from "parse-passwd";
import { PRIVILEGED } from "./config";
import { callPrivileged } from "./util";
// Keep in sync with system/src/riju-system-privileged.c // Keep in sync with system/src/riju-system-privileged.c
const MIN_UID = 2000; const MIN_UID = 2000;
const MAX_UID = 65000; const MAX_UID = 65000;
const PRIVILEGED = process.env.RIJU_PRIVILEGED ? true : false;
const CUR_UID = parseInt(process.env.UID || "") || null; const CUR_UID = parseInt(process.env.UID || "") || null;
let availIds: number[] | null = null; let availIds: number[] | null = null;
@ -29,7 +30,7 @@ async function readExistingUsers(log: (msg: string) => void) {
}) })
) )
) )
.filter(({ username }) => username.startsWith("riju_user")) .filter(({ username }) => username.startsWith("riju"))
.map(({ uid }) => parseInt(uid)) .map(({ uid }) => parseInt(uid))
.filter((uid) => !isNaN(uid) && uid >= MIN_UID && uid < MAX_UID); .filter((uid) => !isNaN(uid) && uid >= MIN_UID && uid < MAX_UID);
nextId = (_.max(availIds) || MIN_UID - 1) + 1; nextId = (_.max(availIds) || MIN_UID - 1) + 1;
@ -40,33 +41,11 @@ async function createUser(log: (msg: string) => void): Promise<number> {
if (nextId! >= MAX_UID) { if (nextId! >= MAX_UID) {
throw new Error("too many users"); throw new Error("too many users");
} }
return await new Promise((resolve, reject) => { const uid = nextId!;
const uid = nextId!; await callPrivileged(["useradd", `${uid}`], log);
const useradd = spawn("system/out/riju-system-privileged", [ log(`Created new user with ID ${uid}`);
"useradd", nextId! += 1;
`${uid}`, return uid;
]);
let output = "";
useradd.stdout.on("data", (data) => {
output += `${data}`;
});
useradd.stderr.on("data", (data) => {
output += `${data}`;
});
useradd.on("close", (code) => {
output = output.trim();
if (output) {
log("Output from useradd:\n" + output);
}
if (code === 0) {
log(`Created new user with ID ${uid}`);
nextId! += 1;
resolve(uid);
} else {
reject(`useradd failed with error code ${code}`);
}
});
});
} }
export async function borrowUser(log: (msg: string) => void) { export async function borrowUser(log: (msg: string) => void) {

83
backend/src/util.ts Normal file
View File

@ -0,0 +1,83 @@
import { spawn, SpawnOptions } from "child_process";
import * as process from "process";
interface Options extends SpawnOptions {
input?: string;
}
export function getEnv(uuid: string) {
const cwd = `/tmp/riju/${uuid}`;
return {
HOME: cwd,
HOSTNAME: "riju",
LANG: "C.UTF-8",
LC_ALL: "C.UTF-8",
PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin",
PWD: cwd,
SHELL: "/usr/bin/bash",
TERM: "xterm-color",
};
}
export async function call(
args: string[],
log: (msg: string) => void,
options?: Options
) {
options = options || {};
const input = options.input;
delete options.input;
const proc = spawn(args[0], args.slice(1), options);
if (input) {
proc.stdin!.end(input);
}
let output = "";
proc.stdout!.on("data", (data: Buffer) => {
output += `${data}`;
});
proc.stderr!.on("data", (data: Buffer) => {
output += `${data}`;
});
await new Promise((resolve, reject) => {
proc.on("error", reject);
proc.on("close", (code: number) => {
output = output.trim();
if (output) {
log(`Output from ${args[0]}:\n` + output);
}
if (code === 0) {
resolve();
} else {
reject(`command ${args[0]} failed with error code ${code}`);
}
});
});
}
export async function callPrivileged(
args: string[],
log: (msg: string) => void,
options?: Options
) {
await call(
["/home/docker/src/system/out/riju-system-privileged"].concat(args),
log,
options
);
}
export async function spawnPrivileged(
uid: number,
uuid: string,
args: string[],
log: (msg: string) => void,
options?: Options
) {
options = options || {};
options.env = getEnv(uuid);
await callPrivileged(
["spawn", `${uid}`, `${uuid}`].concat(args),
log,
options
);
}

View File

@ -10,92 +10,98 @@ interface RijuConfig {
template: string; template: string;
} }
const config: RijuConfig = (window as any).rijuConfig; async function main() {
const config: RijuConfig = (window as any).rijuConfig;
const term = new Terminal(); const term = new Terminal();
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
term.loadAddon(fitAddon); term.loadAddon(fitAddon);
term.open(document.getElementById("terminal")!); term.open(document.getElementById("terminal")!);
fitAddon.fit(); fitAddon.fit();
window.addEventListener("resize", () => fitAddon.fit()); window.addEventListener("resize", () => fitAddon.fit());
term.write("Connecting to server..."); await new Promise((resolve) =>
term.write("Connecting to server...", resolve)
const initialRetryDelayMs = 200;
let retryDelayMs = initialRetryDelayMs;
function tryConnect() {
console.log("Connecting to server...");
socket = new WebSocket(
(document.location.protocol === "http:" ? "ws://" : "wss://") +
document.location.host +
`/api/v1/ws?lang=${encodeURIComponent(config.id)}`
); );
socket.addEventListener("open", () => {
console.log("Successfully connected to server"); const initialRetryDelayMs = 200;
}); let retryDelayMs = initialRetryDelayMs;
socket.addEventListener("message", (event: MessageEvent) => {
let message: any; function tryConnect() {
try { console.log("Connecting to server...");
message = JSON.parse(event.data); socket = new WebSocket(
} catch (err) { (document.location.protocol === "http:" ? "ws://" : "wss://") +
console.error("Malformed message from server:", event.data); document.location.host +
return; `/api/v1/ws?lang=${encodeURIComponent(config.id)}`
} );
if (message?.event && message?.event !== "error") { socket.addEventListener("open", () => {
retryDelayMs = initialRetryDelayMs; console.log("Successfully connected to server");
} });
switch (message?.event) { socket.addEventListener("message", (event: MessageEvent) => {
case "terminalClear": let message: any;
term.reset(); try {
message = JSON.parse(event.data);
} catch (err) {
console.error("Malformed message from server:", event.data);
return; return;
case "terminalOutput": }
if (typeof message.output !== "string") { if (message?.event && message?.event !== "error") {
retryDelayMs = initialRetryDelayMs;
}
switch (message?.event) {
case "terminalClear":
term.reset();
return;
case "terminalOutput":
if (typeof message.output !== "string") {
console.error("Unexpected message from server:", message);
return;
}
term.write(message.output);
return;
default:
console.error("Unexpected message from server:", message); console.error("Unexpected message from server:", message);
return; return;
} }
term.write(message.output); });
return; socket.addEventListener("close", (event: CloseEvent) => {
default: if (event.wasClean) {
console.error("Unexpected message from server:", message); console.log("Connection closed cleanly");
return; } else {
} console.error("Connection died");
}
scheduleConnect();
});
}
function scheduleConnect() {
const delay = retryDelayMs * Math.random();
console.log(`Trying to reconnect in ${Math.floor(delay)}ms`);
setTimeout(tryConnect, delay);
retryDelayMs *= 2;
}
let socket: WebSocket | null = null;
tryConnect();
term.onData(
(data) =>
socket &&
socket.send(JSON.stringify({ event: "terminalInput", input: data }))
);
const editor = monaco.editor.create(document.getElementById("editor")!, {
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 0 },
}); });
socket.addEventListener("close", (event: CloseEvent) => { window.addEventListener("resize", () => editor.layout());
if (event.wasClean) { editor.getModel()!.setValue(config.template);
console.log("Connection closed cleanly"); monaco.editor.setModelLanguage(editor.getModel()!, config.monacoLang);
} else {
console.error("Connection died"); document.getElementById("runButton")!.addEventListener("click", () => {
} socket?.send(JSON.stringify({ event: "runCode", code: editor.getValue() }));
scheduleConnect();
}); });
} }
function scheduleConnect() { main().catch(console.error);
const delay = retryDelayMs * Math.random();
console.log(`Trying to reconnect in ${Math.floor(delay)}ms`);
setTimeout(tryConnect, delay);
retryDelayMs *= 2;
}
let socket: WebSocket | null = null;
tryConnect();
term.onData(
(data) =>
socket &&
socket.send(JSON.stringify({ event: "terminalInput", input: data }))
);
const editor = monaco.editor.create(document.getElementById("editor")!, {
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 0 },
});
window.addEventListener("resize", () => editor.layout());
editor.getModel()!.setValue(config.template);
monaco.editor.setModelLanguage(editor.getModel()!, config.monacoLang);
document.getElementById("runButton")!.addEventListener("click", () => {
socket?.send(JSON.stringify({ event: "runCode", code: editor.getValue() }));
});

View File

@ -1,6 +1,6 @@
{ {
"name": "riju", "name": "riju",
"version": "0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"dependencies": { "dependencies": {
@ -11,6 +11,7 @@
"@types/lodash": "^4.14.155", "@types/lodash": "^4.14.155",
"@types/mkdirp": "^1.0.1", "@types/mkdirp": "^1.0.1",
"@types/parse-passwd": "^1.0.0", "@types/parse-passwd": "^1.0.0",
"@types/rimraf": "^3.0.0",
"@types/tmp": "^0.2.0", "@types/tmp": "^0.2.0",
"@types/uuid": "^8.0.0", "@types/uuid": "^8.0.0",
"app-root-path": "^3.0.0", "app-root-path": "^3.0.0",
@ -21,13 +22,12 @@
"express-ws": "^4.0.0", "express-ws": "^4.0.0",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"mkdirp": "^1.0.4",
"monaco-editor": "^0.20.0", "monaco-editor": "^0.20.0",
"node-cleanup": "^2.1.2", "node-cleanup": "^2.1.2",
"node-pty": "^0.9.0", "node-pty": "^0.9.0",
"npm-run-all": "^4.1.5",
"parse-passwd": "^1.0.0", "parse-passwd": "^1.0.0",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"tmp": "^0.2.1",
"ts-loader": "^7.0.5", "ts-loader": "^7.0.5",
"typescript": "^3.9.5", "typescript": "^3.9.5",
"uuid": "^8.1.0", "uuid": "^8.1.0",
@ -38,12 +38,14 @@
}, },
"scripts": { "scripts": {
"backend": "tsc", "backend": "tsc",
"backend-dev": "tsc --watch", "backend-dev": "tsc --watch --preserveWatchOutput",
"frontend": "webpack --production", "frontend": "webpack --production",
"frontend-dev": "webpack --development --watch", "frontend-dev": "webpack --development --watch",
"server": "scripts/setup.bash && node backend/out/server.js", "server": "scripts/setup.bash && node backend/out/server.js",
"server-dev": "watchexec -w backend/out -r 'scripts/setup.bash && node backend/out/server.js'", "server-dev": "watchexec -w backend/out -r 'scripts/setup.bash && node backend/out/server.js'",
"system": "scripts/compile-system.bash", "system": "scripts/compile-system.bash",
"system-dev": "watchexec -w system/src -n scripts/compile-system.bash" "system-dev": "watchexec -w system/src -n scripts/compile-system.bash",
"build": "run-s backend frontend system",
"dev": "run-p backend-dev frontend-dev system-dev server-dev"
} }
} }

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
set -o pipefail
set -x
export DEBIAN_FRONTEND=noninteractive
apt-get update
(yes || true) | unminimize
rm -rf /var/lib/apt/lists/*
rm "$0"

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
dpkg --add-architecture i386 dpkg --add-architecture i386

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
packages=" packages="

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
packages=" packages="

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
packages=" packages="

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
packages=" packages="

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
packages=" packages="

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
npm config set unsafe-perm true npm config set unsafe-perm true
PERL_MM_USE_DEFAULT=1 cpan App::cpanminus PERL_MM_USE_DEFAULT=1 cpan App::cpanminus

View File

@ -2,6 +2,7 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
# Needed for project infrastructure # Needed for project infrastructure
cd /tmp cd /tmp

View File

@ -2,19 +2,22 @@
set -e set -e
set -o pipefail set -o pipefail
set -x
uid="$1" uid="$1"
rm -rf /tmp/hsperfdata_root rm -rf /tmp/hsperfdata_root
if [[ -n "$uid" ]] && (( "$uid" != 0 )); then if [[ -n "$uid" ]] && (( "$uid" != 0 )); then
useradd --uid="$uid" --create-home --groups sudo docker useradd --uid="$uid" --password "!" --create-home --groups sudo docker
passwd -d docker
else else
useradd --create-home --groups sudo docker useradd --password "!" --create-home --groups sudo docker
passwd -d docker
fi fi
tee /etc/sudoers.d/99-passwordless >/dev/null <<"EOF"
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
EOF
touch /home/docker/.zshrc touch /home/docker/.zshrc
chown docker:docker /home/docker/.zshrc chown docker:docker /home/docker/.zshrc

View File

@ -18,4 +18,4 @@ else
fi fi
docker run ${it} -e TLS -e TLS_PRIVATE_KEY -e TLS_CERTIFICATE \ docker run ${it} -e TLS -e TLS_PRIVATE_KEY -e TLS_CERTIFICATE \
--rm -p 0.0.0.0:80:6119 -p 0.0.0.0:443:6120 riju:prod --rm -p 0.0.0.0:80:6119 -p 0.0.0.0:443:6120 -h riju riju:prod

View File

@ -4,4 +4,7 @@ set -e
set -o pipefail set -o pipefail
mkdir -p /tmp/riju mkdir -p /tmp/riju
rm -rf /tmp/riju/* if [[ -x system/out/riju-system-privileged ]]; then
system/out/riju-system-privileged teardown "*"
fi
chmod a=x,u=rwx /tmp/riju

View File

@ -1,14 +1,18 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <errno.h>
#include <grp.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
// Keep in sync with backend/src/users.ts // Keep in sync with backend/src/users.ts
const int MIN_UID = 2000; const int MIN_UID = 2000;
const int MAX_UID = 65000; const int MAX_UID = 65000;
void die(const char *msg) void die(char *msg)
{ {
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
exit(1); exit(1);
@ -17,19 +21,84 @@ void die(const char *msg)
void die_with_usage() void die_with_usage()
{ {
die("usage:\n" die("usage:\n"
" riju-system-privileged useradd UID"); " riju-system-privileged useradd UID\n"
" riju-system-privileged spawn UID CMDLINE...\n"
" riju-system-privileged setup UID UUID\n"
" riju-system-privileged teardown UUID");
}
int parseUID(char *str)
{
char *endptr;
long uid = strtol(str, &endptr, 10);
if (!*str || *endptr)
die("uid must be an integer");
if (uid < MIN_UID || uid >= MAX_UID)
die("uid is out of range");
return uid;
}
char *parseUUID(char *uuid)
{
if (!*uuid)
die("illegal uuid");
for (char *ptr = uuid; *ptr; ++ptr)
if (!((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || *ptr == '-'))
die("illegal uuid");
return uuid;
} }
void useradd(int uid) void useradd(int uid)
{ {
char *cmdline; char *cmdline;
if (asprintf(&cmdline, "useradd -M -N -l -r -u %1$d riju_user%1$d", uid) < 0) { if (asprintf(&cmdline, "groupadd -g %1$d riju%1$d", uid) < 0)
die("asprintf failed"); die("asprintf failed");
}
int status = system(cmdline); int status = system(cmdline);
if (status) { if (status)
die("groupadd failed");
if (asprintf(&cmdline, "useradd -M -N -l -r -u %1$d -g %1$d -p '!' riju%1$d", uid) < 0)
die("asprintf failed");
status = system(cmdline);
if (status)
die("useradd failed"); die("useradd failed");
} }
void spawn(int uid, char *uuid, char **cmdline)
{
char *cwd;
if (asprintf(&cwd, "/tmp/riju/%s", uuid) < 0)
die("asprintf failed");
if (chdir(cwd) < 0)
die("chdir failed");
if (setgid(uid) < 0)
die("setgid failed");
if (setgroups(0, NULL) < 0)
die("setgroups failed");
if (setuid(uid) < 0)
die("setuid failed");
umask(077);
execvp(cmdline[0], cmdline);
die("execvp failed");
}
void setup(int uid, char *uuid)
{
char *cmdline;
if (asprintf(&cmdline, "install -d -o riju%1$d -g riju%1$d -m 700 /tmp/riju/%2$s", uid, uuid) < 0)
die("asprintf failed");
int status = system(cmdline);
if (status)
die("install failed");
}
void teardown(char *uuid)
{
char *cmdline;
if (asprintf(&cmdline, "rm -rf /tmp/riju/%s", uuid) < 0)
die("asprintf failed");
int status = system(cmdline);
if (status)
die("rm failed");
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -40,15 +109,28 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "useradd")) { if (!strcmp(argv[1], "useradd")) {
if (argc != 3) if (argc != 3)
die_with_usage(); die_with_usage();
char *endptr; useradd(parseUID(argv[2]));
long uid = strtol(argv[2], &endptr, 10); return 0;
if (!argv[2] || *endptr) { }
die("uid must be an integer"); if (!strcmp(argv[1], "spawn")) {
} if (argc < 5)
if (uid < MIN_UID || uid >= MAX_UID) { die_with_usage();
die("uid is out of range"); spawn(parseUID(argv[2]), parseUUID(argv[3]), &argv[4]);
} return 0;
useradd(uid); }
if (!strcmp(argv[1], "setup")) {
if (argc != 4)
die_with_usage();
int uid = parseUID(argv[2]);
char *uuid = parseUUID(argv[3]);
setup(uid, uuid);
return 0;
}
if (!strcmp(argv[1], "teardown")) {
if (argc != 3)
die_with_usage();
char *uuid = strcmp(argv[2], "*") ? parseUUID(argv[2]) : "*";
teardown(uuid);
return 0; return 0;
} }
die_with_usage(); die_with_usage();

313
yarn.lock
View File

@ -55,6 +55,14 @@
"@types/qs" "*" "@types/qs" "*"
"@types/serve-static" "*" "@types/serve-static" "*"
"@types/glob@*":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987"
integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==
dependencies:
"@types/minimatch" "*"
"@types/node" "*"
"@types/json-schema@^7.0.4": "@types/json-schema@^7.0.4":
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
@ -70,6 +78,11 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.2.tgz#857a118d8634c84bba7ae14088e4508490cd5da5" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.2.tgz#857a118d8634c84bba7ae14088e4508490cd5da5"
integrity sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q== integrity sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/mkdirp@^1.0.1": "@types/mkdirp@^1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.1.tgz#0930b948914a78587de35458b86c907b6e98bbf6" resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-1.0.1.tgz#0930b948914a78587de35458b86c907b6e98bbf6"
@ -97,6 +110,14 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/rimraf@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f"
integrity sha512-7WhJ0MdpFgYQPXlF4Dx+DhgvlPCfz/x5mHaeDQAKhcenvQP1KCpLQ18JklAqeGMYSAT2PxLpzd0g2/HE7fj7hQ==
dependencies:
"@types/glob" "*"
"@types/node" "*"
"@types/serve-static@*": "@types/serve-static@*":
version "1.13.4" version "1.13.4"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.4.tgz#6662a93583e5a6cabca1b23592eb91e12fa80e7c" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.4.tgz#6662a93583e5a6cabca1b23592eb91e12fa80e7c"
@ -663,7 +684,7 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
chalk@2.4.2, chalk@^2.3.0, chalk@^2.4.2: chalk@2.4.2, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -880,7 +901,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
safe-buffer "^5.0.1" safe-buffer "^5.0.1"
sha.js "^2.4.8" sha.js "^2.4.8"
cross-spawn@6.0.5, cross-spawn@^6.0.0: cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5" version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@ -954,6 +975,13 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
object-keys "^1.0.12"
define-property@^0.2.5: define-property@^0.2.5:
version "0.2.5" version "0.2.5"
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
@ -1100,6 +1128,39 @@ errno@^0.1.3, errno@~0.1.7:
dependencies: dependencies:
prr "~1.0.1" prr "~1.0.1"
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
es-abstract@^1.17.0-next.1, es-abstract@^1.17.5:
version "1.17.6"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==
dependencies:
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.1"
is-callable "^1.2.0"
is-regex "^1.1.0"
object-inspect "^1.7.0"
object-keys "^1.1.1"
object.assign "^4.1.0"
string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1"
es-to-primitive@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
dependencies:
is-callable "^1.1.4"
is-date-object "^1.0.1"
is-symbol "^1.0.2"
escape-html@~1.0.3: escape-html@~1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@ -1410,6 +1471,11 @@ fsevents@~2.1.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-caller-file@^2.0.1: get-caller-file@^2.0.1:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@ -1500,6 +1566,11 @@ has-flag@^3.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-symbols@^1.0.0, has-symbols@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
has-value@^0.3.1: has-value@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@ -1531,6 +1602,13 @@ has-values@^1.0.0:
is-number "^3.0.0" is-number "^3.0.0"
kind-of "^4.0.0" kind-of "^4.0.0"
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
hash-base@^3.0.0: hash-base@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
@ -1564,6 +1642,11 @@ homedir-polyfill@^1.0.1:
dependencies: dependencies:
parse-passwd "^1.0.0" parse-passwd "^1.0.0"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
http-errors@1.7.2: http-errors@1.7.2:
version "1.7.2" version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
@ -1695,6 +1778,11 @@ is-accessor-descriptor@^1.0.0:
dependencies: dependencies:
kind-of "^6.0.0" kind-of "^6.0.0"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-binary-path@^1.0.0: is-binary-path@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
@ -1714,6 +1802,11 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-callable@^1.1.4, is-callable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
is-data-descriptor@^0.1.4: is-data-descriptor@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@ -1728,6 +1821,11 @@ is-data-descriptor@^1.0.0:
dependencies: dependencies:
kind-of "^6.0.0" kind-of "^6.0.0"
is-date-object@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
is-descriptor@^0.1.0: is-descriptor@^0.1.0:
version "0.1.6" version "0.1.6"
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
@ -1801,11 +1899,25 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies: dependencies:
isobject "^3.0.1" isobject "^3.0.1"
is-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff"
integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==
dependencies:
has-symbols "^1.0.1"
is-stream@^1.1.0: is-stream@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
is-symbol@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==
dependencies:
has-symbols "^1.0.1"
is-windows@^1.0.1, is-windows@^1.0.2: is-windows@^1.0.1, is-windows@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@ -1848,7 +1960,7 @@ jake@^10.6.1:
filelist "^1.0.1" filelist "^1.0.1"
minimatch "^3.0.4" minimatch "^3.0.4"
json-parse-better-errors@^1.0.2: json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
@ -1903,6 +2015,16 @@ lcid@^2.0.0:
dependencies: dependencies:
invert-kv "^2.0.0" invert-kv "^2.0.0"
load-json-file@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
dependencies:
graceful-fs "^4.1.2"
parse-json "^4.0.0"
pify "^3.0.0"
strip-bom "^3.0.0"
loader-runner@^2.4.0: loader-runner@^2.4.0:
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
@ -2021,6 +2143,11 @@ memory-fs@^0.5.0:
errno "^0.1.3" errno "^0.1.3"
readable-stream "^2.0.1" readable-stream "^2.0.1"
memorystream@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
merge-descriptors@1.0.1: merge-descriptors@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@ -2141,11 +2268,6 @@ mkdirp@^0.5.1, mkdirp@^0.5.3:
dependencies: dependencies:
minimist "^1.2.5" minimist "^1.2.5"
mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
monaco-editor@^0.20.0: monaco-editor@^0.20.0:
version "0.20.0" version "0.20.0"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
@ -2251,6 +2373,16 @@ node-pty@^0.9.0:
dependencies: dependencies:
nan "^2.14.0" nan "^2.14.0"
normalize-package-data@^2.3.2:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
dependencies:
hosted-git-info "^2.1.4"
resolve "^1.10.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
normalize-path@^2.1.1: normalize-path@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@ -2263,6 +2395,21 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
npm-run-all@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
dependencies:
ansi-styles "^3.2.1"
chalk "^2.4.1"
cross-spawn "^6.0.5"
memorystream "^0.3.1"
minimatch "^3.0.4"
pidtree "^0.3.0"
read-pkg "^3.0.0"
shell-quote "^1.6.1"
string.prototype.padend "^3.0.0"
npm-run-path@^2.0.0: npm-run-path@^2.0.0:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@ -2284,6 +2431,16 @@ object-copy@^0.1.0:
define-property "^0.2.5" define-property "^0.2.5"
kind-of "^3.0.3" kind-of "^3.0.3"
object-inspect@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
object-visit@^1.0.0: object-visit@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
@ -2291,6 +2448,16 @@ object-visit@^1.0.0:
dependencies: dependencies:
isobject "^3.0.0" isobject "^3.0.0"
object.assign@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
has-symbols "^1.0.0"
object-keys "^1.0.11"
object.pick@^1.3.0: object.pick@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@ -2386,6 +2553,14 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5:
pbkdf2 "^3.0.3" pbkdf2 "^3.0.3"
safe-buffer "^5.1.1" safe-buffer "^5.1.1"
parse-json@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
dependencies:
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
parse-passwd@^1.0.0: parse-passwd@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
@ -2426,11 +2601,23 @@ path-key@^2.0.0, path-key@^2.0.1:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
path-to-regexp@0.1.7: path-to-regexp@0.1.7:
version "0.1.7" version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-type@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
dependencies:
pify "^3.0.0"
pbkdf2@^3.0.3: pbkdf2@^3.0.3:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
@ -2447,6 +2634,16 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
pidtree@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
pify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pify@^4.0.1: pify@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
@ -2645,6 +2842,15 @@ raw-body@2.4.0:
iconv-lite "0.4.24" iconv-lite "0.4.24"
unpipe "1.0.0" unpipe "1.0.0"
read-pkg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
dependencies:
load-json-file "^4.0.0"
normalize-package-data "^2.3.2"
path-type "^3.0.0"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7" version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
@ -2741,6 +2947,13 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@^1.10.0:
version "1.17.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==
dependencies:
path-parse "^1.0.6"
ret@~0.1.10: ret@~0.1.10:
version "0.1.15" version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@ -2753,13 +2966,6 @@ rimraf@^2.5.4, rimraf@^2.6.3:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
rimraf@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
dependencies:
glob "^7.1.3"
ripemd160@^2.0.0, ripemd160@^2.0.1: ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@ -2815,7 +3021,7 @@ schema-utils@^2.6.5, schema-utils@^2.6.6:
ajv "^6.12.2" ajv "^6.12.2"
ajv-keywords "^3.4.1" ajv-keywords "^3.4.1"
semver@^5.5.0, semver@^5.6.0: "semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
version "5.7.1" version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@ -2906,6 +3112,11 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
shell-quote@^1.6.1:
version "1.7.2"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
signal-exit@^3.0.0: signal-exit@^3.0.0:
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@ -2980,6 +3191,32 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
spdx-correct@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
dependencies:
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
spdx-exceptions@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
spdx-expression-parse@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.5"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
split-string@^3.0.1, split-string@^3.0.2: split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@ -3048,6 +3285,30 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0" is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0" strip-ansi "^5.1.0"
string.prototype.padend@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3"
integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
string.prototype.trimend@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.5"
string.prototype.trimstart@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54"
integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.5"
string_decoder@^1.0.0, string_decoder@^1.1.1: string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
@ -3069,6 +3330,11 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies: dependencies:
ansi-regex "^4.1.0" ansi-regex "^4.1.0"
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
strip-eof@^1.0.0: strip-eof@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@ -3140,13 +3406,6 @@ timers-browserify@^2.0.4:
dependencies: dependencies:
setimmediate "^1.0.4" setimmediate "^1.0.4"
tmp@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
dependencies:
rimraf "^3.0.0"
to-arraybuffer@^1.0.0: to-arraybuffer@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@ -3334,6 +3593,14 @@ v8-compile-cache@2.0.3:
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
dependencies:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
vary@~1.1.2: vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"