mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
fix: Js deep dir (#1784)
* fix: Js deep dir * Delete broken.log * Delete test.log * fix: Remove the == parent
This commit is contained in:
588
backend/Cargo.lock
generated
588
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -374,3 +374,47 @@ async fn js_action_test_rename() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn js_action_test_deep_dir() {
|
||||||
|
let js_action = JsProcedure { args: vec![] };
|
||||||
|
let path: PathBuf = "test/js_action_execute/"
|
||||||
|
.parse::<PathBuf>()
|
||||||
|
.unwrap()
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap();
|
||||||
|
let package_id = "test-package".parse().unwrap();
|
||||||
|
let package_version: Version = "0.3.0.3".parse().unwrap();
|
||||||
|
let name = ProcedureName::Action("test-deep-dir".parse().unwrap());
|
||||||
|
let volumes: Volumes = serde_json::from_value(serde_json::json!({
|
||||||
|
"main": {
|
||||||
|
"type": "data"
|
||||||
|
},
|
||||||
|
"compat": {
|
||||||
|
"type": "assets"
|
||||||
|
},
|
||||||
|
"filebrowser" :{
|
||||||
|
"package-id": "filebrowser",
|
||||||
|
"path": "data",
|
||||||
|
"readonly": true,
|
||||||
|
"type": "pointer",
|
||||||
|
"volume-id": "main",
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
|
let input: Option<serde_json::Value> = None;
|
||||||
|
let timeout = Some(Duration::from_secs(10));
|
||||||
|
js_action
|
||||||
|
.execute::<serde_json::Value, serde_json::Value>(
|
||||||
|
&path,
|
||||||
|
&package_id,
|
||||||
|
&package_version,
|
||||||
|
name,
|
||||||
|
&volumes,
|
||||||
|
input,
|
||||||
|
timeout,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,45 +94,45 @@ export async function getConfig(effects) {
|
|||||||
const metadata = await effects.metadata({
|
const metadata = await effects.metadata({
|
||||||
path: "./test.log",
|
path: "./test.log",
|
||||||
volumeId: "main",
|
volumeId: "main",
|
||||||
})
|
});
|
||||||
|
|
||||||
if (typeof metadata.fileType !== 'string') {
|
if (typeof metadata.fileType !== "string") {
|
||||||
throw new TypeError("File type is not a string")
|
throw new TypeError("File type is not a string");
|
||||||
}
|
}
|
||||||
if (typeof metadata.isDir !== 'boolean' ) {
|
if (typeof metadata.isDir !== "boolean") {
|
||||||
throw new TypeError("isDir is not a boolean")
|
throw new TypeError("isDir is not a boolean");
|
||||||
}
|
}
|
||||||
if (typeof metadata.isFile !== 'boolean' ) {
|
if (typeof metadata.isFile !== "boolean") {
|
||||||
throw new TypeError("isFile is not a boolean")
|
throw new TypeError("isFile is not a boolean");
|
||||||
}
|
}
|
||||||
if (typeof metadata.isSymlink !== 'boolean' ) {
|
if (typeof metadata.isSymlink !== "boolean") {
|
||||||
throw new TypeError("isSymlink is not a boolean")
|
throw new TypeError("isSymlink is not a boolean");
|
||||||
}
|
}
|
||||||
if (typeof metadata.len !== 'number' ) {
|
if (typeof metadata.len !== "number") {
|
||||||
throw new TypeError("len is not a number")
|
throw new TypeError("len is not a number");
|
||||||
}
|
}
|
||||||
if (typeof metadata.gid !== 'number' ) {
|
if (typeof metadata.gid !== "number") {
|
||||||
throw new TypeError("gid is not a number")
|
throw new TypeError("gid is not a number");
|
||||||
}
|
}
|
||||||
if (typeof metadata.uid !== 'number' ) {
|
if (typeof metadata.uid !== "number") {
|
||||||
throw new TypeError("uid is not a number")
|
throw new TypeError("uid is not a number");
|
||||||
}
|
}
|
||||||
if (typeof metadata.mode !== 'number' ) {
|
if (typeof metadata.mode !== "number") {
|
||||||
throw new TypeError("mode is not a number")
|
throw new TypeError("mode is not a number");
|
||||||
}
|
}
|
||||||
if (!(metadata.modified instanceof Date )) {
|
if (!(metadata.modified instanceof Date)) {
|
||||||
throw new TypeError("modified is not a Date")
|
throw new TypeError("modified is not a Date");
|
||||||
}
|
}
|
||||||
if (!(metadata.accessed instanceof Date )) {
|
if (!(metadata.accessed instanceof Date)) {
|
||||||
throw new TypeError("accessed is not a Date")
|
throw new TypeError("accessed is not a Date");
|
||||||
}
|
}
|
||||||
if (!(metadata.created instanceof Date )) {
|
if (!(metadata.created instanceof Date)) {
|
||||||
throw new TypeError("created is not a Date")
|
throw new TypeError("created is not a Date");
|
||||||
}
|
}
|
||||||
if (typeof metadata.readonly !== 'boolean' ) {
|
if (typeof metadata.readonly !== "boolean") {
|
||||||
throw new TypeError("readonly is not a boolean")
|
throw new TypeError("readonly is not a boolean");
|
||||||
}
|
}
|
||||||
effects.error(JSON.stringify(metadata))
|
effects.error(JSON.stringify(metadata));
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
result: {
|
result: {
|
||||||
@@ -724,97 +724,145 @@ export async function getConfig(effects) {
|
|||||||
|
|
||||||
export async function setConfig(effects) {
|
export async function setConfig(effects) {
|
||||||
return {
|
return {
|
||||||
error: "Not setup"
|
error: "Not setup",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const assert = (condition, message) => {
|
const assert = (condition, message) => {
|
||||||
if (!condition) {
|
if (!condition) {
|
||||||
throw new Error(message)
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const action = {
|
export const action = {
|
||||||
async fetch(effects, _input) {
|
async fetch(effects, _input) {
|
||||||
const example = await effects.fetch("https://postman-echo.com/get?foo1=bar1&foo2=bar2");
|
const example = await effects.fetch(
|
||||||
assert(Number(example.headers['content-length']) > 0 && Number(example.headers['content-length']) <= 1000000,"Should have content length");
|
"https://postman-echo.com/get?foo1=bar1&foo2=bar2"
|
||||||
assert((example.text() instanceof Promise), "example.text() should be a promise");
|
);
|
||||||
assert((example.body === undefined), "example.body should not be defined");
|
assert(
|
||||||
assert((JSON.parse(await example.text()).args.foo1 === 'bar1'), "Body should be parsed");
|
Number(example.headers["content-length"]) > 0 &&
|
||||||
|
Number(example.headers["content-length"]) <= 1000000,
|
||||||
|
"Should have content length"
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
example.text() instanceof Promise,
|
||||||
|
"example.text() should be a promise"
|
||||||
|
);
|
||||||
|
assert(example.body === undefined, "example.body should not be defined");
|
||||||
|
assert(
|
||||||
|
JSON.parse(await example.text()).args.foo1 === "bar1",
|
||||||
|
"Body should be parsed"
|
||||||
|
);
|
||||||
const message = `This worked @ ${new Date().toISOString()}`;
|
const message = `This worked @ ${new Date().toISOString()}`;
|
||||||
const secondResponse = await effects.fetch("https://postman-echo.com/post", {
|
const secondResponse = await effects.fetch(
|
||||||
method: "POST",
|
"https://postman-echo.com/post",
|
||||||
body:JSON.stringify({message }),
|
{
|
||||||
headers:{
|
method: "POST",
|
||||||
test: "1234",
|
body: JSON.stringify({ message }),
|
||||||
}
|
headers: {
|
||||||
})
|
test: "1234",
|
||||||
assert(((await secondResponse.json()).json.message === message), "Body should be parsed from response");
|
},
|
||||||
return {
|
|
||||||
result: {
|
|
||||||
copyable: false,
|
|
||||||
message: "Done",
|
|
||||||
version: "0",
|
|
||||||
qr: false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
(await secondResponse.json()).json.message === message,
|
||||||
|
"Body should be parsed from response"
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
copyable: false,
|
||||||
|
message: "Done",
|
||||||
|
version: "0",
|
||||||
|
qr: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async 'js-action-var-arg'(_effects, _input, testInput) {
|
async "js-action-var-arg"(_effects, _input, testInput) {
|
||||||
|
|
||||||
assert(testInput == 42, "Input should be passed in");
|
assert(testInput == 42, "Input should be passed in");
|
||||||
return {
|
return {
|
||||||
result: {
|
result: {
|
||||||
copyable: false,
|
copyable: false,
|
||||||
message: "Done",
|
message: "Done",
|
||||||
version: "0",
|
version: "0",
|
||||||
qr: false,
|
qr: false,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
async 'test-rename'(effects, _input) {
|
async "test-rename"(effects, _input) {
|
||||||
|
|
||||||
await effects.writeFile({
|
await effects.writeFile({
|
||||||
volumeId: 'main',
|
volumeId: "main",
|
||||||
path: 'test-rename.txt',
|
path: "test-rename.txt",
|
||||||
toWrite: 'Hello World',
|
toWrite: "Hello World",
|
||||||
});
|
});
|
||||||
await effects.rename({
|
await effects.rename({
|
||||||
srcVolume: 'main',
|
srcVolume: "main",
|
||||||
srcPath: 'test-rename.txt',
|
srcPath: "test-rename.txt",
|
||||||
dstVolume: 'main',
|
dstVolume: "main",
|
||||||
dstPath: 'test-rename-2.txt',
|
dstPath: "test-rename-2.txt",
|
||||||
});
|
});
|
||||||
|
|
||||||
const readIn = await effects.readFile({
|
const readIn = await effects.readFile({
|
||||||
volumeId: 'main',
|
volumeId: "main",
|
||||||
path: 'test-rename-2.txt',
|
path: "test-rename-2.txt",
|
||||||
});
|
});
|
||||||
assert(readIn === 'Hello World', "Contents should be the same");
|
assert(readIn === "Hello World", "Contents should be the same");
|
||||||
|
|
||||||
await effects.removeFile({
|
await effects.removeFile({
|
||||||
path: "test-rename-2.txt",
|
path: "test-rename-2.txt",
|
||||||
volumeId: "main",
|
volumeId: "main",
|
||||||
});
|
});
|
||||||
|
|
||||||
try{
|
try {
|
||||||
|
|
||||||
await effects.removeFile({
|
await effects.removeFile({
|
||||||
path: "test-rename.txt",
|
path: "test-rename.txt",
|
||||||
volumeId: "main",
|
volumeId: "main",
|
||||||
});
|
});
|
||||||
assert(false, "Should not be able to remove file that doesn't exist");
|
assert(false, "Should not be able to remove file that doesn't exist");
|
||||||
}
|
} catch (_) {}
|
||||||
catch (_){}
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
result: {
|
||||||
|
copyable: false,
|
||||||
|
message: "Done",
|
||||||
|
version: "0",
|
||||||
|
qr: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Created this test because of issue
|
||||||
|
* https://github.com/Start9Labs/embassy-os/issues/1737
|
||||||
|
* which that we couldn't create a dir that was deeply nested, and the parents where
|
||||||
|
* not created yet. Found this out during the migrations, where the parent would die.
|
||||||
|
* @param {*} effects
|
||||||
|
* @param {*} _input
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async "test-deep-dir"(effects, _input) {
|
||||||
|
effects.error("Test");
|
||||||
|
await effects
|
||||||
|
.removeDir({
|
||||||
|
volumeId: "main",
|
||||||
|
path: "test-deep-dir",
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
await effects.createDir({
|
||||||
|
volumeId: "main",
|
||||||
|
path: "test-deep-dir/deep/123",
|
||||||
|
});
|
||||||
|
await effects.removeDir({
|
||||||
|
volumeId: "main",
|
||||||
|
path: "test-deep-dir",
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: {
|
result: {
|
||||||
copyable: false,
|
copyable: false,
|
||||||
message: "Done",
|
message: "Done",
|
||||||
version: "0",
|
version: "0",
|
||||||
qr: false,
|
qr: false,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -772,7 +772,22 @@ mod fns {
|
|||||||
parent: impl AsRef<Path>,
|
parent: impl AsRef<Path>,
|
||||||
child: impl AsRef<Path>,
|
child: impl AsRef<Path>,
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, AnyError> {
|
||||||
let child = tokio::fs::canonicalize(child).await?;
|
let child = {
|
||||||
|
let mut child = child.as_ref();
|
||||||
|
loop {
|
||||||
|
let meta = tokio::fs::metadata(child).await;
|
||||||
|
if meta.is_ok() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
child = match child.parent() {
|
||||||
|
Some(child) => child,
|
||||||
|
None => {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
tokio::fs::canonicalize(child).await?
|
||||||
|
};
|
||||||
let parent = tokio::fs::canonicalize(parent).await?;
|
let parent = tokio::fs::canonicalize(parent).await?;
|
||||||
Ok(child.starts_with(parent))
|
Ok(child.starts_with(parent))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user