diff --git a/bindings/electron/src/meths.rs b/bindings/electron/src/meths.rs index 10b574a3ef6..feb9ca5cf32 100644 --- a/bindings/electron/src/meths.rs +++ b/bindings/electron/src/meths.rs @@ -5,7 +5,10 @@ */ #[allow(unused_imports)] -use neon::{prelude::*, types::buffer::TypedArray}; +use neon::{ + prelude::*, + types::{buffer::TypedArray, JsBigInt}, +}; // CancelledGreetingAttemptReason @@ -1405,13 +1408,11 @@ fn struct_file_stat_js_to_rs<'a>( js_val.value(cx) }; let size = { - let js_val: Handle = obj.get(cx, "size")?; + let js_val: Handle = obj.get(cx, "size")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -1468,7 +1469,7 @@ fn struct_file_stat_rs_to_js<'a>( js_obj.set(cx, "isPlaceholder", js_is_placeholder)?; let js_need_sync = JsBoolean::new(cx, rs_obj.need_sync); js_obj.set(cx, "needSync", js_need_sync)?; - let js_size = JsNumber::new(cx, rs_obj.size as f64); + let js_size = JsBigInt::from_u64(cx, rs_obj.size); js_obj.set(cx, "size", js_size)?; Ok(js_obj) } @@ -3215,13 +3216,11 @@ fn struct_workspace_history_file_stat_js_to_rs<'a>( } }; let size = { - let js_val: Handle = obj.get(cx, "size")?; + let js_val: Handle = obj.get(cx, "size")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -3272,7 +3271,7 @@ fn struct_workspace_history_file_stat_rs_to_js<'a>( js_obj.set(cx, "updated", js_updated)?; let js_version = JsNumber::new(cx, rs_obj.version as f64); js_obj.set(cx, "version", js_version)?; - let js_size = JsNumber::new(cx, rs_obj.size as f64); + let js_size = JsBigInt::from_u64(cx, rs_obj.size); js_obj.set(cx, "size", js_size)?; Ok(js_obj) } @@ -3443,13 +3442,11 @@ fn variant_active_users_limit_js_to_rs<'a>( match tag.as_str() { "ActiveUsersLimitLimitedTo" => { let x0 = { - let js_val: Handle = obj.get(cx, "x0")?; + let js_val: Handle = obj.get(cx, "x0")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -3470,7 +3467,7 @@ fn variant_active_users_limit_rs_to_js<'a>( libparsec::ActiveUsersLimit::LimitedTo(x0, ..) => { let js_tag = JsString::try_new(cx, "LimitedTo").or_throw(cx)?; js_obj.set(cx, "tag", js_tag)?; - let js_x0 = JsNumber::new(cx, x0 as f64); + let js_x0 = JsBigInt::from_u64(cx, x0); js_obj.set(cx, "x0", js_x0)?; } libparsec::ActiveUsersLimit::NoLimit { .. } => { @@ -4464,35 +4461,29 @@ fn variant_client_event_js_to_rs<'a>( } }; let blocks = { - let js_val: Handle = obj.get(cx, "blocks")?; + let js_val: Handle = obj.get(cx, "blocks")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; let block_index = { - let js_val: Handle = obj.get(cx, "blockIndex")?; + let js_val: Handle = obj.get(cx, "blockIndex")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; let blocksize = { - let js_val: Handle = obj.get(cx, "blocksize")?; + let js_val: Handle = obj.get(cx, "blocksize")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -4785,11 +4776,11 @@ fn variant_client_event_rs_to_js<'a>( }) .or_throw(cx)?; js_obj.set(cx, "entryId", js_entry_id)?; - let js_blocks = JsNumber::new(cx, blocks as f64); + let js_blocks = JsBigInt::from_u64(cx, blocks); js_obj.set(cx, "blocks", js_blocks)?; - let js_block_index = JsNumber::new(cx, block_index as f64); + let js_block_index = JsBigInt::from_u64(cx, block_index); js_obj.set(cx, "blockIndex", js_block_index)?; - let js_blocksize = JsNumber::new(cx, blocksize as f64); + let js_blocksize = JsBigInt::from_u64(cx, blocksize); js_obj.set(cx, "blocksize", js_blocksize)?; } libparsec::ClientEvent::WorkspaceOpsOutboundSyncStarted { @@ -6141,13 +6132,11 @@ fn variant_entry_stat_js_to_rs<'a>( js_val.value(cx) }; let size = { - let js_val: Handle = obj.get(cx, "size")?; + let js_val: Handle = obj.get(cx, "size")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -6352,7 +6341,7 @@ fn variant_entry_stat_rs_to_js<'a>( js_obj.set(cx, "isPlaceholder", js_is_placeholder)?; let js_need_sync = JsBoolean::new(cx, need_sync); js_obj.set(cx, "needSync", js_need_sync)?; - let js_size = JsNumber::new(cx, size as f64); + let js_size = JsBigInt::from_u64(cx, size); js_obj.set(cx, "size", js_size)?; } libparsec::EntryStat::Folder { @@ -8794,13 +8783,11 @@ fn variant_parsed_parsec_addr_js_to_rs<'a>( } }; let key_index = { - let js_val: Handle = obj.get(cx, "keyIndex")?; + let js_val: Handle = obj.get(cx, "keyIndex")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -9023,7 +9010,7 @@ fn variant_parsed_parsec_addr_rs_to_js<'a>( }) .or_throw(cx)?; js_obj.set(cx, "workspaceId", js_workspace_id)?; - let js_key_index = JsNumber::new(cx, key_index as f64); + let js_key_index = JsBigInt::from_u64(cx, key_index); js_obj.set(cx, "keyIndex", js_key_index)?; let js_encrypted_path = { let mut js_buff = JsArrayBuffer::new(cx, encrypted_path.len())?; @@ -11019,13 +11006,11 @@ fn variant_workspace_history_entry_stat_js_to_rs<'a>( } }; let size = { - let js_val: Handle = obj.get(cx, "size")?; + let js_val: Handle = obj.get(cx, "size")?; { - let v = js_val.value(cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -11174,7 +11159,7 @@ fn variant_workspace_history_entry_stat_rs_to_js<'a>( js_obj.set(cx, "updated", js_updated)?; let js_version = JsNumber::new(cx, version as f64); js_obj.set(cx, "version", js_version)?; - let js_size = JsNumber::new(cx, size as f64); + let js_size = JsBigInt::from_u64(cx, size); js_obj.set(cx, "size", js_size)?; } libparsec::WorkspaceHistoryEntryStat::Folder { @@ -18422,24 +18407,20 @@ fn workspace_fd_read(mut cx: FunctionContext) -> JsResult { } }; let offset = { - let js_val = cx.argument::(2)?; + let js_val = cx.argument::(2)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; let size = { - let js_val = cx.argument::(3)?; + let js_val = cx.argument::(3)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -18517,13 +18498,11 @@ fn workspace_fd_resize(mut cx: FunctionContext) -> JsResult { } }; let length = { - let js_val = cx.argument::(2)?; + let js_val = cx.argument::(2)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -18668,13 +18647,11 @@ fn workspace_fd_write(mut cx: FunctionContext) -> JsResult { } }; let offset = { - let js_val = cx.argument::(2)?; + let js_val = cx.argument::(2)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -18698,7 +18675,7 @@ fn workspace_fd_write(mut cx: FunctionContext) -> JsResult { let js_obj = JsObject::new(&mut cx); let js_tag = JsBoolean::new(&mut cx, true); js_obj.set(&mut cx, "ok", js_tag)?; - let js_value = JsNumber::new(&mut cx, ok as f64); + let js_value = JsBigInt::from_u64(&mut cx, ok); js_obj.set(&mut cx, "value", js_value)?; js_obj } @@ -18749,13 +18726,11 @@ fn workspace_fd_write_constrained_io(mut cx: FunctionContext) -> JsResult(2)?; + let js_val = cx.argument::(2)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; @@ -18780,7 +18755,7 @@ fn workspace_fd_write_constrained_io(mut cx: FunctionContext) -> JsResult JsResult let js_obj = JsObject::new(&mut cx); let js_tag = JsBoolean::new(&mut cx, true); js_obj.set(&mut cx, "ok", js_tag)?; - let js_value = JsNumber::new(&mut cx, ok as f64); + let js_value = JsBigInt::from_u64(&mut cx, ok); js_obj.set(&mut cx, "value", js_value)?; js_obj } @@ -19028,24 +19003,20 @@ fn workspace_history_fd_read(mut cx: FunctionContext) -> JsResult { } }; let offset = { - let js_val = cx.argument::(2)?; + let js_val = cx.argument::(2)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; let size = { - let js_val = cx.argument::(3)?; + let js_val = cx.argument::(3)?; { - let v = js_val.value(&mut cx); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = js_val + .to_u64(&mut cx) + .or_else(|_| cx.throw_type_error("Not an u64 number"))?; v } }; diff --git a/bindings/generator/templates/binding_electron_meths.rs.j2 b/bindings/generator/templates/binding_electron_meths.rs.j2 index 39ccc4afc9a..201d240e1e4 100644 --- a/bindings/generator/templates/binding_electron_meths.rs.j2 +++ b/bindings/generator/templates/binding_electron_meths.rs.j2 @@ -24,8 +24,10 @@ JsValue JsNull {%- elif type.kind == "bool" -%} JsBoolean -{%- elif type.kind in ("u8_based", "i32_based", "u32_based", "i64_based", "u64_based", "f64_based", "float") -%} +{%- elif type.kind in ("u8_based", "i32_based", "u32_based", "f64_based", "float") -%} JsNumber +{%- elif type.kind in ("i64_based", "u64_based") -%} +JsBigInt {%- elif type.kind in ("str", "str_based") -%} JsString {%- elif type.kind in ("bytes", "bytes_based") -%} @@ -207,11 +209,7 @@ JsString } {%- elif type.kind == "i64_based" -%} { - let v = {{ js_val }}.value({{ mut_cx_ref }}); - if v < (i64::MIN as f64) || (i64::MAX as f64) < v { - cx.throw_type_error("Not an i64 number")? - } - let v = v as i64; + let v = {{ js_val }}.to_i64({{ mut_cx_ref }}).or_else(|_| cx.throw_type_error("Not an i64 number"))?; {% if type.custom_from_rs_i64 -%} let custom_from_rs_i64 = {{ type.custom_from_rs_i64 }}; match custom_from_rs_i64(v) { @@ -224,11 +222,7 @@ JsString } {%- elif type.kind == "u64_based" -%} { - let v = {{ js_val }}.value({{ mut_cx_ref }}); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - cx.throw_type_error("Not an u64 number")? - } - let v = v as u64; + let v = {{ js_val }}.to_u64({{ mut_cx_ref }}).or_else(|_| cx.throw_type_error("Not an u64 number"))?; {% if type.custom_from_rs_u64 -%} let custom_from_rs_u64 = {{ type.custom_from_rs_u64 }}; match custom_from_rs_u64(v) { @@ -478,7 +472,7 @@ JsNumber::new({{ mut_cx_ref }}, as f64 ) {%- elif type.kind == "u64_based" -%} -JsNumber::new({{ mut_cx_ref }}, +JsBigInt::from_u64({{ mut_cx_ref }}, {%- if type.custom_to_rs_u64 -%} { let custom_to_rs_u64 = {{ type.custom_to_rs_u64 }}; @@ -490,10 +484,9 @@ JsNumber::new({{ mut_cx_ref }}, {%- else -%} {{ rs_value }} {%- endif %} - as f64 ) {%- elif type.kind == "i64_based" -%} -JsNumber::new({{ mut_cx_ref }}, +JsBigInt::from_i64({{ mut_cx_ref }}, {%- if type.custom_to_rs_i64 -%} { let custom_to_rs_i64 = {{ type.custom_to_rs_i64 }}; @@ -505,7 +498,6 @@ JsNumber::new({{ mut_cx_ref }}, {%- else -%} {{ rs_value }} {%- endif %} - as f64 ) {%- elif type.kind == "f64_based" -%} JsNumber::new({{ mut_cx_ref }}, @@ -880,7 +872,7 @@ fn {{ meth.name }}(mut cx: FunctionContext) -> JsResult { {% endif %} #[allow(unused_imports)] -use neon::{prelude::*, types::buffer::TypedArray}; +use neon::{prelude::*, types::{buffer::TypedArray, JsBigInt}}; {# Enum #} {% for enum in api.enums %} diff --git a/bindings/generator/templates/binding_web_meths.rs.j2 b/bindings/generator/templates/binding_web_meths.rs.j2 index ff911adaf75..82d48f00674 100644 --- a/bindings/generator/templates/binding_web_meths.rs.j2 +++ b/bindings/generator/templates/binding_web_meths.rs.j2 @@ -286,11 +286,7 @@ if {{ js_val }}.is_null() { } {%- elif type.kind == "i64_based" -%} { - let v = {{ js_val }}.dyn_into::().map_err(|_| TypeError::new("Not a number"))?.value_of(); - if v < (i64::MIN as f64) || (i64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an i64 number"))); - } - let v = v as i64; + let v = i64::try_from({{ js_val }}).map_err(|_| TypeError::new("Not a BigInt representing an i64 number"))?; {% if type.custom_from_rs_i64 -%} let custom_from_rs_i64 = {{ type.custom_from_rs_i64 }}; match custom_from_rs_i64(v) { @@ -303,11 +299,7 @@ if {{ js_val }}.is_null() { } {%- elif type.kind == "u64_based" -%} { - let v = {{ js_val }}.dyn_into::().map_err(|_| TypeError::new("Not a number"))?.value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from({{ js_val }}).map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; {% if type.custom_from_rs_u64 -%} let custom_from_rs_u64 = {{ type.custom_from_rs_u64 }}; match custom_from_rs_u64(v) { @@ -501,7 +493,7 @@ JsValue::from({{ rs_value }}) {%- elif type.kind == "i64_based" -%} {%- if type.custom_to_rs_i64 %} { - let custom_to_rs_i64 = {{ type.custom_to_rs_i32 }}; + let custom_to_rs_i64 = {{ type.custom_to_rs_i64 }}; let v = match custom_to_rs_i64({{ rs_value }}) { Ok(ok) => ok, Err(err) => return Err(JsValue::from(TypeError::new(err.as_ref()))), @@ -514,7 +506,7 @@ JsValue::from({{ rs_value }}) {%- elif type.kind == "u64_based" -%} {%- if type.custom_to_rs_u64 %} { - let custom_to_rs_u64 = {{ type.custom_to_rs_i32 }}; + let custom_to_rs_u64 = {{ type.custom_to_rs_u64 }}; let v = match custom_to_rs_u64({{ rs_value }}) { Ok(ok) => ok, Err(err) => return Err(JsValue::from(TypeError::new(err.as_ref()))), diff --git a/bindings/generator/templates/client_plugin_definitions.ts.j2 b/bindings/generator/templates/client_plugin_definitions.ts.j2 index db8816c83c2..1025d027b19 100644 --- a/bindings/generator/templates/client_plugin_definitions.ts.j2 +++ b/bindings/generator/templates/client_plugin_definitions.ts.j2 @@ -82,13 +82,20 @@ export type {{ type.name }} = Uint8Array {% endif %} {% endfor %} {# Number-based types #} -{% for type in api.u8_based_types + api.i32_based_types + api.u32_based_types + api.i64_based_types + api.u64_based_types + api.f64_based_types %} +{% for type in api.u8_based_types + api.i32_based_types + api.u32_based_types + api.f64_based_types %} {% if type.custom_ts_type_declaration %} {{ type.custom_ts_type_declaration }} {% else %} export type {{ type.name }} = number {% endif %} {% endfor %} +{% for type in api.i64_based_types + api.u64_based_types %} +{% if type.custom_ts_type_declaration %} +{{ type.custom_ts_type_declaration }} +{% else %} +export type {{ type.name }} = bigint +{% endif %} +{% endfor %} {# Structures #} {% for struct in api.structs %} diff --git a/bindings/web/src/meths.rs b/bindings/web/src/meths.rs index 1a32c74c55a..85a874c5dea 100644 --- a/bindings/web/src/meths.rs +++ b/bindings/web/src/meths.rs @@ -1515,14 +1515,8 @@ fn struct_file_stat_js_to_rs(obj: JsValue) -> Result() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -3440,14 +3434,8 @@ fn struct_workspace_history_file_stat_js_to_rs( let size = { let js_val = Reflect::get(&obj, &"size".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -3691,14 +3679,8 @@ fn variant_active_users_limit_js_to_rs( let x1 = { let js_val = Reflect::get(&obj, &"x1".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -4888,42 +4870,24 @@ fn variant_client_event_js_to_rs(obj: JsValue) -> Result() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; let block_index = { let js_val = Reflect::get(&obj, &"blockIndex".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; let blocksize = { let js_val = Reflect::get(&obj, &"blocksize".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -6801,14 +6765,8 @@ fn variant_entry_stat_js_to_rs(obj: JsValue) -> Result() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -9780,14 +9738,8 @@ fn variant_parsed_parsec_addr_js_to_rs( let key_index = { let js_val = Reflect::get(&obj, &"keyIndex".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; @@ -12245,14 +12197,8 @@ fn variant_workspace_history_entry_stat_js_to_rs( let size = { let js_val = Reflect::get(&obj, &"size".into())?; { - let v = js_val - .dyn_into::() - .map_err(|_| TypeError::new("Not a number"))? - .value_of(); - if v < (u64::MIN as f64) || (u64::MAX as f64) < v { - return Err(JsValue::from(TypeError::new("Not an u64 number"))); - } - let v = v as u64; + let v = u64::try_from(js_val) + .map_err(|_| TypeError::new("Not a BigInt representing an u64 number"))?; v } }; diff --git a/client/.env.development b/client/.env.development index d5fe8913736..e8a77025464 100644 --- a/client/.env.development +++ b/client/.env.development @@ -6,3 +6,5 @@ PARSEC_APP_TRIAL_SERVERS="trial.parsec.cloud" PARSEC_APP_BMS_USE_MOCK="false" PARSEC_APP_BMS_MOCKED_FUNCTIONS="" PARSEC_APP_BMS_FAIL_FUNCTIONS="" +PARSEC_APP_CREATE_DEFAULT_WORKSPACES="true" +PARSEC_APP_CLEAR_CACHE="true" diff --git a/client/README.md b/client/README.md index 37649f3254a..1fc077e5502 100644 --- a/client/README.md +++ b/client/README.md @@ -119,9 +119,11 @@ ionic cap add ios ## Variables -| Name | Type | Description | Remark | -| ---------------------------------- | ------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -| `PARSEC_APP_DEV_BMS_CREDENTIALS` | `:` | Used as default login credentials for the BMS | Only for development purposes! Avoid using `:` in your password as it will mess up the parsing. | -| `PARSEC_APP_BMS_USE_MOCK` | `boolean` | Used to mock calls to the BMS | Only for development purposes! | -| `PARSEC_APP_BMS_MOCKED_FUNCTIONS ` | `function1;function2;...` | Comma-separated list of functions from the BMS API to mock | Only for development purposes! | -| `PARSEC_APP_BMS_FAIL_FUNCTIONS ` | `function1;function2;...` | Comma-separated list of functions from the BMS API that should fail if mocked | Only for development purposes! | +| Name | Type | Description | Remark | +| -------------------------------------- | ------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `PARSEC_APP_DEV_BMS_CREDENTIALS` | `:` | Used as default login credentials for the BMS | Only for development purposes! Avoid using `:` in your password as it will mess up the parsing. | +| `PARSEC_APP_BMS_USE_MOCK` | `boolean` | Used to mock calls to the BMS | Only for development purposes! | +| `PARSEC_APP_BMS_MOCKED_FUNCTIONS ` | `function1;function2;...` | Comma-separated list of functions from the BMS API to mock | Only for development purposes! | +| `PARSEC_APP_BMS_FAIL_FUNCTIONS ` | `function1;function2;...` | Comma-separated list of functions from the BMS API that should fail if mocked | Only for development purposes! | +| `PARSEC_APP_CREATE_DEFAULT_WORKSPACES` | `boolean` | Create default workspaces when initializing the app | Only for development purposes! | +| `PARSEC_APP_CLEAR_CACHE` | `boolean` | Clear the cache | Only for development purposes! | diff --git a/client/playwright.config.ts b/client/playwright.config.ts index 99858c301af..35f69d7b618 100644 --- a/client/playwright.config.ts +++ b/client/playwright.config.ts @@ -37,6 +37,21 @@ export default defineConfig({ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', }, + testIgnore: [ + '**/workspace_sharing.spec.ts', + '**/workspace_history.spec.ts', + '**/user_list.spec.ts', + '**/user_details.spec.ts', + '**/document_context_menu.spec.ts', + '**/file_import.spec.ts', + '**/file_details.spec.ts', + '**/file_viewers.spec.ts', + '**/file_viewers_document.spec.ts', + '**/file_viewers_pdf.spec.ts', + '**/documents_list.spec.ts', + '**/export_recovery_device.spec.ts', + '**/import_recovery_device.spec.ts', + ], /* Configure projects for major browsers */ projects: [ { diff --git a/client/src/common/file.ts b/client/src/common/file.ts index 34c2cb905b4..05884d0874b 100644 --- a/client/src/common/file.ts +++ b/client/src/common/file.ts @@ -75,7 +75,7 @@ function size(bytes: number, system: [number, string][]): Translatable { return { key: key, data: { size: formattedAmount } }; } -export function formatFileSize(bytesize: number): Translatable { +export function formatFileSize(bytesize: number | bigint): Translatable { const SYSTEM: [number, string][] = [ [Math.pow(1024, 0), 'common.filesize.bytes'], [Math.pow(1024, 1), 'common.filesize.kilobytes'], @@ -83,7 +83,7 @@ export function formatFileSize(bytesize: number): Translatable { [Math.pow(1024, 3), 'common.filesize.gigabytes'], [Math.pow(1024, 4), 'common.filesize.terabytes'], ]; - return size(bytesize, SYSTEM); + return size(Number(bytesize), SYSTEM); } /* File icons */ diff --git a/client/src/main.ts b/client/src/main.ts index ce7c9d6c11e..e702933ee9a 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -23,7 +23,7 @@ import { availableDeviceMatchesServer } from '@/common/device'; import { bootstrapLinkValidator, claimLinkValidator, fileLinkValidator } from '@/common/validators'; import appEnUS from '@/locales/en-US.json'; import appFrFR from '@/locales/fr-FR.json'; -import { getLoggedInDevices, getOrganizationHandle, isElectron, listAvailableDevices, logout, needsMocks, parseFileLink } from '@/parsec'; +import { getLoggedInDevices, getOrganizationHandle, isElectron, listAvailableDevices, logout, parseFileLink } from '@/parsec'; import { AvailableDevice, Platform, libparsec } from '@/plugins/libparsec'; import { Env } from '@/services/environment'; import { Events } from '@/services/eventDistributor'; @@ -55,6 +55,13 @@ function preventRightClick(): void { }); } +function warnRefresh(): void { + window.addEventListener('beforeunload', async (event) => { + event.preventDefault(); + event.returnValue = true; + }); +} + async function initViewers(): Promise { pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker; @@ -161,20 +168,10 @@ async function setupApp(): Promise { app.provide(ThemeManagerKey, themeManager); if ((await libparsec.getPlatform()) === Platform.Web) { - if (!needsMocks()) { - // Only called when the user has interacted with the page - window.addEventListener('beforeunload', async (event: BeforeUnloadEvent) => { - event.preventDefault(); - event.returnValue = true; - }); - - window.addEventListener('unload', async (_event: Event) => { - // Stop the imports and properly logout on close. - await cleanBeforeQuitting(injectionProvider); - }); - } else { - Sentry.disable(); - } + window.addEventListener('unload', async (_event: Event) => { + // Stop the imports and properly logout on close. + await cleanBeforeQuitting(injectionProvider); + }); } window.electronAPI.pageIsInitialized(); @@ -186,6 +183,7 @@ async function setupApp(): Promise { // - dev or prod where devices are fetched from the local storage // - tests with Playwright where the testbed instantiation is done by Playwright if ('TESTING' in window && window.TESTING) { + Sentry.disable(); // handle the testbed and provides the configPath window.nextStageHook = (): any => { return [libparsec, nextStage]; @@ -358,7 +356,10 @@ function setupMockElectronAPI(): void { console[level](`[MOCKED-ELECTRON-LOG] ${message}`); }, pageIsInitialized: (): void => { - window.isDev = (): boolean => needsMocks(); + window.isDev = (): boolean => Boolean(import.meta.env.PARSEC_APP_TESTBED_SERVER); + if (!window.isDev()) { + warnRefresh(); + } }, openConfigDir: (): void => { console.log('OpenConfigDir: Not available'); diff --git a/client/src/parsec/claim_device.ts b/client/src/parsec/claim_device.ts index 964a67921b7..37724caf82a 100644 --- a/client/src/parsec/claim_device.ts +++ b/client/src/parsec/claim_device.ts @@ -12,15 +12,13 @@ import { DeviceClaimInProgress1Info, DeviceClaimInProgress2Info, DeviceClaimInProgress3Info, - DeviceFileType, DeviceLabel, DeviceSaveStrategy, HumanHandle, Result, SASCode, } from '@/parsec'; -import { needsMocks } from '@/parsec/environment'; -import { DEFAULT_HANDLE, MOCK_WAITING_TIME, getClientConfig, wait } from '@/parsec/internals'; +import { getClientConfig } from '@/parsec/internals'; import { libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; @@ -44,10 +42,10 @@ export class DeviceClaim { } async abort(): Promise { - if (this.canceller !== null && !needsMocks()) { + if (this.canceller !== null) { await libparsec.cancel(this.canceller); } - if (this.handle !== null && !needsMocks()) { + if (this.handle !== null) { await libparsec.claimerGreeterAbortOperation(this.handle); } this.canceller = null; @@ -79,187 +77,97 @@ export class DeviceClaim { this._assertState(true, true); - if (!needsMocks()) { - const clientConfig = getClientConfig(); - const result = await libparsec.claimerRetrieveInfo(clientConfig, eventCallback, invitationLink); - if (result.ok) { - if (result.value.tag !== AnyClaimRetrievedInfoTag.Device) { - throw Error('Unexpected tag'); - } - this.handle = result.value.handle; - this.greeter = result.value.greeterHumanHandle; + const clientConfig = getClientConfig(); + const result = await libparsec.claimerRetrieveInfo(clientConfig, eventCallback, invitationLink); + if (result.ok) { + if (result.value.tag !== AnyClaimRetrievedInfoTag.Device) { + throw Error('Unexpected tag'); } - return result as Result; - } else { - await wait(MOCK_WAITING_TIME); - this.handle = DEFAULT_HANDLE; - this.greeter = { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }; - return { - ok: true, - value: { - tag: AnyClaimRetrievedInfoTag.Device, - handle: DEFAULT_HANDLE, - greeterUserId: '1234', - greeterHumanHandle: { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }, - }, - }; + this.handle = result.value.handle; + this.greeter = result.value.greeterHumanHandle; } + return result as Result; } async initialWaitHost(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerDeviceInitialDoWaitPeer(this.canceller, this.handle!); - if (result.ok) { - this.SASCodeChoices = result.value.greeterSasChoices; - this.correctSASCode = result.value.greeterSas; - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - this.SASCodeChoices = ['5MNO', '6PQR', '7STU', '8VWX']; - this.correctSASCode = '7STU'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - greeterSas: this.correctSASCode, - greeterSasChoices: this.SASCodeChoices, - }, - }; + + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerDeviceInitialDoWaitPeer(this.canceller, this.handle!); + if (result.ok) { + this.SASCodeChoices = result.value.greeterSasChoices; + this.correctSASCode = result.value.greeterSas; + this.handle = result.value.handle; } + this.canceller = null; + return result; } async denyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerDeviceInProgress1DoDenyTrust(this.canceller, this.handle!); - this.handle = null; - this.canceller = null; - return result; - } else { - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerDeviceInProgress1DoDenyTrust(this.canceller, this.handle!); + this.handle = null; + this.canceller = null; + return result; } async signifyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerDeviceInProgress1DoSignifyTrust(this.canceller, this.handle!); - if (result.ok) { - this.guestSASCode = result.value.claimerSas; - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - this.guestSASCode = '1337'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - claimerSas: '1337', - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerDeviceInProgress1DoSignifyTrust(this.canceller, this.handle!); + if (result.ok) { + this.guestSASCode = result.value.claimerSas; + this.handle = result.value.handle; } + this.canceller = null; + return result; } async waitHostTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerDeviceInProgress2DoWaitPeerTrust(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerDeviceInProgress2DoWaitPeerTrust(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; } + return result; } async doClaim(deviceLabel: DeviceLabel): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - const result = await libparsec.claimerDeviceInProgress3DoClaim( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.canceller, - this.handle!, - deviceLabel, - ); - if (result.ok) { - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - }, - }; + this.canceller = await libparsec.newCanceller(); + const result = await libparsec.claimerDeviceInProgress3DoClaim( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.canceller, + this.handle!, + deviceLabel, + ); + if (result.ok) { + this.handle = result.value.handle; } + this.canceller = null; + return result; } async finalize(saveStrategy: DeviceSaveStrategy): Promise> { this._assertState(true, false); - if (!needsMocks()) { - const result = await libparsec.claimerDeviceFinalizeSaveLocalDevice( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.handle!, - saveStrategy, - ); - if (result.ok) { - result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); - result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); - this.device = result.value; - } - this.handle = null; - return result; - } else { - this.handle = null; - this.device = { - keyFilePath: '/path', - serverUrl: 'https://parsec.invalid', - createdOn: DateTime.utc(), - protectedOn: DateTime.utc(), - organizationId: 'MyOrg', - userId: 'userid', - deviceId: 'deviceid', - humanHandle: { - label: 'A', - email: 'a@b.c', - }, - deviceLabel: 'a@b', - ty: DeviceFileType.Password, - }; - return { ok: true, value: this.device }; + const result = await libparsec.claimerDeviceFinalizeSaveLocalDevice( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.handle!, + saveStrategy, + ); + if (result.ok) { + result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); + result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); + this.device = result.value; } + this.handle = null; + return result; } } diff --git a/client/src/parsec/claim_user.ts b/client/src/parsec/claim_user.ts index 6f61d1867b2..238c44a9d15 100644 --- a/client/src/parsec/claim_user.ts +++ b/client/src/parsec/claim_user.ts @@ -8,7 +8,6 @@ import { ClaimerRetrieveInfoError, ClientEvent, ConnectionHandle, - DeviceFileType, DeviceSaveStrategy, HumanHandle, Result, @@ -18,8 +17,7 @@ import { UserClaimInProgress2Info, UserClaimInProgress3Info, } from '@/parsec'; -import { needsMocks } from '@/parsec/environment'; -import { DEFAULT_HANDLE, MOCK_WAITING_TIME, getClientConfig, wait } from '@/parsec/internals'; +import { getClientConfig } from '@/parsec/internals'; import { libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; @@ -43,10 +41,10 @@ export class UserClaim { } async abort(): Promise { - if (this.canceller !== null && !needsMocks()) { + if (this.canceller !== null) { await libparsec.cancel(this.canceller); } - if (this.handle !== null && !needsMocks()) { + if (this.handle !== null) { await libparsec.claimerGreeterAbortOperation(this.handle); } this.canceller = null; @@ -78,189 +76,97 @@ export class UserClaim { this._assertState(true, true); - if (!needsMocks()) { - const clientConfig = getClientConfig(); - const result = await libparsec.claimerRetrieveInfo(clientConfig, eventCallback, invitationLink); - if (result.ok) { - if (result.value.tag !== AnyClaimRetrievedInfoTag.User) { - throw Error('Unexpected tag'); - } - this.handle = result.value.handle; - this.greeter = result.value.greeterHumanHandle; + const clientConfig = getClientConfig(); + const result = await libparsec.claimerRetrieveInfo(clientConfig, eventCallback, invitationLink); + if (result.ok) { + if (result.value.tag !== AnyClaimRetrievedInfoTag.User) { + throw Error('Unexpected tag'); } - return result as Result; - } else { - await wait(MOCK_WAITING_TIME); - this.handle = DEFAULT_HANDLE; - this.greeter = { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }; - return { - ok: true, - value: { - tag: AnyClaimRetrievedInfoTag.User, - handle: DEFAULT_HANDLE, - claimerEmail: 'shadowheart@swordcoast.faerun', - greeterUserId: '1234', - greeterHumanHandle: { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }, - }, - }; + this.handle = result.value.handle; + this.greeter = result.value.greeterHumanHandle; } + return result as Result; } async initialWaitHost(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerUserInitialDoWaitPeer(this.canceller, this.handle!); - if (result.ok) { - this.SASCodeChoices = result.value.greeterSasChoices; - this.correctSASCode = result.value.greeterSas; - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - this.SASCodeChoices = ['1ABC', '2DEF', '3GHI', '4JKL']; - this.correctSASCode = '2DEF'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - greeterSas: '2DEF', - greeterSasChoices: ['1ABC', '2DEF', '3GHI', '4JKL'], - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerUserInitialDoWaitPeer(this.canceller, this.handle!); + if (result.ok) { + this.SASCodeChoices = result.value.greeterSasChoices; + this.correctSASCode = result.value.greeterSas; + this.handle = result.value.handle; } + this.canceller = null; + return result; } async denyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerUserInProgress1DoDenyTrust(this.canceller, this.handle!); - this.handle = null; - this.canceller = null; - return result; - } else { - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerUserInProgress1DoDenyTrust(this.canceller, this.handle!); + this.handle = null; + this.canceller = null; + return result; } async signifyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerUserInProgress1DoSignifyTrust(this.canceller, this.handle!); - if (result.ok) { - this.guestSASCode = result.value.claimerSas; - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - this.guestSASCode = '1337'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - claimerSas: '1337', - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerUserInProgress1DoSignifyTrust(this.canceller, this.handle!); + if (result.ok) { + this.guestSASCode = result.value.claimerSas; + this.handle = result.value.handle; } + this.canceller = null; + return result; } async waitHostTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.claimerUserInProgress2DoWaitPeerTrust(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.claimerUserInProgress2DoWaitPeerTrust(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; } + return result; } async doClaim(deviceLabel: string, userName: string, email: string): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - const result = await libparsec.claimerUserInProgress3DoClaim( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.canceller, - this.handle!, - deviceLabel, - { email: email, label: userName }, - ); - if (result.ok) { - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - }, - }; + this.canceller = await libparsec.newCanceller(); + const result = await libparsec.claimerUserInProgress3DoClaim( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.canceller, + this.handle!, + deviceLabel, + { email: email, label: userName }, + ); + if (result.ok) { + this.handle = result.value.handle; } + this.canceller = null; + return result; } async finalize(saveStrategy: DeviceSaveStrategy): Promise> { this._assertState(true, false); - if (!needsMocks()) { - const result = await libparsec.claimerUserFinalizeSaveLocalDevice( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.handle!, - saveStrategy, - ); - if (result.ok) { - result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); - result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); - this.device = result.value; - } - this.handle = null; - return result; - } else { - this.handle = null; - this.device = { - keyFilePath: '/path', - serverUrl: 'https://parsec.invalid', - createdOn: DateTime.utc(), - protectedOn: DateTime.utc(), - organizationId: 'MyOrg', - userId: 'userid', - deviceId: 'deviceid', - humanHandle: { - label: 'A', - email: 'a@b.c', - }, - deviceLabel: 'a@b', - ty: DeviceFileType.Password, - }; - return { ok: true, value: this.device }; + const result = await libparsec.claimerUserFinalizeSaveLocalDevice( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.handle!, + saveStrategy, + ); + if (result.ok) { + result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); + result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); + this.device = result.value; } + this.handle = null; + return result; } } diff --git a/client/src/parsec/device.ts b/client/src/parsec/device.ts index 486bb42df9c..b0ac8f07594 100644 --- a/client/src/parsec/device.ts +++ b/client/src/parsec/device.ts @@ -1,7 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { needsMocks } from '@/parsec/environment'; -import { getClientConfig, wait } from '@/parsec/internals'; +import { getClientConfig } from '@/parsec/internals'; import { getClientInfo } from '@/parsec/login'; import { getParsecHandle } from '@/parsec/routing'; import { @@ -11,18 +10,16 @@ import { ClientListUserDevicesError, ClientListUserDevicesErrorTag, ClientNewDeviceInvitationError, - DeviceFileType, DeviceInfo, DevicePurpose, DeviceSaveStrategy, ImportRecoveryDeviceError, - ImportRecoveryDeviceErrorTag, - InvitationEmailSentStatus, NewInvitationInfo, OwnDeviceInfo, Result, UserID, } from '@/parsec/types'; +import { generateNoHandleError } from '@/parsec/utils'; import { libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; @@ -35,21 +32,10 @@ function generateRecoveryDeviceLabel(): string { export async function exportRecoveryDevice(): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientExportRecoveryDevice(handle, generateRecoveryDeviceLabel()); - } else { - await wait(300); - return { - ok: true, - value: ['ABCDEF', new Uint8Array([0x6d, 0x65, 0x6f, 0x77])], - }; } -} - -function areArraysEqual(a: Uint8Array, b: Uint8Array): boolean { - return a.every((val, index) => { - return val === b[index]; - }); + return generateNoHandleError(); } export async function importRecoveryDevice( @@ -58,47 +44,18 @@ export async function importRecoveryDevice( passphrase: string, saveStrategy: DeviceSaveStrategy, ): Promise> { - if (!needsMocks()) { - const result = await libparsec.importRecoveryDevice(getClientConfig(), recoveryData, passphrase, deviceLabel, saveStrategy); - if (result.ok) { - result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); - result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); - } - return result; + const result = await libparsec.importRecoveryDevice(getClientConfig(), recoveryData, passphrase, deviceLabel, saveStrategy); + if (result.ok) { + result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); + result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); } - - // cspell:disable-next-line - if (passphrase !== 'ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ12-3456-7890-ABCD-EFGH-IJKL-MNOP') { - return { ok: false, error: { tag: ImportRecoveryDeviceErrorTag.InvalidPassphrase, error: 'Wrong passphrase' } }; - } - if (areArraysEqual(recoveryData, new Uint8Array([78, 79, 80, 10]))) { - return { ok: false, error: { tag: ImportRecoveryDeviceErrorTag.InvalidData, error: 'Wrong data' } }; - } - - return { - ok: true, - value: { - keyFilePath: 'dummy', - serverUrl: 'https://parsec.invalid', - createdOn: DateTime.utc(), - protectedOn: DateTime.utc(), - organizationId: 'dummy_org', - userId: 'dummy_user_id', - deviceId: 'device_id', - humanHandle: { - email: 'dummy_email@email.dum', - label: 'dummy_label', - }, - deviceLabel: deviceLabel, - ty: DeviceFileType.Password, - }, - }; + return result; } export async function listOwnDevices(): Promise, ClientListUserDevicesError>> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { const clientResult = await getClientInfo(); if (clientResult.ok) { @@ -118,28 +75,14 @@ export async function listOwnDevices(): Promise, Cli error: { tag: ClientListUserDevicesErrorTag.Internal, error: '' }, }; } - } else { - return { - ok: true, - value: [1, 2, 3].map((n) => { - return { - id: `device${n}`, - deviceLabel: n === 3 ? `${RECOVERY_DEVICE_PREFIX}_device${n}` : `device${n}`, - createdOn: DateTime.now(), - createdBy: 'some_device', - isCurrent: n === 1, - isRecovery: n === 3, - purpose: n === 3 ? DevicePurpose.PassphraseRecovery : DevicePurpose.Standard, - }; - }), - }; } + return generateNoHandleError(); } export async function listUserDevices(user: UserID): Promise, ClientListUserDevicesError>> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientListUserDevices(handle, user); if (result.ok) { result.value.map((item) => { @@ -148,34 +91,8 @@ export async function listUserDevices(user: UserID): Promise(); } export async function archiveDevice(device: AvailableDevice): Promise> { @@ -185,19 +102,9 @@ export async function archiveDevice(device: AvailableDevice): Promise> { const clientHandle = getParsecHandle(); - if (clientHandle !== null && !needsMocks()) { + if (clientHandle !== null) { const result = await libparsec.clientNewDeviceInvitation(clientHandle, sendEmail); return result; - } else { - return { - ok: true, - value: { - // cspell:disable-next-line - addr: 'parsec3://example.parsec.cloud/Org?a=claim_device&p=xBj1p7vXl_j1tzTjrx5pzbXV7XTbx_Xnnb0', - // cspell:disable-next-line - token: '9ae715f49bc0468eac211e1028f15529', - emailSentStatus: InvitationEmailSentStatus.Success, - }, - }; } + return generateNoHandleError(); } diff --git a/client/src/parsec/environment.ts b/client/src/parsec/environment.ts index b7927cda50b..b3491fb377f 100644 --- a/client/src/parsec/environment.ts +++ b/client/src/parsec/environment.ts @@ -33,13 +33,6 @@ export function usesTestbed(): boolean { return window.usesTestbed(); } -// Whether or not module functions should return mock values. -// Currently, this can be used on web, since the bindings are not fully -// implemented, but it could also prove useful when in a testing environment. -export function needsMocks(): boolean { - return !isDesktop(); -} - export function isElectron(): boolean { return isPlatform('electron'); } diff --git a/client/src/parsec/file.ts b/client/src/parsec/file.ts index ec6a39f0f2a..22cd4b7fd0c 100644 --- a/client/src/parsec/file.ts +++ b/client/src/parsec/file.ts @@ -1,11 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { needsMocks } from '@/parsec/environment'; -import { wait } from '@/parsec/internals'; -import { MockFiles } from '@/parsec/mock_files'; -import { MockEntry, generateEntriesForEachFileType, generateFile, generateFolder } from '@/parsec/mock_generator'; import { Path } from '@/parsec/path'; -import { getParsecHandle, getWorkspaceHandle } from '@/parsec/routing'; import { EntryName, EntryStat, @@ -23,15 +18,10 @@ import { Result, WorkspaceCreateFileError, WorkspaceCreateFolderError, - WorkspaceCreateFolderErrorTag, WorkspaceFdCloseError, - WorkspaceFdCloseErrorTag, WorkspaceFdReadError, - WorkspaceFdReadErrorTag, WorkspaceFdResizeError, - WorkspaceFdResizeErrorTag, WorkspaceFdWriteError, - WorkspaceFdWriteErrorTag, WorkspaceHandle, WorkspaceMoveEntryError, WorkspaceOpenFileError, @@ -42,41 +32,22 @@ import { import { MoveEntryModeTag, libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; -const MOCK_OPENED_FILES = new Map(); -let MOCK_CURRENT_FD = 1; - export const DEFAULT_READ_SIZE = 256_000; export async function createFile(workspaceHandle: WorkspaceHandle, path: FsPath): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceCreateFile(workspaceHandle, path); - } else { - return { ok: true, value: '42' }; - } + return await libparsec.workspaceCreateFile(workspaceHandle, path); } export async function createFolder(workspaceHandle: WorkspaceHandle, path: FsPath): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceCreateFolderAll(workspaceHandle, path); - } else { - return { ok: false, error: { tag: WorkspaceCreateFolderErrorTag.EntryExists, error: 'already exists' } }; - } + return await libparsec.workspaceCreateFolderAll(workspaceHandle, path); } export async function deleteFile(workspaceHandle: WorkspaceHandle, path: FsPath): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceRemoveFile(workspaceHandle, path); - } else { - return { ok: true, value: null }; - } + return await libparsec.workspaceRemoveFile(workspaceHandle, path); } export async function deleteFolder(workspaceHandle: WorkspaceHandle, path: FsPath): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceRemoveFolderAll(workspaceHandle, path); - } else { - return { ok: true, value: null }; - } + return await libparsec.workspaceRemoveFolderAll(workspaceHandle, path); } export async function rename( @@ -84,58 +55,35 @@ export async function rename( path: FsPath, newName: EntryName, ): Promise> { - if (!needsMocks()) { - const newPath = await Path.join(await Path.parent(path), newName); - const result = await libparsec.workspaceMoveEntry(workspaceHandle, path, newPath, { tag: MoveEntryModeTag.NoReplace }); - if (result.ok) { - return { ok: true, value: newPath }; - } - return result; - } else { - return { ok: true, value: '/a/b.txt' }; + const newPath = await Path.join(await Path.parent(path), newName); + const result = await libparsec.workspaceMoveEntry(workspaceHandle, path, newPath, { tag: MoveEntryModeTag.NoReplace }); + if (result.ok) { + return { ok: true, value: newPath }; } + return result; } -let MOCK_FILE_ID = 1; - export async function entryStat(workspaceHandle: WorkspaceHandle, path: FsPath): Promise> { const fileName = (await Path.filename(path)) || ''; - if (!needsMocks()) { - const result = await libparsec.workspaceStatEntry(workspaceHandle, path); - if (result.ok) { - result.value.created = DateTime.fromSeconds(result.value.created as any as number); - result.value.updated = DateTime.fromSeconds(result.value.updated as any as number); - if (result.value.tag === FileType.File) { - (result.value as EntryStatFile).isFile = (): boolean => true; - (result.value as EntryStatFile).name = fileName; - (result.value as EntryStatFile).path = path; - (result.value as EntryStatFile).isConfined = (): boolean => result.value.confinementPoint !== null; - } else { - (result.value as EntryStatFolder).isFile = (): boolean => false; - (result.value as EntryStatFolder).name = fileName; - (result.value as EntryStatFolder).path = path; - (result.value as EntryStatFolder).isConfined = (): boolean => result.value.confinementPoint !== null; - } + const result = await libparsec.workspaceStatEntry(workspaceHandle, path); + if (result.ok) { + result.value.created = DateTime.fromSeconds(result.value.created as any as number); + result.value.updated = DateTime.fromSeconds(result.value.updated as any as number); + if (result.value.tag === FileType.File) { + (result.value as EntryStatFile).size = result.value.size; + (result.value as EntryStatFile).isFile = (): boolean => true; + (result.value as EntryStatFile).name = fileName; + (result.value as EntryStatFile).path = path; + (result.value as EntryStatFile).isConfined = (): boolean => result.value.confinementPoint !== null; + } else { + (result.value as EntryStatFolder).isFile = (): boolean => false; + (result.value as EntryStatFolder).name = fileName; + (result.value as EntryStatFolder).path = path; + (result.value as EntryStatFolder).isConfined = (): boolean => result.value.confinementPoint !== null; } - return result as Result; - } - - MOCK_FILE_ID += 1; - - let entry: MockEntry; - - if (path !== '/' && fileName.startsWith('File_')) { - entry = await generateFile(await Path.parent(path), { parentId: `${MOCK_FILE_ID}`, fileName: fileName }); - } else { - entry = await generateFolder(path, { parentId: `${MOCK_FILE_ID}`, fileName: fileName }); } - (entry as any as EntryStat).baseVersion = entry.version; - (entry as any as EntryStat).confinementPoint = null; - (entry as any as EntryStat).isConfined = (): boolean => false; - (entry as any as EntryStat).needSync = Math.floor(Math.random() * 2) === 1; - (entry as any as EntryStat).isPlaceholder = false; - return { ok: true, value: entry as any as EntryStat }; + return result as Result; } export async function statFolderChildren( @@ -143,56 +91,47 @@ export async function statFolderChildren( path: FsPath, excludeConfined = true, ): Promise, WorkspaceStatFolderChildrenError>> { - if (!needsMocks()) { - const watchResult = await libparsec.workspaceWatchEntryOneshot(workspaceHandle, path); + const watchResult = await libparsec.workspaceWatchEntryOneshot(workspaceHandle, path); - let result; - if (!watchResult.ok) { - result = await libparsec.workspaceStatFolderChildren(workspaceHandle, path); - } else { - result = await libparsec.workspaceStatFolderChildrenById(workspaceHandle, watchResult.value); - } + let result; + if (!watchResult.ok) { + result = await libparsec.workspaceStatFolderChildren(workspaceHandle, path); + } else { + result = await libparsec.workspaceStatFolderChildrenById(workspaceHandle, watchResult.value); + } - if (!result.ok) { - return result; - } + if (!result.ok) { + return result; + } - const cooked: Array = []; - for (const [name, stat] of result.value) { - if (!stat.confinementPoint || !excludeConfined) { - stat.created = DateTime.fromSeconds(stat.created as any as number); - stat.updated = DateTime.fromSeconds(stat.updated as any as number); - if (stat.tag === FileType.File) { - (stat as EntryStatFile).isFile = (): boolean => true; - (stat as EntryStatFile).name = name; - (stat as EntryStatFile).path = await Path.join(path, name); - (stat as EntryStatFile).isConfined = (): boolean => stat.confinementPoint !== null; - } else { - (stat as EntryStatFolder).isFile = (): boolean => false; - (stat as EntryStatFolder).name = name; - (stat as EntryStatFolder).path = await Path.join(path, name); - (stat as EntryStatFolder).isConfined = (): boolean => stat.confinementPoint !== null; - } - cooked.push(stat as EntryStat); + const cooked: Array = []; + for (const [name, stat] of result.value) { + if (name === undefined || stat === undefined) { + continue; + } + if (!stat.confinementPoint || !excludeConfined) { + stat.created = DateTime.fromSeconds(stat.created as any as number); + stat.updated = DateTime.fromSeconds(stat.updated as any as number); + if (stat.tag === FileType.File) { + (stat as EntryStatFile).size = stat.size; + (stat as EntryStatFile).isFile = (): boolean => true; + (stat as EntryStatFile).name = name; + (stat as EntryStatFile).path = await Path.join(path, name); + (stat as EntryStatFile).isConfined = (): boolean => stat.confinementPoint !== null; + } else { + (stat as EntryStatFolder).isFile = (): boolean => false; + (stat as EntryStatFolder).name = name; + (stat as EntryStatFolder).path = await Path.join(path, name); + (stat as EntryStatFolder).isConfined = (): boolean => stat.confinementPoint !== null; } + cooked.push(stat as EntryStat); } - - return { - ok: true, - value: cooked, - }; } - await wait(500); - const items = (await generateEntriesForEachFileType(path)).map((entry) => { - (entry as any as EntryStat).baseVersion = entry.version; - (entry as any as EntryStat).confinementPoint = null; - (entry as any as EntryStat).isConfined = (): boolean => false; - (entry as any as EntryStat).needSync = Math.floor(Math.random() * 2) === 1; - (entry as any as EntryStat).isPlaceholder = false; - return entry as any as EntryStat; - }); - return { ok: true, value: items }; + return { + ok: true, + value: cooked, + }; } export async function moveEntry( @@ -201,16 +140,12 @@ export async function moveEntry( destination: FsPath, forceReplace = false, ): Promise> { - if (workspaceHandle && !needsMocks()) { - return libparsec.workspaceMoveEntry( - workspaceHandle, - source, - destination, - forceReplace ? { tag: MoveEntryModeTag.CanReplace } : { tag: MoveEntryModeTag.NoReplace }, - ); - } else { - return { ok: true, value: null }; - } + return libparsec.workspaceMoveEntry( + workspaceHandle, + source, + destination, + forceReplace ? { tag: MoveEntryModeTag.CanReplace } : { tag: MoveEntryModeTag.NoReplace }, + ); } export enum CopyErrorTag { @@ -221,17 +156,6 @@ export interface CopyError { tag: CopyErrorTag.Internal; } -export async function copyEntry(_source: FsPath, _destination: FsPath): Promise> { - const clientHandle = getParsecHandle(); - const workspaceHandle = getWorkspaceHandle(); - - if (clientHandle && workspaceHandle && !needsMocks()) { - return { ok: true, value: null }; - } else { - return { ok: true, value: null }; - } -} - export async function parseFileLink(link: string): Promise> { const result = await libparsec.parseParsecAddr(link); if (result.ok && result.value.tag !== ParsedParsecAddrTag.WorkspacePath) { @@ -297,26 +221,11 @@ export async function openFile( createNew: options.createNew ? true : false, }; - if (workspaceHandle && !needsMocks()) { - return await libparsec.workspaceOpenFile(workspaceHandle, path, parsecOptions); - } else { - const fd = MOCK_CURRENT_FD; - MOCK_CURRENT_FD += 1; - MOCK_OPENED_FILES.set(fd, path); - return { ok: true, value: fd }; - } + return await libparsec.workspaceOpenFile(workspaceHandle, path, parsecOptions); } export async function closeFile(workspaceHandle: WorkspaceHandle, fd: FileDescriptor): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceFdClose(workspaceHandle, fd); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceFdCloseErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - MOCK_OPENED_FILES.delete(fd); - return { ok: true, value: null }; - } + return await libparsec.workspaceFdClose(workspaceHandle, fd); } export async function resizeFile( @@ -324,14 +233,7 @@ export async function resizeFile( fd: FileDescriptor, length: number, ): Promise> { - if (workspaceHandle && !needsMocks()) { - return await libparsec.workspaceFdResize(workspaceHandle, fd, length, true); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceFdResizeErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - return { ok: true, value: null }; - } + return await libparsec.workspaceFdResize(workspaceHandle, fd, BigInt(length), true); } export async function writeFile( @@ -340,15 +242,11 @@ export async function writeFile( offset: number, data: Uint8Array, ): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceFdWrite(workspaceHandle, fd, offset, data); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceFdWriteErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - await wait(100); - return { ok: true, value: data.length }; + const result = await libparsec.workspaceFdWrite(workspaceHandle, fd, BigInt(offset), data); + if (result.ok) { + return { ok: true, value: Number(result.value) }; } + return result; } export async function readFile( @@ -357,53 +255,7 @@ export async function readFile( offset: number, size: number, ): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceFdRead(workspaceHandle, fd, offset, size); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceFdReadErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - await wait(100); - const path = MOCK_OPENED_FILES.get(fd) as string; - const fileName = (await Path.filename(path)) as EntryName; - const ext = Path.getFileExtension(fileName); - - switch (ext) { - case 'xlsx': - offset === 0 && console.log('Using XLSX content'); - return { ok: true, value: MockFiles.XLSX.slice(offset, offset + size) }; - case 'png': - offset === 0 && console.log('Using PNG content'); - return { ok: true, value: MockFiles.PNG.slice(offset, offset + size) }; - case 'docx': - offset === 0 && console.log('Using DOCX content'); - return { ok: true, value: MockFiles.DOCX.slice(offset, offset + size) }; - case 'txt': - offset === 0 && console.log('Using TXT content'); - return { ok: true, value: MockFiles.TXT.slice(offset, offset + size) }; - case 'py': - offset === 0 && console.log('Using PY content'); - return { ok: true, value: MockFiles.PY.slice(offset, offset + size) }; - case 'pdf': - offset === 0 && console.log('Using PDF content'); - return { ok: true, value: MockFiles.PDF.slice(offset, offset + size) }; - case 'mp3': - offset === 0 && console.log('Using MP3 content'); - return { ok: true, value: MockFiles.MP3.slice(offset, offset + size) }; - case 'mp4': - offset === 0 && console.log('Using MP4 content'); - return { ok: true, value: MockFiles.MP4.slice(offset, offset + size) }; - } - console.log('Using default file content'); - return { - ok: true, - value: new Uint8Array([ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 6, 0, 0, 0, 141, 111, 38, 229, 0, 0, 0, 28, - 73, 68, 65, 84, 8, 215, 99, 248, 255, 255, 63, 195, 127, 6, 32, 5, 195, 32, 18, 132, 208, 49, 241, 130, 88, 205, 4, 0, 14, 245, 53, - 203, 209, 142, 14, 31, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, - ]), - }; - } + return await libparsec.workspaceFdRead(workspaceHandle, fd, BigInt(offset), BigInt(size)); } export interface EntryTree { @@ -444,7 +296,7 @@ export async function listTree(workspaceHandle: WorkspaceHandle, path: FsPath, d tree.maxFilesReached = true; } } else { - tree.totalSize += (entry as EntryStatFile).size; + tree.totalSize += Number((entry as EntryStatFile).size); tree.entries.push(entry as EntryStatFile); if (tree.entries.length > filesLimit) { tree.maxFilesReached = true; diff --git a/client/src/parsec/greet_device.ts b/client/src/parsec/greet_device.ts index 223ea15307d..8bdf89926b2 100644 --- a/client/src/parsec/greet_device.ts +++ b/client/src/parsec/greet_device.ts @@ -15,9 +15,8 @@ import { Result, createDeviceInvitation, } from '@/parsec'; -import { needsMocks } from '@/parsec/environment'; -import { DEFAULT_HANDLE, MOCK_WAITING_TIME, wait } from '@/parsec/internals'; import { getParsecHandle } from '@/parsec/routing'; +import { generateNoHandleError } from '@/parsec/utils'; import { InvitationToken, ParsecInvitationAddr, SASCode, libparsec } from '@/plugins/libparsec'; export class DeviceGreet { @@ -42,10 +41,10 @@ export class DeviceGreet { } async abort(): Promise { - if (this.canceller !== null && !needsMocks()) { + if (this.canceller !== null) { await libparsec.cancel(this.canceller); } - if (this.handle !== null && !needsMocks()) { + if (this.handle !== null) { await libparsec.claimerGreeterAbortOperation(this.handle); } this.canceller = null; @@ -91,152 +90,101 @@ export class DeviceGreet { async sendEmail(): Promise { const clientHandle = getParsecHandle(); - if (clientHandle !== null && !needsMocks()) { + if (clientHandle !== null) { const result = await libparsec.clientNewDeviceInvitation(clientHandle, true); return result.ok; - } else { - return true; } + return false; } async startGreet(): Promise> { this._assertState(true, true); const clientHandle = getParsecHandle(); - if (clientHandle !== null && !needsMocks()) { + if (clientHandle !== null) { const result = await libparsec.clientStartDeviceInvitationGreet(clientHandle, this.token); if (result.ok) { this.handle = result.value.handle; } return result; - } else { - this.handle = DEFAULT_HANDLE; - await wait(MOCK_WAITING_TIME); - return { ok: true, value: { handle: DEFAULT_HANDLE } }; } + return generateNoHandleError(); } async initialWaitGuest(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterDeviceInitialDoWaitPeer(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - this.hostSASCode = result.value.greeterSas; - } - return result; - } else { - this.hostSASCode = '2EDF'; - return { - ok: true, - value: { handle: DEFAULT_HANDLE, greeterSas: this.hostSASCode }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterDeviceInitialDoWaitPeer(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; + this.hostSASCode = result.value.greeterSas; } + return result; } async waitGuestTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterDeviceInProgress1DoWaitPeerTrust(this.canceller, this.handle!); - if (result.ok) { - this.handle = result.value.handle; - this.SASCodeChoices = result.value.claimerSasChoices; - this.correctSASCode = result.value.claimerSas; - } - this.canceller = null; - return result; - } else { - await wait(MOCK_WAITING_TIME); - this.SASCodeChoices = ['1ABC', '2DEF', '3GHI', '4JKL']; - this.correctSASCode = '2DEF'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - claimerSasChoices: this.SASCodeChoices, - claimerSas: this.correctSASCode, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterDeviceInProgress1DoWaitPeerTrust(this.canceller, this.handle!); + if (result.ok) { + this.handle = result.value.handle; + this.SASCodeChoices = result.value.claimerSasChoices; + this.correctSASCode = result.value.claimerSas; } + this.canceller = null; + return result; } async denyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterDeviceInProgress2DoDenyTrust(this.canceller, this.handle!); - this.handle = null; - this.canceller = null; - return result; - } else { - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterDeviceInProgress2DoDenyTrust(this.canceller, this.handle!); + this.handle = null; + this.canceller = null; + return result; } async signifyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterDeviceInProgress2DoSignifyTrust(this.canceller, this.handle!); - if (result.ok) { - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - return { ok: true, value: { handle: DEFAULT_HANDLE } }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterDeviceInProgress2DoSignifyTrust(this.canceller, this.handle!); + if (result.ok) { + this.handle = result.value.handle; } + this.canceller = null; + return result; } async getClaimRequests(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterDeviceInProgress3DoGetClaimRequests(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - this.requestedDeviceLabel = result.value.requestedDeviceLabel || ''; - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - this.requestedDeviceLabel = 'My Device'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - requestedDeviceLabel: this.requestedDeviceLabel, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterDeviceInProgress3DoGetClaimRequests(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; + this.requestedDeviceLabel = result.value.requestedDeviceLabel || ''; } + return result; } async createDevice(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - const result = await libparsec.greeterDeviceInProgress4DoCreate( - this.canceller, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.handle!, - this.requestedDeviceLabel, - ); - this.canceller = null; - this.handle = null; - return result; - } else { - this.handle = null; - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + const result = await libparsec.greeterDeviceInProgress4DoCreate( + this.canceller, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.handle!, + this.requestedDeviceLabel, + ); + this.canceller = null; + this.handle = null; + return result; } } diff --git a/client/src/parsec/greet_user.ts b/client/src/parsec/greet_user.ts index 2d8addc4ffe..da4db4d93d7 100644 --- a/client/src/parsec/greet_user.ts +++ b/client/src/parsec/greet_user.ts @@ -15,9 +15,8 @@ import { UserGreetInitialInfo, UserProfile, } from '@/parsec'; -import { needsMocks } from '@/parsec/environment'; -import { DEFAULT_HANDLE, MOCK_WAITING_TIME, wait } from '@/parsec/internals'; import { getParsecHandle } from '@/parsec/routing'; +import { generateNoHandleError } from '@/parsec/utils'; import { SASCode, libparsec } from '@/plugins/libparsec'; export class UserGreet { @@ -40,10 +39,10 @@ export class UserGreet { } async abort(): Promise { - if (this.canceller !== null && !needsMocks()) { + if (this.canceller !== null) { await libparsec.cancel(this.canceller); } - if (this.handle !== null && !needsMocks()) { + if (this.handle !== null) { await libparsec.claimerGreeterAbortOperation(this.handle); } this.canceller = null; @@ -69,150 +68,93 @@ export class UserGreet { async startGreet(token: InvitationToken): Promise> { const clientHandle = getParsecHandle(); - if (clientHandle !== null && !needsMocks()) { + if (clientHandle !== null) { const result = await libparsec.clientStartUserInvitationGreet(clientHandle, token); if (result.ok) { this.handle = result.value.handle; } return result; - } else { - this.handle = DEFAULT_HANDLE; - await wait(MOCK_WAITING_TIME); - return { ok: true, value: { handle: DEFAULT_HANDLE } }; } + return generateNoHandleError(); } async initialWaitGuest(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterUserInitialDoWaitPeer(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - this.hostSASCode = result.value.greeterSas; - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - this.hostSASCode = '2EDF'; - return { - ok: true, - value: { handle: DEFAULT_HANDLE, greeterSas: this.hostSASCode }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterUserInitialDoWaitPeer(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; + this.hostSASCode = result.value.greeterSas; } + return result; } async waitGuestTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterUserInProgress1DoWaitPeerTrust(this.canceller, this.handle!); - if (result.ok) { - this.handle = result.value.handle; - this.SASCodeChoices = result.value.claimerSasChoices; - this.correctSASCode = result.value.claimerSas; - } - this.canceller = null; - return result; - } else { - await wait(MOCK_WAITING_TIME); - this.SASCodeChoices = ['1ABC', '2DEF', '3GHI', '4JKL']; - this.correctSASCode = '2DEF'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - claimerSasChoices: this.SASCodeChoices, - claimerSas: this.correctSASCode, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterUserInProgress1DoWaitPeerTrust(this.canceller, this.handle!); + if (result.ok) { + this.handle = result.value.handle; + this.SASCodeChoices = result.value.claimerSasChoices; + this.correctSASCode = result.value.claimerSas; } + this.canceller = null; + return result; } async denyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterUserInProgress2DoDenyTrust(this.canceller, this.handle!); - this.handle = null; - this.canceller = null; - return result; - } else { - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterUserInProgress2DoDenyTrust(this.canceller, this.handle!); + this.handle = null; + this.canceller = null; + return result; } async signifyTrust(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterUserInProgress2DoSignifyTrust(this.canceller, this.handle!); - if (result.ok) { - this.handle = result.value.handle; - } - this.canceller = null; - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { ok: true, value: { handle: DEFAULT_HANDLE } }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterUserInProgress2DoSignifyTrust(this.canceller, this.handle!); + if (result.ok) { + this.handle = result.value.handle; } + this.canceller = null; + return result; } async getClaimRequests(): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await libparsec.greeterUserInProgress3DoGetClaimRequests(this.canceller, this.handle!); - this.canceller = null; - if (result.ok) { - this.handle = result.value.handle; - this.requestedHumanHandle = result.value.requestedHumanHandle; - this.requestedDeviceLabel = result.value.requestedDeviceLabel || ''; - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - this.requestedHumanHandle = { - label: 'Gordon Freeman', - email: 'gordon.freeman@blackmesa.nm', - }; - this.requestedDeviceLabel = 'My Device'; - return { - ok: true, - value: { - handle: DEFAULT_HANDLE, - requestedDeviceLabel: this.requestedDeviceLabel, - requestedHumanHandle: this.requestedHumanHandle, - }, - }; + this.canceller = await libparsec.newCanceller(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = await libparsec.greeterUserInProgress3DoGetClaimRequests(this.canceller, this.handle!); + this.canceller = null; + if (result.ok) { + this.handle = result.value.handle; + this.requestedHumanHandle = result.value.requestedHumanHandle; + this.requestedDeviceLabel = result.value.requestedDeviceLabel || ''; } + return result; } async createUser(humanHandle: HumanHandle, profile: UserProfile): Promise> { this._assertState(true, false); - if (!needsMocks()) { - this.canceller = await libparsec.newCanceller(); - const result = await libparsec.greeterUserInProgress4DoCreate( - this.canceller, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.handle!, - humanHandle, - this.requestedDeviceLabel, - profile, - ); - this.canceller = null; - this.handle = null; - return result; - } else { - this.handle = null; - return { ok: true, value: null }; - } + this.canceller = await libparsec.newCanceller(); + const result = await libparsec.greeterUserInProgress4DoCreate( + this.canceller, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.handle!, + humanHandle, + this.requestedDeviceLabel, + profile, + ); + this.canceller = null; + this.handle = null; + return result; } } diff --git a/client/src/parsec/history.ts b/client/src/parsec/history.ts index 67b6daefbd1..664a24ee131 100644 --- a/client/src/parsec/history.ts +++ b/client/src/parsec/history.ts @@ -1,12 +1,7 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { needsMocks } from '@/parsec/environment'; -import { wait } from '@/parsec/internals'; -import { MockFiles } from '@/parsec/mock_files'; -import { generateEntries, generateFile, generateFolder } from '@/parsec/mock_generator'; import { Path } from '@/parsec/path'; import { - EntryName, FileDescriptor, FsPath, Result, @@ -16,9 +11,7 @@ import { WorkspaceHistoryEntryStatFolder, WorkspaceHistoryEntryStatTag, WorkspaceHistoryFdCloseError, - WorkspaceHistoryFdCloseErrorTag, WorkspaceHistoryFdReadError, - WorkspaceHistoryFdReadErrorTag, WorkspaceHistoryOpenFileError, WorkspaceHistoryStatEntryError, WorkspaceHistoryStatFolderChildrenError, @@ -26,42 +19,31 @@ import { import { libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; -const MOCK_OPENED_FILES = new Map(); -let MOCK_CURRENT_FD = 1; - export async function statFolderChildrenAt( handle: WorkspaceHandle, path: FsPath, at: DateTime, ): Promise, WorkspaceHistoryStatFolderChildrenError>> { - if (!needsMocks()) { - const result = await libparsec.workspaceHistoryStatFolderChildren(handle, at.toSeconds() as any as DateTime, path); - if (result.ok) { - const cooked: Array = []; - for (const [name, stat] of result.value) { - stat.created = DateTime.fromSeconds(stat.created as any as number); - stat.updated = DateTime.fromSeconds(stat.updated as any as number); - if (stat.tag === WorkspaceHistoryEntryStatTag.File) { - (stat as WorkspaceHistoryEntryStatFile).isFile = (): boolean => true; - (stat as WorkspaceHistoryEntryStatFile).name = name; - (stat as WorkspaceHistoryEntryStatFile).path = await Path.join(path, name); - } else { - (stat as WorkspaceHistoryEntryStatFolder).isFile = (): boolean => false; - (stat as WorkspaceHistoryEntryStatFolder).name = name; - (stat as WorkspaceHistoryEntryStatFolder).path = await Path.join(path, name); - } - cooked.push(stat as WorkspaceHistoryEntryStat); + const result = await libparsec.workspaceHistoryStatFolderChildren(handle, at.toSeconds() as any as DateTime, path); + if (result.ok) { + const cooked: Array = []; + for (const [name, stat] of result.value) { + stat.created = DateTime.fromSeconds(stat.created as any as number); + stat.updated = DateTime.fromSeconds(stat.updated as any as number); + if (stat.tag === WorkspaceHistoryEntryStatTag.File) { + (stat as WorkspaceHistoryEntryStatFile).isFile = (): boolean => true; + (stat as WorkspaceHistoryEntryStatFile).name = name; + (stat as WorkspaceHistoryEntryStatFile).path = await Path.join(path, name); + } else { + (stat as WorkspaceHistoryEntryStatFolder).isFile = (): boolean => false; + (stat as WorkspaceHistoryEntryStatFolder).name = name; + (stat as WorkspaceHistoryEntryStatFolder).path = await Path.join(path, name); } - return { ok: true, value: cooked }; + cooked.push(stat as WorkspaceHistoryEntryStat); } - return result; + return { ok: true, value: cooked }; } - // Take some time to load - await wait(1500); - const items = (await generateEntries(path)).map((entry) => { - return entry as any as WorkspaceHistoryEntryStat; - }); - return { ok: true, value: items }; + return result; } export async function entryStatAt( @@ -70,25 +52,20 @@ export async function entryStatAt( at: DateTime, ): Promise> { const fileName = (await Path.filename(path)) || ''; - - if (!needsMocks()) { - const result = await libparsec.workspaceHistoryStatEntry(workspaceHandle, at.toSeconds() as any as DateTime, path); - if (result.ok) { - if (result.value.tag === WorkspaceHistoryEntryStatTag.File) { - (result.value as WorkspaceHistoryEntryStatFile).isFile = (): boolean => true; - (result.value as WorkspaceHistoryEntryStatFile).name = fileName; - (result.value as WorkspaceHistoryEntryStatFile).path = path; - } else { - (result.value as WorkspaceHistoryEntryStatFolder).isFile = (): boolean => false; - (result.value as WorkspaceHistoryEntryStatFolder).name = fileName; - (result.value as WorkspaceHistoryEntryStatFolder).path = path; - } - return result as Result; + const result = await libparsec.workspaceHistoryStatEntry(workspaceHandle, at.toSeconds() as any as DateTime, path); + if (result.ok) { + if (result.value.tag === WorkspaceHistoryEntryStatTag.File) { + (result.value as WorkspaceHistoryEntryStatFile).isFile = (): boolean => true; + (result.value as WorkspaceHistoryEntryStatFile).name = fileName; + (result.value as WorkspaceHistoryEntryStatFile).path = path; + } else { + (result.value as WorkspaceHistoryEntryStatFolder).isFile = (): boolean => false; + (result.value as WorkspaceHistoryEntryStatFolder).name = fileName; + (result.value as WorkspaceHistoryEntryStatFolder).path = path; } - return result; + return result as Result; } - const entry = fileName.startsWith('File_') ? await generateFile(path, { fileName: fileName }) : await generateFolder(path); - return { ok: true, value: entry as any as WorkspaceHistoryEntryStat }; + return result; } export async function openFileAt( @@ -96,30 +73,14 @@ export async function openFileAt( path: FsPath, at: DateTime, ): Promise> { - if (workspaceHandle && !needsMocks()) { - const result = await libparsec.workspaceHistoryOpenFile(workspaceHandle, at.toSeconds() as any as DateTime, path); - return result; - } else { - const fd = MOCK_CURRENT_FD; - MOCK_CURRENT_FD += 1; - MOCK_OPENED_FILES.set(fd, path); - return { ok: true, value: fd }; - } + return await libparsec.workspaceHistoryOpenFile(workspaceHandle, at.toSeconds() as any as DateTime, path); } export async function closeHistoryFile( workspaceHandle: WorkspaceHandle, fd: FileDescriptor, ): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceHistoryFdClose(workspaceHandle, fd); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceHistoryFdCloseErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - MOCK_OPENED_FILES.delete(fd); - return { ok: true, value: null }; - } + return await libparsec.workspaceHistoryFdClose(workspaceHandle, fd); } export async function readHistoryFile( @@ -127,54 +88,11 @@ export async function readHistoryFile( fd: FileDescriptor, offset: number, size: number, -): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceHistoryFdRead(workspaceHandle, fd, offset, size); - } else { - if (!MOCK_OPENED_FILES.has(fd)) { - return { ok: false, error: { tag: WorkspaceHistoryFdReadErrorTag.BadFileDescriptor, error: 'Invalid file descriptor' } }; - } - await wait(100); - const path = MOCK_OPENED_FILES.get(fd) as string; - const fileName = (await Path.filename(path)) as EntryName; - const ext = Path.getFileExtension(fileName); - - switch (ext) { - case 'xlsx': - console.log('Using XLSX content'); - return { ok: true, value: MockFiles.XLSX }; - case 'png': - console.log('Using PNG content'); - return { ok: true, value: MockFiles.PNG }; - case 'docx': - console.log('Using DOCX content'); - return { ok: true, value: MockFiles.DOCX }; - case 'txt': - console.log('Using TXT content'); - return { ok: true, value: MockFiles.TXT }; - case 'py': - console.log('Using PY content'); - return { ok: true, value: MockFiles.PY }; - case 'pdf': - console.log('Using PDF content'); - return { ok: true, value: MockFiles.PDF }; - case 'mp3': - console.log('Using MP3 content'); - return { ok: true, value: MockFiles.MP3 }; - case 'mp4': - console.log('Using MP4 content'); - return { ok: true, value: MockFiles.MP4 }; - } - console.log('Using default file content'); - return { - ok: true, - value: new Uint8Array([ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 6, 0, 0, 0, 141, 111, 38, 229, 0, 0, 0, 28, - 73, 68, 65, 84, 8, 215, 99, 248, 255, 255, 63, 195, 127, 6, 32, 5, 195, 32, 18, 132, 208, 49, 241, 130, 88, 205, 4, 0, 14, 245, 53, - 203, 209, 142, 14, 31, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, - ]), - }; - } +): Promise> { + return (await libparsec.workspaceHistoryFdRead(workspaceHandle, fd, BigInt(offset), BigInt(size))) as Result< + Uint8Array, + WorkspaceHistoryFdReadError + >; } export interface HistoryEntryTree { @@ -221,7 +139,7 @@ export async function listTreeAt( tree.maxFilesReached = true; } } else { - tree.totalSize += (entry as WorkspaceHistoryEntryStatFile).size; + tree.totalSize += Number((entry as WorkspaceHistoryEntryStatFile).size); tree.entries.push(entry as WorkspaceHistoryEntryStatFile); if (tree.entries.length > filesLimit) { tree.maxFilesReached = true; diff --git a/client/src/parsec/invitation.ts b/client/src/parsec/invitation.ts index f17988266a8..d057ba35604 100644 --- a/client/src/parsec/invitation.ts +++ b/client/src/parsec/invitation.ts @@ -1,13 +1,9 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { needsMocks } from '@/parsec/environment'; import { getParsecHandle } from '@/parsec/routing'; import { ClientCancelInvitationError, - ClientNewDeviceInvitationError, ClientNewUserInvitationError, - ClientNewUserInvitationErrorTag, - InvitationEmailSentStatus, InvitationStatus, InvitationToken, ListInvitationsError, @@ -15,54 +11,17 @@ import { Result, UserInvitation, } from '@/parsec/types'; -import { listUsers } from '@/parsec/user'; -import { InviteListInvitationCreatedByTag, InviteListItem, InviteListItemTag, libparsec } from '@/plugins/libparsec'; +import { generateNoHandleError } from '@/parsec/utils'; +import { InviteListItem, InviteListItemTag, libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; export async function inviteUser(email: string): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientNewUserInvitation(handle, email, true); - } else { - const usersResult = await listUsers(true); - if (usersResult.ok) { - if (usersResult.value.map((u) => u.humanHandle.email).includes(email)) { - return { - ok: false, - error: { - tag: ClientNewUserInvitationErrorTag.AlreadyMember, - error: `${email} is already a member of this organization`, - }, - }; - } - } - return { - ok: true, - value: { - token: '12346565645645654645645645645645', - emailSentStatus: InvitationEmailSentStatus.Success, - // cspell:disable-next-line - addr: 'parsec3://parsec.example.com/Org?a=claimer_user&p=xBjXbfjrnrnrjnrjnrnjrjnrjnrjnrjnrjk', - }, - }; - } -} - -export async function inviteDevice( - sendEmail: boolean, -): Promise> { - const handle = getParsecHandle(); - - if (handle !== null && !needsMocks()) { - const ret = await libparsec.clientNewDeviceInvitation(handle, sendEmail); - if (ret.ok) { - return { ok: true, value: [ret.value.token, ret.value.emailSentStatus] }; - } else { - return ret; - } } - return { ok: true, value: ['1234', InvitationEmailSentStatus.Success] }; + return generateNoHandleError(); } export async function listUserInvitations(options?: { @@ -84,7 +43,7 @@ export async function listUserInvitations(options?: { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientListInvitations(handle); if (!result.ok) { @@ -99,57 +58,15 @@ export async function listUserInvitations(options?: { return item; }); return result as any; - } else { - return { - ok: true, - value: [ - { - tag: InviteListItemTag.User, - // cspell:disable-next-line - addr: 'parsec3://parsec.example.com/MyOrg?a=claim_device&token=xBjXbfjrnrnrjnrjnrnjrjnrjnrjnrjnrjk', - token: '12346565645645654645645645645645', - createdOn: DateTime.now(), - claimerEmail: 'shadowheart@swordcoast.faerun', - createdBy: { - tag: InviteListInvitationCreatedByTag.User, - humanHandle: { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }, - userId: '1234', - }, - status: InvitationStatus.Ready, - }, - { - tag: InviteListItemTag.User, - // cspell:disable-next-line - addr: 'parsec3://parsec.example.com/MyOrg?a=claim_user&token=xBjfbfjrnrnrjnrjnrnjrjnrjnrjnrjnrjk', - token: '32346565645645654645645645645645', - createdOn: DateTime.now(), - createdBy: { - tag: InviteListInvitationCreatedByTag.User, - humanHandle: { - email: 'gale@waterdeep.faerun', - // cspell:disable-next-line - label: 'Gale Dekarios', - }, - userId: '1234', - }, - claimerEmail: 'gale@waterdeep.faerun', - status: InvitationStatus.Ready, - }, - ], - }; } + return generateNoHandleError(); } export async function cancelInvitation(token: InvitationToken): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientCancelInvitation(handle, token); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } diff --git a/client/src/parsec/login.ts b/client/src/parsec/login.ts index f194a339643..b03efa4d79f 100644 --- a/client/src/parsec/login.ts +++ b/client/src/parsec/login.ts @@ -1,29 +1,19 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { - ActiveUsersLimitTag, - DeviceAccessStrategyKeyring, - DeviceFileType, - DeviceSaveStrategyKeyring, - DeviceSaveStrategyPassword, - libparsec, -} from '@/plugins/libparsec'; - -import { needsMocks } from '@/parsec/environment'; -import { DEFAULT_HANDLE, getClientConfig } from '@/parsec/internals'; +import { DeviceAccessStrategyKeyring, DeviceSaveStrategyKeyring, DeviceSaveStrategyPassword, libparsec } from '@/plugins/libparsec'; + +import { getClientConfig } from '@/parsec/internals'; import { parseParsecAddr } from '@/parsec/organization'; import { getParsecHandle } from '@/parsec/routing'; import { AvailableDevice, ClientChangeAuthenticationError, - ClientChangeAuthenticationErrorTag, ClientEvent, ClientEventInvitationChanged, ClientEventTag, ClientInfo, ClientInfoError, ClientStartError, - ClientStartErrorTag, ClientStopError, ConnectionHandle, DeviceAccessStrategy, @@ -35,6 +25,7 @@ import { Result, UserProfile, } from '@/parsec/types'; +import { generateNoHandleError } from '@/parsec/utils'; import { getConnectionHandle } from '@/router'; import { EventDistributor, Events } from '@/services/eventDistributor'; import { DateTime } from 'luxon'; @@ -49,32 +40,6 @@ export interface LoggedInDeviceInfo { const loggedInDevices: Array = []; -export function mockLoggedInDevice(): void { - if (loggedInDevices.length === 0) { - loggedInDevices.push({ - handle: DEFAULT_HANDLE, - device: { - keyFilePath: '/fake', - createdOn: DateTime.now(), - protectedOn: DateTime.now(), - serverUrl: 'parsec3://127.0.0.1:6770?no_ssl=true', - organizationId: 'MyOrg', - userId: 'MockUserId', - deviceId: 'MockDeviceId', - humanHandle: { - label: 'Gordon Freeman', - email: 'gordon.freeman@blackmesa.nm', - }, - deviceLabel: 'HEV Suit', - ty: DeviceFileType.Password, - }, - isExpired: false, - isOnline: true, - shouldAcceptTos: false, - }); - } -} - export async function getLoggedInDevices(): Promise> { return loggedInDevices; } @@ -95,15 +60,6 @@ export function getConnectionInfo(handle: ConnectionHandle | null = null): Logge if (!handle) { handle = getParsecHandle(); } - if (needsMocks()) { - return { - handle: DEFAULT_HANDLE, - device: {} as AvailableDevice, - isExpired: false, - isOnline: true, - shouldAcceptTos: false, - }; - } return loggedInDevices.find((info) => info.handle === handle); } @@ -247,30 +203,12 @@ export async function login( const callback = (handle: ConnectionHandle, event: ClientEvent): void => { parsecEventCallback(eventDistributor, event, handle); }; - if (!needsMocks()) { - const clientConfig = getClientConfig(); - const result = await libparsec.clientStart(clientConfig, callback, accessStrategy); - if (result.ok) { - loggedInDevices.push({ handle: result.value, device: device, isExpired: false, isOnline: false, shouldAcceptTos: false }); - } - return result; - } else { - if ( - accessStrategy.tag === DeviceAccessStrategyTag.Password && - ['P@ssw0rd.', 'AVeryL0ngP@ssw0rd'].includes((accessStrategy as DeviceAccessStrategyPassword).password) - ) { - loggedInDevices.push({ handle: DEFAULT_HANDLE, device: device, isExpired: false, isOnline: true, shouldAcceptTos: false }); - callback(DEFAULT_HANDLE, { tag: ClientEventTag.Online }); - return { ok: true, value: DEFAULT_HANDLE }; - } - return { - ok: false, - error: { - tag: ClientStartErrorTag.LoadDeviceDecryptionFailed, - error: 'WrongPassword', - }, - }; + const clientConfig = getClientConfig(); + const result = await libparsec.clientStart(clientConfig, callback, accessStrategy); + if (result.ok) { + loggedInDevices.push({ handle: result.value, device: device, isExpired: false, isOnline: false, shouldAcceptTos: false }); } + return result; } export async function logout(handle?: ConnectionHandle | undefined | null): Promise> { @@ -278,7 +216,7 @@ export async function logout(handle?: ConnectionHandle | undefined | null): Prom handle = getParsecHandle(); } - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientStop(handle); if (result.ok) { const index = loggedInDevices.findIndex((info) => info.handle === handle); @@ -287,13 +225,8 @@ export async function logout(handle?: ConnectionHandle | undefined | null): Prom } } return result; - } else { - const index = loggedInDevices.findIndex((info) => info.handle === handle); - if (index !== -1) { - loggedInDevices.splice(index, 1); - } - return { ok: true, value: null }; } + return generateNoHandleError(); } export async function getClientInfo(handle: ConnectionHandle | null = null): Promise> { @@ -301,31 +234,10 @@ export async function getClientInfo(handle: ConnectionHandle | null = null): Pro handle = getConnectionHandle(); } - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientInfo(handle); - } else { - return { - ok: true, - value: { - organizationAddr: 'parsec3://example.com/MyOrg', - organizationId: 'MyOrg', - deviceId: 'device1', - deviceLabel: 'My First Device', - userId: 'me', - currentProfile: UserProfile.Admin, - humanHandle: { - email: 'user@host.com', - label: 'Gordon Freeman', - }, - serverConfig: { - userProfileOutsiderAllowed: true, - activeUsersLimit: { - tag: ActiveUsersLimitTag.NoLimit, - }, - }, - }, - }; } + return generateNoHandleError(); } export async function getClientProfile(): Promise { @@ -358,40 +270,20 @@ export async function getCurrentAvailableDevice(): Promise device.deviceId === clientResult.value.deviceId); - if (!needsMocks()) { - const currentAvailableDevice = availableDevices.find((device) => device.deviceId === clientResult.value.deviceId); - if (!currentAvailableDevice) { - return { ok: false, error: { tag: 'NotFound' } }; - } - return { ok: true, value: currentAvailableDevice }; - } else { - const device = availableDevices[0]; - // Uncomment this to experience the login as you would with keyring - // device.ty = DeviceFileType.Keyring; - return { ok: true, value: device }; + const currentAvailableDevice = availableDevices.find((device) => device.deviceId === clientResult.value.deviceId); + if (!currentAvailableDevice) { + return { ok: false, error: { tag: 'NotFound' } }; } + return { ok: true, value: currentAvailableDevice }; } export async function changeAuthentication( accessStrategy: DeviceAccessStrategy, saveStrategy: DeviceSaveStrategy, ): Promise> { - if (!needsMocks()) { - const clientConfig = getClientConfig(); - return await libparsec.clientChangeAuthentication(clientConfig, accessStrategy, saveStrategy); - } else { - // Fake an error - if ( - accessStrategy.tag === DeviceAccessStrategyTag.Password && - (accessStrategy as DeviceAccessStrategyPassword).password !== 'P@ssw0rd.' - ) { - return { ok: false, error: { tag: ClientChangeAuthenticationErrorTag.DecryptionFailed, error: 'Invalid password' } }; - } - return { ok: true, value: null }; - } + const clientConfig = getClientConfig(); + return await libparsec.clientChangeAuthentication(clientConfig, accessStrategy, saveStrategy); } export async function isKeyringAvailable(): Promise { @@ -429,14 +321,7 @@ export const SaveStrategy = { }; export async function isAuthenticationValid(device: AvailableDevice, accessStrategy: DeviceAccessStrategy): Promise { - if (!needsMocks()) { - const clientConfig = getClientConfig(); - const result = await libparsec.clientStart(clientConfig, (_handle: number, _event: ClientEvent) => {}, accessStrategy); - return result.ok; - } else { - return ( - accessStrategy.tag === DeviceAccessStrategyTag.Password && - ['P@ssw0rd.', 'AVeryL0ngP@ssw0rd'].includes((accessStrategy as DeviceAccessStrategyPassword).password) - ); - } + const clientConfig = getClientConfig(); + const result = await libparsec.clientStart(clientConfig, (_handle: number, _event: ClientEvent) => {}, accessStrategy); + return result.ok; } diff --git a/client/src/parsec/organization.ts b/client/src/parsec/organization.ts index 5285c40cc52..6ed45e054a7 100644 --- a/client/src/parsec/organization.ts +++ b/client/src/parsec/organization.ts @@ -8,8 +8,6 @@ import { libparsec, } from '@/plugins/libparsec'; -import { needsMocks } from '@/parsec/environment'; -import { MOCK_WAITING_TIME, wait } from '@/parsec/internals'; import { getClientInfo } from '@/parsec/login'; import { AvailableDevice, @@ -17,7 +15,6 @@ import { BootstrapOrganizationErrorTag, ClientConfig, ClientEvent, - DeviceFileType, DeviceSaveStrategy, OrganizationID, OrganizationInfo, @@ -46,53 +43,33 @@ export async function createOrganization( const bootstrapAddr = await libparsec.buildParsecOrganizationBootstrapAddr(serverAddr, orgName); - if (!needsMocks()) { - const config: ClientConfig = { - configDir: window.getConfigDir(), - dataBaseDir: window.getDataBaseDir(), - mountpointMountStrategy: { tag: MountpointMountStrategyTag.Disabled }, - workspaceStorageCacheSize: { tag: WorkspaceStorageCacheSizeTag.Default }, - withMonitors: false, - preventSyncPattern: null, - }; - const result = await libparsec.bootstrapOrganization( - config, - parsecEventCallback, - bootstrapAddr, - saveStrategy, - { label: userName, email: email }, - deviceLabel, - null, - ); - if (!result.ok && result.error.tag === BootstrapOrganizationErrorTag.TimestampOutOfBallpark) { - result.error.clientTimestamp = DateTime.fromSeconds(result.error.clientTimestamp as any as number); - result.error.serverTimestamp = DateTime.fromSeconds(result.error.serverTimestamp as any as number); - } else if (result.ok) { - result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); - result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - keyFilePath: '/path', - serverUrl: 'https://parsec.invalid', - createdOn: DateTime.utc(), - protectedOn: DateTime.utc(), - organizationId: 'MyOrg', - userId: 'userid', - deviceId: 'deviceid', - humanHandle: { - label: 'A', - email: 'a@b.c', - }, - deviceLabel: 'a@b', - ty: DeviceFileType.Password, - }, - }; + console.log(bootstrapAddr); + + const config: ClientConfig = { + configDir: window.getConfigDir(), + dataBaseDir: window.getDataBaseDir(), + mountpointMountStrategy: { tag: MountpointMountStrategyTag.Disabled }, + workspaceStorageCacheSize: { tag: WorkspaceStorageCacheSizeTag.Default }, + withMonitors: false, + preventSyncPattern: null, + }; + const result = await libparsec.bootstrapOrganization( + config, + parsecEventCallback, + bootstrapAddr, + saveStrategy, + { label: userName, email: email }, + deviceLabel, + null, + ); + if (!result.ok && result.error.tag === BootstrapOrganizationErrorTag.TimestampOutOfBallpark) { + result.error.clientTimestamp = DateTime.fromSeconds(result.error.clientTimestamp as any as number); + result.error.serverTimestamp = DateTime.fromSeconds(result.error.serverTimestamp as any as number); + } else if (result.ok) { + result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); + result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); } + return result; } export async function bootstrapOrganization( @@ -106,53 +83,31 @@ export async function bootstrapOrganization( console.log('On event', event); } - if (!needsMocks()) { - const config: ClientConfig = { - configDir: window.getConfigDir(), - dataBaseDir: window.getDataBaseDir(), - mountpointMountStrategy: { tag: MountpointMountStrategyTag.Disabled }, - workspaceStorageCacheSize: { tag: WorkspaceStorageCacheSizeTag.Default }, - withMonitors: false, - preventSyncPattern: null, - }; - const result = await libparsec.bootstrapOrganization( - config, - parsecEventCallback, - bootstrapAddr, - saveStrategy, - { label: userName, email: email }, - deviceLabel, - null, - ); - if (!result.ok && result.error.tag === BootstrapOrganizationErrorTag.TimestampOutOfBallpark) { - result.error.clientTimestamp = DateTime.fromSeconds(result.error.clientTimestamp as any as number); - result.error.serverTimestamp = DateTime.fromSeconds(result.error.serverTimestamp as any as number); - } else if (result.ok) { - result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); - result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); - } - return result; - } else { - await wait(MOCK_WAITING_TIME); - return { - ok: true, - value: { - keyFilePath: '/path', - serverUrl: 'https://parsec.invalid', - createdOn: DateTime.utc(), - protectedOn: DateTime.utc(), - organizationId: 'MyOrg', - userId: 'userid', - deviceId: 'deviceid', - humanHandle: { - label: 'A', - email: 'a@b.c', - }, - deviceLabel: 'a@b', - ty: DeviceFileType.Password, - }, - }; + const config: ClientConfig = { + configDir: window.getConfigDir(), + dataBaseDir: window.getDataBaseDir(), + mountpointMountStrategy: { tag: MountpointMountStrategyTag.Disabled }, + workspaceStorageCacheSize: { tag: WorkspaceStorageCacheSizeTag.Default }, + withMonitors: false, + preventSyncPattern: null, + }; + const result = await libparsec.bootstrapOrganization( + config, + parsecEventCallback, + bootstrapAddr, + saveStrategy, + { label: userName, email: email }, + deviceLabel, + null, + ); + if (!result.ok && result.error.tag === BootstrapOrganizationErrorTag.TimestampOutOfBallpark) { + result.error.clientTimestamp = DateTime.fromSeconds(result.error.clientTimestamp as any as number); + result.error.serverTimestamp = DateTime.fromSeconds(result.error.serverTimestamp as any as number); + } else if (result.ok) { + result.value.createdOn = DateTime.fromSeconds(result.value.createdOn as any as number); + result.value.protectedOn = DateTime.fromSeconds(result.value.protectedOn as any as number); } + return result; } export async function parseParsecAddr(addr: string): Promise> { @@ -185,7 +140,7 @@ export async function getOrganizationInfo(): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientAcceptTos(handle, updatedOn.toSeconds() as any as DateTime); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } export async function getTOS(): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientGetTos(handle); if (result.ok) { result.value.updatedOn = DateTime.fromSeconds(result.value.updatedOn as any as number); } return result; - } else { - return { - ok: true, - value: { - perLocaleUrls: new Map([ - ['en-US', 'https://parsec.cloud/en/404'], - ['fr-FR', 'https://parsec.cloud/404'], - ]), - updatedOn: DateTime.now(), - }, - }; } + return generateNoHandleError(); } diff --git a/client/src/parsec/user.ts b/client/src/parsec/user.ts index 05c27545179..f7ef044217b 100644 --- a/client/src/parsec/user.ts +++ b/client/src/parsec/user.ts @@ -2,9 +2,9 @@ import { libparsec } from '@/plugins/libparsec'; -import { needsMocks } from '@/parsec/environment'; import { getParsecHandle } from '@/parsec/routing'; -import { ClientListUsersError, ClientRevokeUserError, Result, UserID, UserInfo, UserProfile } from '@/parsec/types'; +import { ClientListUsersError, ClientRevokeUserError, Result, UserID, UserInfo } from '@/parsec/types'; +import { generateNoHandleError } from '@/parsec/utils'; import { DateTime } from 'luxon'; function filterUserList(list: Array, pattern: string): Array { @@ -17,7 +17,7 @@ function filterUserList(list: Array, pattern: string): Array export async function listUsers(skipRevoked = true, pattern = ''): Promise, ClientListUsersError>> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientListUsers(handle, skipRevoked); if (result.ok) { const frozenResult = await libparsec.clientListFrozenUsers(handle); @@ -39,134 +39,17 @@ export async function listUsers(skipRevoked = true, pattern = ''): Promise, ClientListUsersError>>; - } else { - let value: Array = [ - { - id: 'me', - humanHandle: { - email: 'user@host.com', - label: 'Gordon Freeman', - }, - currentProfile: UserProfile.Admin, - createdOn: DateTime.now(), - createdBy: 'device', - revokedOn: null, - revokedBy: null, - isRevoked: (): boolean => false, - isFrozen: (): boolean => false, - isActive: (): boolean => true, - }, - { - id: '0123456789abcdef012345689abcdef', - // cspell:disable-next-line - humanHandle: { label: 'Cernd', email: 'cernd@gmail.com' }, - currentProfile: UserProfile.Standard, - createdOn: DateTime.now(), - createdBy: 'device', - revokedOn: null, - revokedBy: null, - isRevoked: (): boolean => false, - isFrozen: (): boolean => false, - isActive: (): boolean => true, - }, - { - id: '123456789abcdef012345689abcdef0', - // cspell:disable-next-line - humanHandle: { label: 'Jaheira', email: 'jaheira@gmail.com' }, - currentProfile: UserProfile.Admin, - createdOn: DateTime.now(), - createdBy: 'device', - revokedOn: null, - revokedBy: null, - isRevoked: (): boolean => false, - isFrozen: (): boolean => false, - isActive: (): boolean => true, - }, - { - id: '23456789abcdef012345689abcdef01', - // cspell:disable-next-line - humanHandle: { label: 'Karl Hungus', email: 'karlhungus@gmail.com' }, - currentProfile: UserProfile.Outsider, - createdOn: DateTime.utc(1998, 4, 22), - createdBy: 'device', - revokedOn: null, - revokedBy: null, - isRevoked: (): boolean => false, - isFrozen: (): boolean => true, - isActive: (): boolean => false, - }, - { - id: '3456789abcdef012345689abcdef012', - // cspell:disable-next-line - humanHandle: { label: 'Patches', email: 'patches@yahoo.fr' }, - currentProfile: UserProfile.Standard, - createdOn: DateTime.utc(2009, 10, 6), - createdBy: 'device', - revokedOn: null, - revokedBy: null, - isRevoked: (): boolean => false, - isFrozen: (): boolean => false, - isActive: (): boolean => true, - }, - ]; - if (!skipRevoked) { - value.push( - { - id: '456789abcdef012345689abcdef0123', - // cspell:disable-next-line - humanHandle: { label: 'Arthas Menethil', email: 'arthasmenethil@gmail.com' }, - currentProfile: UserProfile.Admin, - createdOn: DateTime.utc(2002, 7, 3), - createdBy: 'device', - revokedOn: DateTime.utc(2022, 4, 7), - revokedBy: 'device', - isRevoked: (): boolean => true, - isFrozen: (): boolean => false, - isActive: (): boolean => false, - }, - { - id: '56789abcdef012345689abcdef01234', - // cspell:disable-next-line - humanHandle: { label: 'Gaia', email: 'gaia@gmail.com' }, - currentProfile: UserProfile.Outsider, - createdOn: DateTime.utc(2019, 7, 16), - createdBy: 'device', - revokedOn: DateTime.utc(2023, 11, 3), - revokedBy: 'device', - isRevoked: (): boolean => true, - isFrozen: (): boolean => false, - isActive: (): boolean => false, - }, - { - id: '6789abcdef012345689abcdef012345', - // cspell:disable-next-line - humanHandle: { label: 'Valygar Corthala', email: 'val@gmail.com' }, - currentProfile: UserProfile.Standard, - createdOn: DateTime.utc(2015, 2, 17), - createdBy: 'device', - revokedOn: DateTime.utc(2024, 5, 18), - revokedBy: 'device', - isRevoked: (): boolean => true, - isFrozen: (): boolean => false, - isActive: (): boolean => false, - }, - ); - } - if (pattern.length > 0) { - value = filterUserList(value, pattern); - } - return { ok: true, value: value }; } + return generateNoHandleError(); } export async function revokeUser(userId: UserID): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientRevokeUser(handle, userId); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } export enum UserInfoErrorTag { diff --git a/client/src/parsec/utils.ts b/client/src/parsec/utils.ts new file mode 100644 index 00000000000..09aab789b12 --- /dev/null +++ b/client/src/parsec/utils.ts @@ -0,0 +1,7 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS + +import { Result } from '@/parsec/types'; + +export function generateNoHandleError(): Result { + return { ok: false, error: { tag: 'Internal', error: 'No handle' } as any }; +} diff --git a/client/src/parsec/workspace.ts b/client/src/parsec/workspace.ts index 2defadd114b..a62970675f6 100644 --- a/client/src/parsec/workspace.ts +++ b/client/src/parsec/workspace.ts @@ -1,7 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS import { DataCache } from '@/common/cache'; -import { needsMocks } from '@/parsec/environment'; import { getClientInfo } from '@/parsec/login'; import { getParsecHandle } from '@/parsec/routing'; import { @@ -21,7 +20,6 @@ import { StartedWorkspaceInfo, SystemPath, UserID, - UserProfile, UserTuple, WorkspaceDecryptPathAddrError, WorkspaceGeneratePathAddrError, @@ -29,12 +27,12 @@ import { WorkspaceID, WorkspaceInfo, WorkspaceInfoError, - WorkspaceInfoErrorTag, WorkspaceMountError, WorkspaceMountErrorTag, WorkspaceName, WorkspaceRole, } from '@/parsec/types'; +import { generateNoHandleError } from '@/parsec/utils'; import { WorkspaceStopError, libparsec } from '@/plugins/libparsec'; import { DateTime } from 'luxon'; @@ -75,7 +73,7 @@ export async function listWorkspaces( handle = getParsecHandle(); } - if (handle !== null && !needsMocks()) { + if (handle !== null) { const result = await libparsec.clientListWorkspaces(handle); if (result.ok) { @@ -106,112 +104,24 @@ export async function listWorkspaces( } else { return result; } - } else { - const value: Array = [ - { - id: '1', - currentName: 'Trademeet', - currentSelfRole: WorkspaceRole.Owner, - size: 934_583, - lastUpdated: DateTime.now().minus(2000), - availableOffline: false, - isStarted: false, - isBootstrapped: false, - sharing: [], - mountpoints: [[1, '/home/a']], - handle: 1, - }, - { - id: '2', - currentName: 'The Copper Coronet', - currentSelfRole: WorkspaceRole.Contributor, - size: 3_489_534_274, - lastUpdated: DateTime.now(), - availableOffline: false, - isStarted: false, - isBootstrapped: true, - sharing: [], - mountpoints: [[2, '/home/b']], - handle: 2, - }, - { - id: '3', - currentName: "Watcher's Keep", - currentSelfRole: WorkspaceRole.Reader, - size: 56_153_023, - lastUpdated: DateTime.now(), - availableOffline: true, - isStarted: false, - isBootstrapped: true, - sharing: [], - mountpoints: [[3, '/home/c']], - handle: 3, - }, - ]; - - return { ok: true, value: value }; } + return generateNoHandleError(); } export async function getWorkspaceInfo(workspaceHandle: WorkspaceHandle): Promise> { - if (!needsMocks()) { - const result = await libparsec.workspaceInfo(workspaceHandle); - if (result.ok) { - (result.value as StartedWorkspaceInfo).handle = workspaceHandle; - const createdResult = await libparsec.workspaceHistoryGetWorkspaceManifestV1Timestamp(workspaceHandle); - if (createdResult.ok && createdResult.value) { - try { - (result.value as StartedWorkspaceInfo).created = DateTime.fromSeconds(createdResult.value as any as number); - } catch (error: any) { - console.error(error); - } + const result = await libparsec.workspaceInfo(workspaceHandle); + if (result.ok) { + (result.value as StartedWorkspaceInfo).handle = workspaceHandle; + const createdResult = await libparsec.workspaceHistoryGetWorkspaceManifestV1Timestamp(workspaceHandle); + if (createdResult.ok && createdResult.value) { + try { + (result.value as StartedWorkspaceInfo).created = DateTime.fromSeconds(createdResult.value as any as number); + } catch (error: any) { + console.error(error); } } - return result as Result; - } else { - switch (workspaceHandle) { - case 1: - return { - ok: true, - value: { - client: 42, - id: '1', - currentName: 'Trademeet', - currentSelfRole: WorkspaceRole.Owner, - mountpoints: [[1, '/home/a']], - handle: workspaceHandle, - created: DateTime.now().minus({ days: 8 }), - }, - }; - case 2: - return { - ok: true, - value: { - client: 42, - id: '2', - currentName: 'The Copper Coronet', - currentSelfRole: WorkspaceRole.Manager, - mountpoints: [[1, '/home/b']], - handle: workspaceHandle, - created: DateTime.now().minus({ days: 12 }), - }, - }; - case 3: - return { - ok: true, - value: { - client: 42, - id: '3', - currentName: "Watcher's Keep", - currentSelfRole: WorkspaceRole.Reader, - mountpoints: [[1, '/home/c']], - handle: workspaceHandle, - }, - }; - default: - return { ok: false, error: { tag: WorkspaceInfoErrorTag.Internal, error: 'internal' } }; - } } + return result as Result; } const WORKSPACE_NAMES_CACHE = new DataCache(); @@ -233,21 +143,19 @@ export async function getWorkspaceName(workspaceHandle: WorkspaceHandle): Promis export async function createWorkspace(name: WorkspaceName): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientCreateWorkspace(handle, name); - } else { - return { ok: true, value: '1337' }; } + return generateNoHandleError(); } export async function renameWorkspace(newName: WorkspaceName, id: WorkspaceID): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientRenameWorkspace(handle, id, newName); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } export async function getWorkspaceSharing( @@ -257,7 +165,7 @@ export async function getWorkspaceSharing( ): Promise, ClientListWorkspaceUsersError>> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { let selfId: UserID | null = null; if (!includeSelf) { @@ -302,58 +210,9 @@ export async function getWorkspaceSharing( } return { ok: true, value: value }; } - return { ok: false, error: result.error }; - } else { - const value: Array<[UserTuple, WorkspaceRole | null]> = []; - - if (workspaceId === '1' || workspaceId === '2') { - value.push([ - { - id: '0123456789abcdef012345689abcdef', - // cspell:disable-next-line - humanHandle: { label: 'Korgan Bloodaxe', email: 'korgan@gmail.com' }, - profile: UserProfile.Standard, - }, - WorkspaceRole.Reader, - ]); - } - if (workspaceId === '2') { - value.push([ - { - id: '123456789abcdef012345689abcdef0', - // cspell:disable-next-line - humanHandle: { label: 'Cernd', email: 'cernd@gmail.com' }, - profile: UserProfile.Admin, - }, - WorkspaceRole.Contributor, - ]); - } - - if (includeSelf) { - value.push([ - { - id: 'me', - humanHandle: { email: 'user@host.com', label: 'Gordon Freeman' }, - profile: UserProfile.Admin, - }, - WorkspaceRole.Owner, - ]); - } - - if (includeAllUsers) { - value.push([ - { - id: '23456789abcdef012345689abcdef01', - // cspell:disable-next-line - humanHandle: { label: 'Jaheira', email: 'jaheira@gmail.com' }, - profile: UserProfile.Outsider, - }, - null, - ]); - } - - return { ok: true, value: value }; + return result; } + return generateNoHandleError(); } export async function shareWorkspace( @@ -363,11 +222,10 @@ export async function shareWorkspace( ): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.clientShareWorkspace(handle, workspaceId, userId, role); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } export async function startWorkspace( @@ -378,39 +236,34 @@ export async function startWorkspace( connectionHandle = getParsecHandle(); } - if (connectionHandle !== null && !needsMocks()) { + if (connectionHandle !== null) { return await libparsec.clientStartWorkspace(connectionHandle, workspaceId); - } else { - return { ok: true, value: 1337 }; } + return generateNoHandleError(); } export async function stopWorkspace(workspaceHandle: WorkspaceHandle): Promise> { const handle = getParsecHandle(); - if (handle !== null && !needsMocks()) { + if (handle !== null) { return await libparsec.workspaceStop(workspaceHandle); - } else { - return { ok: true, value: null }; } + return generateNoHandleError(); } export async function mountWorkspace( workspaceHandle: WorkspaceHandle, ): Promise> { - if (!needsMocks()) { - const startedWorkspaceResult = await getWorkspaceInfo(workspaceHandle); - if (!startedWorkspaceResult.ok) { - console.error(`Failed to get started workspace info: ${startedWorkspaceResult.error}`); - return { ok: false, error: { tag: WorkspaceMountErrorTag.Internal, error: '' } }; - } else { - if (startedWorkspaceResult.value.mountpoints.length > 0) { - return { ok: true, value: startedWorkspaceResult.value.mountpoints[0] }; - } + const startedWorkspaceResult = await getWorkspaceInfo(workspaceHandle); + if (!startedWorkspaceResult.ok) { + console.error(`Failed to get started workspace info: ${startedWorkspaceResult.error}`); + return { ok: false, error: { tag: WorkspaceMountErrorTag.Internal, error: '' } }; + } else { + if (startedWorkspaceResult.value.mountpoints.length > 0) { + return { ok: true, value: startedWorkspaceResult.value.mountpoints[0] }; } - return await libparsec.workspaceMount(workspaceHandle); } - return { ok: true, value: [0, ''] }; + return await libparsec.workspaceMount(workspaceHandle); } export async function getPathLink( @@ -418,29 +271,17 @@ export async function getPathLink( path: string, timestamp: DateTime | null = null, ): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceGeneratePathAddr(workspaceHandle, path); + if (timestamp) { + window.electronAPI.log('warn', 'Parameter `timestamp` is ignored'); } - - const org = 'Org'; - // cspell:disable-next-line - const payload = 'k8QY94a350f2f629403db2269c44583f7aa1AcQ0Zkd8YbWfYF19LMwc55HjBOvI8LA8c_9oU2xaBJ0u2Ou0AFZYA4-QHhi2FprzAtUoAgMYwg'; - let link = `parsec3://parsec.cloud/${org}?a=path&p=${payload}`; - if (timestamp !== null) { - // cspell:disable-next-line - link += '×tamp=JEFHNUJEF39350JFHNsss'; - } - return { ok: true, value: link }; + return await libparsec.workspaceGeneratePathAddr(workspaceHandle, path); } export async function decryptFileLink( workspaceHandle: WorkspaceHandle, link: ParsecWorkspacePathAddr, ): Promise> { - if (!needsMocks()) { - return await libparsec.workspaceDecryptPathAddr(workspaceHandle, link); - } - return { ok: true, value: '/' }; + return await libparsec.workspaceDecryptPathAddr(workspaceHandle, link); } export interface SharedWithInfo { @@ -491,8 +332,5 @@ export async function getSystemPath( if (infoResult.value.mountpoints.length === 0) { return { ok: false, error: { tag: MountpointToOsPathErrorTag.Internal, error: 'not mounted' } }; } - if (!needsMocks()) { - return await libparsec.mountpointToOsPath(infoResult.value.mountpoints[0][0], entryPath); - } - return { ok: true, value: `/home${entryPath}` }; + return await libparsec.mountpointToOsPath(infoResult.value.mountpoints[0][0], entryPath); } diff --git a/client/src/plugins/libparsec/definitions.ts b/client/src/plugins/libparsec/definitions.ts index 32a132a6560..b5067d155bd 100644 --- a/client/src/plugins/libparsec/definitions.ts +++ b/client/src/plugins/libparsec/definitions.ts @@ -102,11 +102,11 @@ export type FileDescriptor = number export type Handle = number export type U32 = number export type VersionInt = number -export type I64 = number -export type IndexInt = number -export type SizeInt = number -export type U64 = number export type { DateTime } from 'luxon'; import type { DateTime } from 'luxon'; +export type I64 = bigint +export type IndexInt = bigint +export type SizeInt = bigint +export type U64 = bigint export interface AvailableDevice { keyFilePath: Path diff --git a/client/src/router/types.ts b/client/src/router/types.ts index 74a8ec576d1..87b429618f1 100644 --- a/client/src/router/types.ts +++ b/client/src/router/types.ts @@ -50,80 +50,90 @@ const routes: Array = [ component: () => import('@/views/client-area/ClientAreaLayout.vue'), }, { - // ConnectedLayout ensure that every children components are provided - // with a fileOperationManager, informationManager and eventDistributor - // that correspond with the current ConnectionHandle. - path: '/connected', - component: () => import('@/views/layouts/ConnectedLayout.vue'), + // DevLayout is used to login a default device in case the page was + // just refreshed and we're using the testbed. + // We have to do it this way because Vue doesn't let us make async calls + // in ConnectedLayout before calling provide(). + path: '/dev', + component: () => import('@/views/layouts/DevLayout.vue'), children: [ { - path: '/sidebar', - component: () => import('@/views/sidebar-menu/SidebarMenuPage.vue'), + // ConnectedLayout ensure that every children components are provided + // with a fileOperationManager, informationManager and eventDistributor + // that correspond with the current ConnectionHandle. + path: '/connected', + component: () => import('@/views/layouts/ConnectedLayout.vue'), children: [ { - path: '/header', - component: () => import('@/views/header/HeaderPage.vue'), + path: '/sidebar', + component: () => import('@/views/sidebar-menu/SidebarMenuPage.vue'), children: [ { - path: '/fileOp', - component: () => import('@/views/layouts/FileOperationLayout.vue'), + path: '/header', + component: () => import('@/views/header/HeaderPage.vue'), children: [ { - path: `/:handle(\\d+)/${Routes.Workspaces}`, - name: Routes.Workspaces, - component: () => import('@/views/workspaces/WorkspacesPage.vue'), + path: '/fileOp', + component: () => import('@/views/layouts/FileOperationLayout.vue'), + children: [ + { + path: `/:handle(\\d+)/${Routes.Workspaces}`, + name: Routes.Workspaces, + component: () => import('@/views/workspaces/WorkspacesPage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.Documents}`, + name: Routes.Documents, + component: () => import('@/views/files/FoldersPage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.History}`, + name: Routes.History, + component: () => import('@/views/workspaces/WorkspaceHistoryPage.vue'), + }, + ], }, { - path: `/:handle(\\d+)/${Routes.Documents}`, - name: Routes.Documents, - component: () => import('@/views/files/FoldersPage.vue'), + path: '/:handle(\\d+)', + redirect: { name: Routes.Workspaces }, }, { - path: `/:handle(\\d+)/${Routes.History}`, - name: Routes.History, - component: () => import('@/views/workspaces/WorkspaceHistoryPage.vue'), + path: `/:handle(\\d+)/${Routes.Users}`, + name: Routes.Users, + component: () => import('@/views/users/UsersPage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.Storage}`, + name: Routes.Storage, + component: () => import('@/views/organizations/StoragePage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.Organization}`, + name: Routes.Organization, + component: () => import('@/views/organizations/OrganizationInformationPage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.About}`, + name: Routes.About, + component: () => import('@/views/about/AboutPage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.MyProfile}`, + name: Routes.MyProfile, + component: () => import('@/views/users/MyProfilePage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.RecoveryExport}`, + name: Routes.RecoveryExport, + component: () => import('@/views/devices/ExportRecoveryDevicePage.vue'), + }, + { + path: `/:handle(\\d+)/${Routes.Viewer}`, + name: Routes.Viewer, + component: () => import('@/views/viewers/FileViewer.vue'), }, ], }, - { - path: '/:handle(\\d+)', - redirect: { name: Routes.Workspaces }, - }, - { - path: `/:handle(\\d+)/${Routes.Users}`, - name: Routes.Users, - component: () => import('@/views/users/UsersPage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.Storage}`, - name: Routes.Storage, - component: () => import('@/views/organizations/StoragePage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.Organization}`, - name: Routes.Organization, - component: () => import('@/views/organizations/OrganizationInformationPage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.About}`, - name: Routes.About, - component: () => import('@/views/about/AboutPage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.MyProfile}`, - name: Routes.MyProfile, - component: () => import('@/views/users/MyProfilePage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.RecoveryExport}`, - name: Routes.RecoveryExport, - component: () => import('@/views/devices/ExportRecoveryDevicePage.vue'), - }, - { - path: `/:handle(\\d+)/${Routes.Viewer}`, - name: Routes.Viewer, - component: () => import('@/views/viewers/FileViewer.vue'), - }, ], }, ], diff --git a/client/src/services/fileOperationManager.ts b/client/src/services/fileOperationManager.ts index a71780127c2..e5c2d0cbb37 100644 --- a/client/src/services/fileOperationManager.ts +++ b/client/src/services/fileOperationManager.ts @@ -324,7 +324,7 @@ class FileOperationManager { const srcEntry = statResult.value; if (statResult.value.isFile()) { tree = { - totalSize: (statResult.value as EntryStatFile).size, + totalSize: Number((statResult.value as EntryStatFile).size), entries: [statResult.value as EntryStatFile], maxRecursionReached: false, maxFilesReached: false, @@ -406,7 +406,7 @@ class FileOperationManager { fdW = openWriteResult.value; // Resize the destination - await resizeFile(data.workspaceHandle, fdW, entry.size); + await resizeFile(data.workspaceHandle, fdW, Number(entry.size)); let loop = true; let offset = 0; @@ -546,7 +546,7 @@ class FileOperationManager { } if (statResult.value.isFile()) { tree = { - totalSize: (statResult.value as WorkspaceHistoryEntryStatFile).size, + totalSize: Number((statResult.value as WorkspaceHistoryEntryStatFile).size), entries: [statResult.value as WorkspaceHistoryEntryStatFile], maxRecursionReached: false, maxFilesReached: false, @@ -608,7 +608,7 @@ class FileOperationManager { fdW = openWriteResult.value; // Resize the destination - await resizeFile(data.workspaceHandle, fdW, entry.size); + await resizeFile(data.workspaceHandle, fdW, Number(entry.size)); let loop = true; let offset = 0; diff --git a/client/src/services/hotkeyManager.ts b/client/src/services/hotkeyManager.ts index e5ee20bb4af..f5f69f9070f 100644 --- a/client/src/services/hotkeyManager.ts +++ b/client/src/services/hotkeyManager.ts @@ -1,6 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { isDesktop, isLinux, isMacOS, isMobile, isWeb, isWindows, needsMocks } from '@/parsec/environment'; +import { isDesktop, isLinux, isMacOS, isMobile, isWeb, isWindows } from '@/parsec/environment'; import { Routes, currentRouteIs } from '@/router'; import { modalController } from '@ionic/vue'; @@ -50,7 +50,7 @@ export class HotkeyGroup { } add(options: HotkeyOptions, callback: () => Promise): void { - if (needsMocks()) { + if (window.isDev() && isWeb()) { options.platforms |= Platforms.Web; } this.hotkeys.push({ diff --git a/client/src/services/informationManager.ts b/client/src/services/informationManager.ts index e7dbee87cbd..8bd9e36fcd1 100644 --- a/client/src/services/informationManager.ts +++ b/client/src/services/informationManager.ts @@ -1,6 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { ConnectionHandle, EntryName, FsPath, SizeInt, UserID, WorkspaceHandle, WorkspaceRole } from '@/parsec'; +import { ConnectionHandle, EntryName, FsPath, UserID, WorkspaceHandle, WorkspaceRole } from '@/parsec'; import { getConnectionHandle } from '@/router'; import { NotificationManager } from '@/services/notificationManager'; import { modalController } from '@ionic/vue'; @@ -63,7 +63,7 @@ export interface UserSharedDocumentData extends AbstractInformationData { userId: UserID; fileName: EntryName; filePath: FsPath; - fileSize: SizeInt; + fileSize: number; } // All elements the owner's account has been imported is done diff --git a/client/src/services/injectionProvider.ts b/client/src/services/injectionProvider.ts index 53ae86cc4ad..295da3352a1 100644 --- a/client/src/services/injectionProvider.ts +++ b/client/src/services/injectionProvider.ts @@ -1,6 +1,6 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS -import { ConnectionHandle, needsMocks } from '@/parsec'; +import { ConnectionHandle, isWeb } from '@/parsec'; import { EventData, EventDistributor, Events } from '@/services/eventDistributor'; import { FileOperationManager } from '@/services/fileOperationManager'; import { Information, InformationManager } from '@/services/informationManager'; @@ -48,7 +48,7 @@ export class InjectionProvider { const inj = this.injections.get(handle); if (!inj) { - if (needsMocks()) { + if (window.isDev() && isWeb()) { return this.getDefault(); } console.warn('Could not get injections for handle', handle); diff --git a/client/src/services/storageManager.ts b/client/src/services/storageManager.ts index ba03ae8a392..1dbcaf96029 100644 --- a/client/src/services/storageManager.ts +++ b/client/src/services/storageManager.ts @@ -191,6 +191,11 @@ export class StorageManager { async retrieveBmsAccess(): Promise { return await this.internalStore.get(StorageManager.STORED_BMS_ACCESS_KEY); } + + async clearAll(): Promise { + window.electronAPI.log('warn', 'Clearing all cache'); + await this.internalStore.clear(); + } } class StorageManagerInstance { diff --git a/client/src/views/devices/GreetDeviceModal.vue b/client/src/views/devices/GreetDeviceModal.vue index 01363ba7c76..5efd7ecc161 100644 --- a/client/src/views/devices/GreetDeviceModal.vue +++ b/client/src/views/devices/GreetDeviceModal.vue @@ -149,7 +149,7 @@
diff --git a/client/src/views/home/DeviceJoinOrganizationModal.vue b/client/src/views/home/DeviceJoinOrganizationModal.vue index 8c7dc4b479c..c6b073840c8 100644 --- a/client/src/views/home/DeviceJoinOrganizationModal.vue +++ b/client/src/views/home/DeviceJoinOrganizationModal.vue @@ -89,7 +89,7 @@
{{ $msTranslate('ClaimDeviceModal.subtitles.done') }} diff --git a/client/src/views/home/HomePageHeader.vue b/client/src/views/home/HomePageHeader.vue index 2025daeb369..1b2ceedcc9f 100644 --- a/client/src/views/home/HomePageHeader.vue +++ b/client/src/views/home/HomePageHeader.vue @@ -101,7 +101,6 @@ import { InjectionProvider, InjectionProviderKey } from '@/services/injectionPro import { LogoRowWhite, MsImage, Translatable, MsModalResult } from 'megashark-lib'; import { onMounted, onUnmounted, ref, inject, Ref } from 'vue'; import { Env } from '@/services/environment'; -import { needsMocks } from '@/parsec'; import UpdateAppModal from '@/views/about/UpdateAppModal.vue'; import { APP_VERSION } from '@/services/environment'; @@ -117,10 +116,6 @@ onMounted(async () => { } }); window.electronAPI.getUpdateAvailability(); - if (needsMocks()) { - // Dispatch dummy update event to be able to debug the UpdateAppModal - eventDistributor.dispatchEvent(Events.UpdateAvailability, { updateAvailable: true, version: 'v3.1.0' }); - } }); onUnmounted(async () => { diff --git a/client/src/views/layouts/ConnectedLayout.vue b/client/src/views/layouts/ConnectedLayout.vue index 45a6a8a95e7..106c771f576 100644 --- a/client/src/views/layouts/ConnectedLayout.vue +++ b/client/src/views/layouts/ConnectedLayout.vue @@ -8,9 +8,9 @@ diff --git a/client/src/views/layouts/LoadingLayout.vue b/client/src/views/layouts/LoadingLayout.vue index fdaf2e76ad3..144e95cd566 100644 --- a/client/src/views/layouts/LoadingLayout.vue +++ b/client/src/views/layouts/LoadingLayout.vue @@ -18,7 +18,6 @@ diff --git a/client/src/views/organizations/creation/CreateOrganizationSaas.vue b/client/src/views/organizations/creation/CreateOrganizationSaas.vue index 36ccc2456c0..d34c19fad1b 100644 --- a/client/src/views/organizations/creation/CreateOrganizationSaas.vue +++ b/client/src/views/organizations/creation/CreateOrganizationSaas.vue @@ -212,6 +212,7 @@ async function onCreateClicked(): Promise { if (!props.bootstrapLink) { const response = await BmsAccessInstance.get().createOrganization(organizationName.value); + console.log(response); if (response.isError) { console.log('Failed to create organization'); // TODO: Change this error handling with the real backend response diff --git a/client/src/views/users/GreetUserModal.vue b/client/src/views/users/GreetUserModal.vue index 6d51dd48202..bd96dcde89e 100644 --- a/client/src/views/users/GreetUserModal.vue +++ b/client/src/views/users/GreetUserModal.vue @@ -50,7 +50,7 @@
@@ -96,7 +96,7 @@ :title="'UsersPage.greet.profileDropdownTitle'" :label="'UsersPage.greet.profileDropdownPlaceholder'" :options="profileOptions" - @change="setUserProfile($event.option.key as UserProfile)" + @change="setUserProfile" />
@@ -178,9 +178,10 @@ import { MsSpinner, MsWizardStepper, Translatable, + MsDropdownChangeEvent, } from 'megashark-lib'; import { close } from 'ionicons/icons'; -import { Ref, computed, onMounted, onUnmounted, ref, watch } from 'vue'; +import { Ref, computed, onMounted, ref } from 'vue'; enum GreetUserStep { WaitForGuest = 1, @@ -240,13 +241,10 @@ function getTitleAndSubtitle(): [Translatable, Translatable] { return ['', '']; } -function setUserProfile(role: UserProfile): void { - profile.value = role; -} - -const unwatchProfile = watch(profile, async () => { +async function setUserProfile(event: MsDropdownChangeEvent): Promise { + profile.value = event.option.key; await updateCanGoForward(); -}); +} async function updateCanGoForward(): Promise { if (pageStep.value === GreetUserStep.WaitForGuest && waitingForGuest.value === true) { @@ -488,10 +486,6 @@ async function nextStep(): Promise { onMounted(async () => { await startProcess(); }); - -onUnmounted(async () => { - unwatchProfile(); -});