From 7a1207691f78be42d2f34dc6a83aa1339920467b Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 12:14:12 +0100 Subject: [PATCH 1/6] added clippy and fixes --- README.md | 16 ++ back-end/node/src/api/node.rs | 10 +- back-end/node/src/api/servers/rest.rs | 28 +-- back-end/node/src/bootstrap/config.rs | 4 +- back-end/node/src/bootstrap/init.rs | 21 +- back-end/node/src/main.rs | 2 +- back-end/node/src/modules/space.rs | 20 +- .../src/modules/ssi/did/resolvers/adapter.rs | 6 +- .../ssi/did/resolvers/peer/document.rs | 4 +- .../ssi/did/resolvers/peer/generator.rs | 14 +- .../modules/ssi/did/resolvers/peer/parser.rs | 2 +- .../src/modules/ssi/did/resolvers/types.rs | 16 +- back-end/node/src/modules/ssi/did/types.rs | 2 +- back-end/node/src/modules/ssi/did/util.rs | 8 +- .../node/src/modules/ssi/webauthn/auth.rs | 64 +++--- .../node/src/modules/ssi/webauthn/state.rs | 6 +- back-end/project.json | 74 +++--- nx.json | 13 +- user-interface/flow-web/yarn.lock | 215 ++++++++++++++++++ 19 files changed, 373 insertions(+), 152 deletions(-) diff --git a/README.md b/README.md index 1b26d4fc..c2773088 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,22 @@ The project uses [nx](https://nx.dev/) to manage the workspace. You will need to - Rust and Cargo installed - Node.js and npm/yarn/pnpm +Depending on how you installed `nx`. In the project root, run + +```sh +nx --version + +# Output +# Nx Version: +# - Local: Not found +# - Global: v21.6.4 +``` + +you might need to initilise `nx`. If you installed, `nx` with `brew` or the output of the command above returns ` - Local: Not found` + +``` +nx init --interactive=false --useDotNxInstallation=true +``` ### Getting Started diff --git a/back-end/node/src/api/node.rs b/back-end/node/src/api/node.rs index 0dab3b0c..7f6888fe 100644 --- a/back-end/node/src/api/node.rs +++ b/back-end/node/src/api/node.rs @@ -31,7 +31,7 @@ impl Node { } pub async fn create_space(&self, dir: &str) -> Result<(), AppError> { - info!("Setting up space in Directory: {}", dir); + info!("Setting up space in Directory: {dir}"); space::new_space(&self.db, dir).await?; Ok(()) } @@ -42,7 +42,7 @@ impl Node { info!("Starting WebAuthn Registration.."); webauthn::auth::start_registration(self) .await - .map_err(|e| AppError::Auth(format!("WebAuthn registration failed: {}", e))) + .map_err(|e| AppError::Auth(format!("WebAuthn registration failed: {e}"))) } pub async fn finish_webauthn_registration( @@ -53,7 +53,7 @@ impl Node { info!("Finishing WebAuthn Registration.."); webauthn::auth::finish_registration(self, challenge_id, reg) .await - .map_err(|e| AppError::Auth(format!("WebAuthn registration failed: {}", e))) + .map_err(|e| AppError::Auth(format!("WebAuthn registration failed: {e}"))) } pub async fn start_webauthn_authentication( @@ -61,7 +61,7 @@ impl Node { ) -> Result<(RequestChallengeResponse, String), AppError> { webauthn::auth::start_authentication(self) .await - .map_err(|e| AppError::Auth(format!("WebAuthn authentication start failed: {}", e))) + .map_err(|e| AppError::Auth(format!("WebAuthn authentication start failed: {e}"))) } pub async fn finish_webauthn_authentication( @@ -72,6 +72,6 @@ impl Node { info!("Finishing WebAuthn Authentication.."); webauthn::auth::finish_authentication(self, challenge_id, auth) .await - .map_err(|e| AppError::Auth(format!("WebAuthn authentication failed: {}", e))) + .map_err(|e| AppError::Auth(format!("WebAuthn authentication failed: {e}"))) } } diff --git a/back-end/node/src/api/servers/rest.rs b/back-end/node/src/api/servers/rest.rs index 652af298..4451a6c4 100644 --- a/back-end/node/src/api/servers/rest.rs +++ b/back-end/node/src/api/servers/rest.rs @@ -73,10 +73,7 @@ async fn start_webauthn_registration( let node = app_state.node.read().await; match node.start_webauthn_registration().await { Ok((challenge, challenge_key)) => { - info!( - "WebAuthn registration started successfully with challenge_id: {}", - challenge_key - ); + info!("WebAuthn registration started successfully with challenge_id: {challenge_key}"); Ok(Json(json!({ "challenge": challenge, "challenge_id": challenge_key @@ -104,10 +101,10 @@ async fn finish_webauthn_registration( serde_json::Value::Object(credential_value.clone()), ) .map_err(|e| { - error!("Failed to parse credential: {}", e); + error!("Failed to parse credential: {e}"); ( StatusCode::BAD_REQUEST, - format!("Invalid credential format: {}", e), + format!("Invalid credential format: {e}"), ) })?; @@ -116,10 +113,7 @@ async fn finish_webauthn_registration( .finish_webauthn_registration(challenge_id, reg_credential) .await .map_err(|e| { - error!( - "WebAuthn registration failed for challenge_id {}: {}", - challenge_id, e - ); + error!("WebAuthn registration failed for challenge_id {challenge_id}: {e}"); (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()) })?; @@ -137,10 +131,7 @@ async fn start_webauthn_authentication( let node = app_state.node.read().await; match node.start_webauthn_authentication().await { Ok((challenge, challenge_id)) => { - info!( - "WebAuthn authentication started successfully with challenge_id: {}", - challenge_id - ); + info!("WebAuthn authentication started successfully with challenge_id: {challenge_id}"); Ok(Json(json!({ "challenge": challenge, "challenge_id": challenge_id @@ -168,10 +159,10 @@ async fn finish_webauthn_authentication( credential_value.clone(), )) .map_err(|e| { - error!("Failed to parse authentication credential: {}", e); + error!("Failed to parse authentication credential: {e}"); ( StatusCode::BAD_REQUEST, - format!("Invalid credential format: {}", e), + format!("Invalid credential format: {e}"), ) })?; @@ -180,10 +171,7 @@ async fn finish_webauthn_authentication( .finish_webauthn_authentication(challenge_id, auth_credential) .await .map_err(|e| { - error!( - "WebAuthn authentication failed for challenge_id {}: {}", - challenge_id, e - ); + error!("WebAuthn authentication failed for challenge_id {challenge_id}: {e}"); (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()) })?; diff --git a/back-end/node/src/bootstrap/config.rs b/back-end/node/src/bootstrap/config.rs index eb511b2c..af4df84a 100644 --- a/back-end/node/src/bootstrap/config.rs +++ b/back-end/node/src/bootstrap/config.rs @@ -43,7 +43,7 @@ impl Config { .ok() .map(|s| s.parse::()) .transpose() - .map_err(|_| AppError::Config(format!("Invalid value for {}", key)))? + .map_err(|_| AppError::Config(format!("Invalid value for {key}")))? .unwrap_or(default)) }; @@ -53,7 +53,7 @@ impl Config { .ok() .map(|s| bool::from_str(&s.to_lowercase())) .transpose() - .map_err(|_| AppError::Config(format!("Invalid boolean value for {}", key)))? + .map_err(|_| AppError::Config(format!("Invalid boolean value for {key}")))? .unwrap_or(default)) }; diff --git a/back-end/node/src/bootstrap/init.rs b/back-end/node/src/bootstrap/init.rs index dd3e92b8..121c3764 100644 --- a/back-end/node/src/bootstrap/init.rs +++ b/back-end/node/src/bootstrap/init.rs @@ -60,7 +60,7 @@ pub fn get_flow_config_dir() -> String { pub fn initialize_config_dir(dir: &str) -> Result { let p = paths(dir); let _created = create_directory(&p.config_dir) - .map_err(|e| AppError::Bootstrap(format!("Failed to create directory. {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to create directory. {e}")))?; let lock_file = p.config_dir.join(".init.lock"); let file = fs::OpenOptions::new() @@ -73,10 +73,7 @@ pub fn initialize_config_dir(dir: &str) -> Result { if p.auth_file.exists() { fs4::fs_std::FileExt::unlock(&file)?; return load_existing(&p).map_err(|e| { - AppError::Bootstrap(format!( - "Error while loading existing configurations. {}", - e - )) + AppError::Bootstrap(format!("Error while loading existing configurations. {e}")) }); } @@ -112,7 +109,7 @@ fn generate_keys_and_did() -> (Vec, Vec, String, String) { multicodec_key.extend_from_slice(&pub_key_bytes); let pub_key_multibase = multibase::encode(Base::Base58Btc, &multicodec_key); - let did = format!("did:key:{}", pub_key_multibase); + let did = format!("did:key:{pub_key_multibase}"); (priv_key_bytes, pub_key_bytes, pub_key_multibase, did) } @@ -149,28 +146,28 @@ fn load_existing(p: &Paths) -> Result> { fn bootstrap_new(p: &Paths) -> Result { ensure_keystore_dir(p) - .map_err(|e| AppError::Bootstrap(format!("Failed to setup Keystore directories. {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to setup Keystore directories. {e}")))?; let (priv_key_bytes, pub_key_bytes, pub_key_multibase, did) = generate_keys_and_did(); write_atomic_with_mode(&p.priv_key_file, &priv_key_bytes, 0o600) - .map_err(|e| AppError::Bootstrap(format!("Failed to write private key: {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to write private key: {e}")))?; write_atomic_with_mode(&p.pub_key_file, &pub_key_bytes, 0o644) - .map_err(|e| AppError::Bootstrap(format!("Failed to write public key: {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to write public key: {e}")))?; let meta = AuthMetadata { schema: "flow-auth/v1".to_string(), did: did.clone(), created_at: chrono::Utc::now().to_rfc3339(), - pub_key_multibase: pub_key_multibase, + pub_key_multibase, }; let json = serde_json::to_string_pretty(&meta) - .map_err(|e| AppError::Bootstrap(format!("Failed to serialize auth metadata: {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to serialize auth metadata: {e}")))?; write_atomic_with_mode(&p.auth_file, json.as_bytes(), 0o644) - .map_err(|e| AppError::Bootstrap(format!("Failed to write auth file: {}", e)))?; + .map_err(|e| AppError::Bootstrap(format!("Failed to write auth file: {e}")))?; Ok(NodeData { id: did, diff --git a/back-end/node/src/main.rs b/back-end/node/src/main.rs index cba9655f..e5f6249e 100644 --- a/back-end/node/src/main.rs +++ b/back-end/node/src/main.rs @@ -5,7 +5,7 @@ async fn main() { env_logger::init(); if let Err(e) = node::runner::run().await { - error!("Application failed to start: {}", e); + error!("Application failed to start: {e}"); std::process::exit(1); } } diff --git a/back-end/node/src/modules/space.rs b/back-end/node/src/modules/space.rs index ef224630..8e45e10c 100644 --- a/back-end/node/src/modules/space.rs +++ b/back-end/node/src/modules/space.rs @@ -13,17 +13,17 @@ use sha2::{Digest, Sha256}; use space::Entity as Space; pub async fn new_space(db: &DatabaseConnection, dir: &str) -> Result<(), AppError> { - info!("Setting up space in directory: {}", dir); + info!("Setting up space in directory: {dir}"); let path = Path::new(dir); if !path.exists() { - info!("Creating directory: {}", dir); - fs::create_dir_all(path).map_err(|e| AppError::IO(e))?; + info!("Creating directory: {dir}"); + fs::create_dir_all(path).map_err(AppError::IO)?; } let space_key = generate_space_key(dir)?; - info!("Generated space key: {}", space_key); + info!("Generated space key: {space_key}"); match Space::find() .filter(entity::space::Column::Key.eq(&space_key)) @@ -32,15 +32,13 @@ pub async fn new_space(db: &DatabaseConnection, dir: &str) -> Result<(), AppErro { Ok(Some(_existing_space)) => { info!( - "Space already exists at directory: {} (key: {})", - dir, space_key + "Space already exists at directory: {dir} (key: {space_key})" ); return Ok(()); } Ok(None) => { warn!( - "Directory exists but no space record found. Creating space record for: {}", - dir + "Directory exists but no space record found. Creating space record for: {dir}" ); } Err(e) => { @@ -50,7 +48,7 @@ pub async fn new_space(db: &DatabaseConnection, dir: &str) -> Result<(), AppErro let canonical_location = path .canonicalize() - .map_err(|e| AppError::IO(e))? + .map_err(AppError::IO)? .to_str() .ok_or_else(|| AppError::Config("Directory path contains invalid UTF-8".to_owned()))? .to_owned(); @@ -75,7 +73,7 @@ pub async fn new_space(db: &DatabaseConnection, dir: &str) -> Result<(), AppErro } fn generate_space_key(dir: &str) -> Result { - let path = Path::new(dir).canonicalize().map_err(|e| AppError::IO(e))?; + let path = Path::new(dir).canonicalize().map_err(AppError::IO)?; let path_str = path .to_str() @@ -86,7 +84,7 @@ fn generate_space_key(dir: &str) -> Result { let hash = hasher.finalize(); // Convert to hex string - Ok(format!("{:x}", hash)) + Ok(format!("{hash:x}")) } ////////////////////////////////////////////////////////////////////////// diff --git a/back-end/node/src/modules/ssi/did/resolvers/adapter.rs b/back-end/node/src/modules/ssi/did/resolvers/adapter.rs index e1389dc5..8c1e02a2 100644 --- a/back-end/node/src/modules/ssi/did/resolvers/adapter.rs +++ b/back-end/node/src/modules/ssi/did/resolvers/adapter.rs @@ -123,7 +123,7 @@ impl DidResolver { public_key_id: did.to_string(), signed_data: did.to_string(), }), - registry_version: Some(format!("did:{}:latest", method)), + registry_version: Some(format!("did:{method}:latest")), }), "web" => match Self::web_endpoint_from_did(did) { Ok(url) => Some(VdrInfo { @@ -198,7 +198,7 @@ impl DidResolver { } // Seed a base https:// URL with the authority (host[:port]) - let mut url = Url::parse(&format!("https://{}/", authority_dec))?; + let mut url = Url::parse(&format!("https://{authority_dec}/"))?; // Collect and decode path segments let mut segs: Vec = parts @@ -258,7 +258,7 @@ impl DidResolver { let start = Instant::now(); let did_ref = DID::new(did.as_bytes()).map_err(|e| { - ResolutionError::InvalidDid(format!("Invalid DID format: {:?}", e)) + ResolutionError::InvalidDid(format!("Invalid DID format: {e:?}")) })?; let ssi_options = Self::convert_options(options); let ssi_output = self.inner.resolve_with(did_ref, ssi_options).await?; diff --git a/back-end/node/src/modules/ssi/did/resolvers/peer/document.rs b/back-end/node/src/modules/ssi/did/resolvers/peer/document.rs index 93a5fb52..44f49f07 100644 --- a/back-end/node/src/modules/ssi/did/resolvers/peer/document.rs +++ b/back-end/node/src/modules/ssi/did/resolvers/peer/document.rs @@ -115,7 +115,7 @@ fn create_service( let endpoint = if service.routing_keys.is_empty() && service.accept.is_empty() { // Simple URI endpoint Endpoint::Uri(service.endpoint.clone().parse().map_err(|e| { - error!("Error encountered: {}", e); + error!("Error encountered: {e}"); PeerDidError::InvalidFormat })?) } else { @@ -130,7 +130,7 @@ fn create_service( Ok(Service { id: id .parse() - .map_err(|e| PeerDidError::DidParseError(format!("{:?}", e)))?, + .map_err(|e| PeerDidError::DidParseError(format!("{e:?}")))?, type_: OneOrMany::One(service.service_type.clone()), diff --git a/back-end/node/src/modules/ssi/did/resolvers/peer/generator.rs b/back-end/node/src/modules/ssi/did/resolvers/peer/generator.rs index b9302ce0..20108ce6 100644 --- a/back-end/node/src/modules/ssi/did/resolvers/peer/generator.rs +++ b/back-end/node/src/modules/ssi/did/resolvers/peer/generator.rs @@ -52,7 +52,7 @@ impl PeerDidGenerator { // Encode as base58btc let encoded = multibase::encode(multibase::Base::Base58Btc, &multicodec_key); - Ok(format!("did:peer:0{}", encoded)) + Ok(format!("did:peer:0{encoded}")) } /// Generate did:peer:0 from X25519 public key bytes @@ -69,7 +69,7 @@ impl PeerDidGenerator { let encoded = multibase::encode(multibase::Base::Base58Btc, &multicodec_key); - Ok(format!("did:peer:0{}", encoded)) + Ok(format!("did:peer:0{encoded}")) } /// Generate did:peer:0 from P-256 key (WebAuthn ES256) @@ -92,7 +92,7 @@ impl PeerDidGenerator { let encoded = multibase::encode(multibase::Base::Base58Btc, &multicodec_key); - Ok(format!("did:peer:0{}", encoded)) + Ok(format!("did:peer:0{encoded}")) } _ => Err(PeerDidError::UnsupportedKeyType), } @@ -112,7 +112,7 @@ impl PeerDidGenerator { let encoded = multibase::encode(multibase::Base::Base58Btc, &multicodec_key); - Ok(format!("did:peer:0{}", encoded)) + Ok(format!("did:peer:0{encoded}")) } _ => Err(PeerDidError::UnsupportedKeyType), } @@ -134,13 +134,13 @@ impl PeerDidGenerator { // Add verification keys (transform: E) for key in verification_keys { let encoded = Self::encode_key_with_prefix('E', &key, 0xed)?; - parts.push(format!(".{}", encoded)); + parts.push(format!(".{encoded}")); } // Add encryption keys (transform: V) for key in encryption_keys { let encoded = Self::encode_key_with_prefix('V', &key, 0xec)?; - parts.push(format!(".{}", encoded)); + parts.push(format!(".{encoded}")); } Ok(parts.join("")) @@ -157,7 +157,7 @@ impl PeerDidGenerator { let encoded = multibase::encode(multibase::Base::Base58Btc, &multicodec_key); - Ok(format!("{}{}", transform, encoded)) + Ok(format!("{transform}{encoded}")) } } diff --git a/back-end/node/src/modules/ssi/did/resolvers/peer/parser.rs b/back-end/node/src/modules/ssi/did/resolvers/peer/parser.rs index 71776bfd..bc2ccd80 100644 --- a/back-end/node/src/modules/ssi/did/resolvers/peer/parser.rs +++ b/back-end/node/src/modules/ssi/did/resolvers/peer/parser.rs @@ -140,7 +140,7 @@ impl ParsedPeerDid { } _ => { // Unknown transform - skip or error - log::warn!("Unknown transform code: {}", transform); + log::warn!("Unknown transform code: {transform}"); } } } diff --git a/back-end/node/src/modules/ssi/did/resolvers/types.rs b/back-end/node/src/modules/ssi/did/resolvers/types.rs index ebaf21fd..b22cb1d8 100644 --- a/back-end/node/src/modules/ssi/did/resolvers/types.rs +++ b/back-end/node/src/modules/ssi/did/resolvers/types.rs @@ -99,18 +99,18 @@ impl ResolutionError { impl std::fmt::Display for ResolutionError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::InvalidDid(msg) => write!(f, "Invalid DID: {}", msg), + Self::InvalidDid(msg) => write!(f, "Invalid DID: {msg}"), Self::NotFound => write!(f, "DID not found"), - Self::MethodNotSupported(method) => write!(f, "DID method '{}' not supported", method), - Self::NetworkError(msg) => write!(f, "Network error: {}", msg), - Self::InvalidDidDocument(msg) => write!(f, "Invalid DID Document: {}", msg), - Self::SecurityError(msg) => write!(f, "Security error: {}", msg), + Self::MethodNotSupported(method) => write!(f, "DID method '{method}' not supported"), + Self::NetworkError(msg) => write!(f, "Network error: {msg}"), + Self::InvalidDidDocument(msg) => write!(f, "Invalid DID Document: {msg}"), + Self::SecurityError(msg) => write!(f, "Security error: {msg}"), Self::Deactivated => write!(f, "DID has been deactivated"), Self::RepresentationNotSupported(repr) => { - write!(f, "Representation '{}' not supported", repr) + write!(f, "Representation '{repr}' not supported") } - Self::ResolutionFailed(msg) => write!(f, "Resolution failed: {}", msg), - Self::InternalError(msg) => write!(f, "Internal error: {}", msg), + Self::ResolutionFailed(msg) => write!(f, "Resolution failed: {msg}"), + Self::InternalError(msg) => write!(f, "Internal error: {msg}"), } } } diff --git a/back-end/node/src/modules/ssi/did/types.rs b/back-end/node/src/modules/ssi/did/types.rs index b483b821..ec199a4c 100644 --- a/back-end/node/src/modules/ssi/did/types.rs +++ b/back-end/node/src/modules/ssi/did/types.rs @@ -37,7 +37,7 @@ impl ResolutionOptions { pub fn with_accept(mut self, accept: &str) -> Result { let media_type = accept .parse::() - .map_err(|e| format!("Invalid media type: {}", e))?; + .map_err(|e| format!("Invalid media type: {e}"))?; self.standard.accept = Some(media_type); Ok(self) } diff --git a/back-end/node/src/modules/ssi/did/util.rs b/back-end/node/src/modules/ssi/did/util.rs index 630f4543..e405b19f 100644 --- a/back-end/node/src/modules/ssi/did/util.rs +++ b/back-end/node/src/modules/ssi/did/util.rs @@ -34,7 +34,7 @@ pub fn generate_did_peer_from_passkey( ) -> Result> { let did = PeerDidGenerator::from_passkey(passkey)?; - info!("Generated did:peer: {}", did); + info!("Generated did:peer: {did}"); Ok(did) } @@ -50,7 +50,7 @@ pub fn generate_did_key_from_passkey( // Generate DID from JWK let did = DIDKey::generate(&jwk)?; - info!("Generated DID: {}", did); + info!("Generated DID: {did}"); Ok(did.into_string()) } @@ -110,7 +110,7 @@ pub fn cose_to_jwk(cose_key: &COSEKey) -> Result }) } _ => { - error!("Unsupported COSE algorithm: {:?}", alg); + error!("Unsupported COSE algorithm: {alg:?}"); Err("Unsupported COSE algorithm".into()) } } @@ -165,7 +165,7 @@ pub fn create_did_document( let did_buf = did.parse::()?; // Create verification method ID - let verification_method_id = format!("{}#key-1", did).parse::()?; + let verification_method_id = format!("{did}#key-1").parse::()?; // Create verification method with JWK in properties let mut properties = BTreeMap::new(); diff --git a/back-end/node/src/modules/ssi/webauthn/auth.rs b/back-end/node/src/modules/ssi/webauthn/auth.rs index da526606..c81c56dd 100644 --- a/back-end/node/src/modules/ssi/webauthn/auth.rs +++ b/back-end/node/src/modules/ssi/webauthn/auth.rs @@ -53,7 +53,7 @@ pub async fn start_registration( let existing_creds = get_existing_credentials(&node.db, &device_id) .await .map_err(|e| { - error!("Failed to query existing credentials: {}", e); + error!("Failed to query existing credentials: {e}"); WebauthnError::CredentialRetrievalError })?; @@ -79,7 +79,7 @@ pub async fn start_registration( }; let mut cache = REG_CACHE.lock().map_err(|e| { - error!("Failed to acquire lock on REG_CACHE: {}", e); + error!("Failed to acquire lock on REG_CACHE: {e}"); WebauthnError::CredentialPersistenceError })?; @@ -88,13 +88,12 @@ pub async fn start_registration( cache.insert(challenge_key.clone(), session); info!( - "Started Registration process with challenge: {}", - challenge_key + "Started Registration process with challenge: {challenge_key}" ); (ccr, challenge_key) } Err(e) => { - info!("error -> {:?}", e); + info!("error -> {e:?}"); return Err(e); } }; @@ -107,11 +106,11 @@ pub async fn finish_registration( challenge_key: &str, reg: RegisterPublicKeyCredential, ) -> Result<(String, String), WebauthnError> { - info!("Finishing registration for challenge_id: {}", challenge_key); + info!("Finishing registration for challenge_id: {challenge_key}"); let (_uuid, device_id, reg_state) = { let mut cache = REG_CACHE.lock().map_err(|e| { - error!("Failed to acquire lock on REG_CACHE: {}", e); + error!("Failed to acquire lock on REG_CACHE: {e}"); WebauthnError::CredentialRetrievalError })?; @@ -135,28 +134,28 @@ pub async fn finish_registration( // Generate DID from passkey using SSI let did = generate_did_key_from_passkey(&passkey).map_err(|e| { - error!("Failed to generate DID: {}", e); + error!("Failed to generate DID: {e}"); WebauthnError::CredentialPersistenceError })?; // Create DID Document let jwk = cose_to_jwk(passkey.get_public_key()).map_err(|e| { - error!("Failed to convert COSE to JWK: {}", e); + error!("Failed to convert COSE to JWK: {e}"); WebauthnError::CredentialPersistenceError })?; let did_doc = create_did_document(&did, &jwk).map_err(|e| { - error!("Failed to create DID document: {}", e); + error!("Failed to create DID document: {e}"); WebauthnError::CredentialPersistenceError })?; let did_doc_json = did_document_to_json(&did_doc).map_err(|e| { - error!("Failed to serialize DID document: {}", e); + error!("Failed to serialize DID document: {e}"); WebauthnError::CredentialPersistenceError })?; - info!("Generated DID: {}", did); - info!("DID Document: {}", did_doc_json); + info!("Generated DID: {did}"); + info!("DID Document: {did_doc_json}"); // Create or get user with DID let user = get_or_create_user( @@ -168,20 +167,20 @@ pub async fn finish_registration( ) .await .map_err(|e| { - error!("Failed to create/get user: {}", e); + error!("Failed to create/get user: {e}"); WebauthnError::CredentialPersistenceError })?; store_passkey(&node.db, user.id, &device_id, &passkey) .await .map_err(|e| { - error!("Failed to store Passkey: {}", e.to_string()); + error!("Failed to store Passkey: {e}"); WebauthnError::CredentialPersistenceError })?; info!( - "Passkey stored successfully for user: {} (DID: {})", - user.id, did + "Passkey stored successfully for user: {0} (DID: {did})", + user.id ); Ok((did, did_doc_json)) @@ -193,10 +192,7 @@ pub async fn store_passkey( device_id: &str, passkey: &Passkey, ) -> Result> { - info!( - "Storing passkey for user {} with device_id {}", - user_id, device_id - ); + info!("Storing passkey for user {user_id} with device_id {device_id}"); // Serialize the entire Passkey object to JSON for storage let json_data = serde_json::to_string(&passkey)?; @@ -247,7 +243,7 @@ pub async fn start_authentication( node: &Node, ) -> Result<(RequestChallengeResponse, String), WebauthnError> { let device_id = node.node_data.id.as_str(); - info!("Starting authentication for device: {}", device_id); + info!("Starting authentication for device: {device_id}"); // Get all passkeys for this device let passkeys = get_passkeys_for_device(&node.db, device_id) @@ -275,7 +271,7 @@ pub async fn start_authentication( }; let mut cache = AUTH_CACHE.lock().map_err(|e| { - error!("Failed to acquire lock on AUTH_CACHE: {}", e); + error!("Failed to acquire lock on AUTH_CACHE: {e}"); WebauthnError::CredentialPersistenceError })?; @@ -284,13 +280,12 @@ pub async fn start_authentication( cache.insert(challenge_key.clone(), session); info!( - "Started authentication process with challenge: {}", - challenge_key + "Started authentication process with challenge: {challenge_key}" ); (rcr, challenge_key) } Err(e) => { - info!("Authentication start error -> {:?}", e); + info!("Authentication start error -> {e:?}"); return Err(e); } }; @@ -306,7 +301,7 @@ pub async fn finish_authentication( ) -> Result { let (_uuid, device_id, auth_state) = { let mut cache = AUTH_CACHE.lock().map_err(|e| { - error!("Failed to acquire lock on AUTH_CACHE: {}", e); + error!("Failed to acquire lock on AUTH_CACHE: {e}"); WebauthnError::CredentialRetrievalError })?; @@ -379,8 +374,7 @@ async fn update_passkey_counter( active_model.update(db).await?; info!( - "Updated passkey counter for device: {} to {}", - device_id, new_counter + "Updated passkey counter for device: {device_id} to {new_counter}" ); Ok(()) } @@ -394,7 +388,7 @@ async fn get_passkeys_by_device_id( use entity::pass_key::Column; use entity::pass_key::Entity as PassKeyEntity; - info!("Retrieving passkeys for device_id: {}", device_id); + info!("Retrieving passkeys for device_id: {device_id}"); let passkey_models = PassKeyEntity::find() .filter(Column::DeviceId.eq(device_id)) @@ -430,7 +424,7 @@ async fn _get_passkey_by_credential_id( use entity::pass_key::Column; use entity::pass_key::Entity as PassKeyEntity; - info!("Looking up passkey by credential_id: {:x?}", credential_id); + info!("Looking up passkey by credential_id: {credential_id:x?}"); let passkey_model = PassKeyEntity::find() .filter(Column::CredentialId.eq(credential_id)) @@ -501,7 +495,7 @@ async fn _update_sign_count( passkey.update(db).await?; - info!("Sign count updated successfully for passkey {}", passkey_id); + info!("Sign count updated successfully for passkey {passkey_id}"); Ok(()) } @@ -520,12 +514,12 @@ async fn get_or_create_user( .one(db) .await? { - info!("Found existing user with DID: {}", did); + info!("Found existing user with DID: {did}"); return Ok(user); } // Create new user - info!("Creating new user with DID: {}", did); + info!("Creating new user with DID: {did}"); let device_ids = vec![device_id.to_string()]; let new_user = user::ActiveModel { @@ -540,7 +534,7 @@ async fn get_or_create_user( }; let user = new_user.insert(db).await?; - info!("Created user with ID: {} and DID: {}", user.id, did); + info!("Created user with ID: {0} and DID: {did}", user.id); Ok(user) } diff --git a/back-end/node/src/modules/ssi/webauthn/state.rs b/back-end/node/src/modules/ssi/webauthn/state.rs index 6577611a..68af2299 100644 --- a/back-end/node/src/modules/ssi/webauthn/state.rs +++ b/back-end/node/src/modules/ssi/webauthn/state.rs @@ -45,17 +45,17 @@ impl AuthState { info!("Initializing WebAuthn authstate"); let rp_origin = Url::parse(&config.rp_origin) - .map_err(|e| AppError::Config(format!("Invalid WebAuthn origin URL: {}", e)))?; + .map_err(|e| AppError::Config(format!("Invalid WebAuthn origin URL: {e}")))?; let builder = WebauthnBuilder::new(&config.rp_id, &rp_origin) - .map_err(|e| AppError::Config(format!("Invalid WebAuthn configuration: {}", e)))?; + .map_err(|e| AppError::Config(format!("Invalid WebAuthn configuration: {e}")))?; let builder = builder.rp_name(&config.rp_name); let webauthn = Arc::new( builder .build() - .map_err(|e| AppError::Config(format!("Failed to build WebAuthn: {}", e)))?, + .map_err(|e| AppError::Config(format!("Failed to build WebAuthn: {e}")))?, ); Ok(AuthState { webauthn }) diff --git a/back-end/project.json b/back-end/project.json index 531fd1dd..ddce34b5 100644 --- a/back-end/project.json +++ b/back-end/project.json @@ -1,32 +1,44 @@ { - "$schema": "../node_modules/nx/schemas/project-schema.json", - "name": "back-end", - "root": "back-end", - "projectType": "application", - "targets": { - "build": { - "executor": "nx:run-commands", - "options": { - "command": "cargo build --release", - "cwd": "back-end" - }, - "outputs": [ - "{workspaceRoot}/back-end/target" - ] - }, - "test": { - "executor": "nx:run-commands", - "options": { - "command": "cargo test", - "cwd": "back-end" - } - }, - "run-node": { - "executor": "nx:run-commands", - "options": { - "command": "cargo run --bin node", - "cwd": "back-end" - } - } - } -} \ No newline at end of file + "$schema": "../node_modules/nx/schemas/project-schema.json", + "name": "back-end", + "root": "back-end", + "projectType": "application", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "cargo build --release", + "cwd": "back-end" + }, + "outputs": ["{workspaceRoot}/back-end/target"] + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "cargo test", + "cwd": "back-end" + } + }, + "run-node": { + "executor": "nx:run-commands", + "options": { + "command": "cargo run --bin node", + "cwd": "back-end" + } + }, + "lint": { + "executor": "nx:run-commands", + "options": { + "command": "cargo clippy", + "cwd": "back-end" + } + }, + "lint-fix": { + "executor": "nx:run-commands", + "options": { + "command": "cargo clippy --fix --lib -p node --allow-dirty -- --deny=clippy::uninlined_format_args", + "cwd": "back-end" + } + } + } +} diff --git a/nx.json b/nx.json index e6bafb54..99a0f4e1 100644 --- a/nx.json +++ b/nx.json @@ -1,7 +1,8 @@ { - "installation": { - "version": "21.5.3" - }, - "$schema": "./node_modules/nx/schemas/nx-schema.json", - "nxCloudId": "68cf195f6baa947a0e33ba10" -} \ No newline at end of file + "installation": { + "version": "21.5.3" + }, + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "nxCloudId": "68cf195f6baa947a0e33ba10" +} + diff --git a/user-interface/flow-web/yarn.lock b/user-interface/flow-web/yarn.lock index 86c5bb9d..7e22a805 100644 --- a/user-interface/flow-web/yarn.lock +++ b/user-interface/flow-web/yarn.lock @@ -271,11 +271,121 @@ minimatch "^9.0.3" plist "^3.1.0" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + "@esbuild/darwin-arm64@0.21.5": version "0.21.5" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz" integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint-community/eslint-utils@^4.2.0": version "4.9.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz" @@ -488,11 +598,116 @@ resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz" integrity sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA== +"@rollup/rollup-android-arm-eabi@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz" + integrity sha512-o3pcKzJgSGt4d74lSZ+OCnHwkKBeAbFDmbEm5gg70eA8VkyCuC/zV9TwBnmw6VjDlRdF4Pshfb+WE9E6XY1PoQ== + +"@rollup/rollup-android-arm64@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.2.tgz" + integrity sha512-cqFSWO5tX2vhC9hJTK8WAiPIm4Q8q/cU8j2HQA0L3E1uXvBYbOZMhE2oFL8n2pKB5sOCHY6bBuHaRwG7TkfJyw== + "@rollup/rollup-darwin-arm64@4.52.2": version "4.52.2" resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.2.tgz" integrity sha512-vngduywkkv8Fkh3wIZf5nFPXzWsNsVu1kvtLETWxTFf/5opZmflgVSeLgdHR56RQh71xhPhWoOkEBvbehwTlVA== +"@rollup/rollup-darwin-x64@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.2.tgz" + integrity sha512-h11KikYrUCYTrDj6h939hhMNlqU2fo/X4NB0OZcys3fya49o1hmFaczAiJWVAFgrM1NCP6RrO7lQKeVYSKBPSQ== + +"@rollup/rollup-freebsd-arm64@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.2.tgz" + integrity sha512-/eg4CI61ZUkLXxMHyVlmlGrSQZ34xqWlZNW43IAU4RmdzWEx0mQJ2mN/Cx4IHLVZFL6UBGAh+/GXhgvGb+nVxw== + +"@rollup/rollup-freebsd-x64@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.2.tgz" + integrity sha512-QOWgFH5X9+p+S1NAfOqc0z8qEpJIoUHf7OWjNUGOeW18Mx22lAUOiA9b6r2/vpzLdfxi/f+VWsYjUOMCcYh0Ng== + +"@rollup/rollup-linux-arm-gnueabihf@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.2.tgz" + integrity sha512-kDWSPafToDd8LcBYd1t5jw7bD5Ojcu12S3uT372e5HKPzQt532vW+rGFFOaiR0opxePyUkHrwz8iWYEyH1IIQA== + +"@rollup/rollup-linux-arm-musleabihf@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.2.tgz" + integrity sha512-gKm7Mk9wCv6/rkzwCiUC4KnevYhlf8ztBrDRT9g/u//1fZLapSRc+eDZj2Eu2wpJ+0RzUKgtNijnVIB4ZxyL+w== + +"@rollup/rollup-linux-arm64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.2.tgz" + integrity sha512-66lA8vnj5mB/rtDNwPgrrKUOtCLVQypkyDa2gMfOefXK6rcZAxKLO9Fy3GkW8VkPnENv9hBkNOFfGLf6rNKGUg== + +"@rollup/rollup-linux-arm64-musl@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.2.tgz" + integrity sha512-s+OPucLNdJHvuZHuIz2WwncJ+SfWHFEmlC5nKMUgAelUeBUnlB4wt7rXWiyG4Zn07uY2Dd+SGyVa9oyLkVGOjA== + +"@rollup/rollup-linux-loong64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.2.tgz" + integrity sha512-8wTRM3+gVMDLLDdaT6tKmOE3lJyRy9NpJUS/ZRWmLCmOPIJhVyXwjBo+XbrrwtV33Em1/eCTd5TuGJm4+DmYjw== + +"@rollup/rollup-linux-ppc64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.2.tgz" + integrity sha512-6yqEfgJ1anIeuP2P/zhtfBlDpXUb80t8DpbYwXQ3bQd95JMvUaqiX+fKqYqUwZXqdJDd8xdilNtsHM2N0cFm6A== + +"@rollup/rollup-linux-riscv64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.2.tgz" + integrity sha512-sshYUiYVSEI2B6dp4jMncwxbrUqRdNApF2c3bhtLAU0qA8Lrri0p0NauOsTWh3yCCCDyBOjESHMExonp7Nzc0w== + +"@rollup/rollup-linux-riscv64-musl@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.2.tgz" + integrity sha512-duBLgd+3pqC4MMwBrKkFxaZerUxZcYApQVC5SdbF5/e/589GwVvlRUnyqMFbM8iUSb1BaoX/3fRL7hB9m2Pj8Q== + +"@rollup/rollup-linux-s390x-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.2.tgz" + integrity sha512-tzhYJJidDUVGMgVyE+PmxENPHlvvqm1KILjjZhB8/xHYqAGeizh3GBGf9u6WdJpZrz1aCpIIHG0LgJgH9rVjHQ== + +"@rollup/rollup-linux-x64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.2.tgz" + integrity sha512-opH8GSUuVcCSSyHHcl5hELrmnk4waZoVpgn/4FDao9iyE4WpQhyWJ5ryl5M3ocp4qkRuHfyXnGqg8M9oKCEKRA== + +"@rollup/rollup-linux-x64-musl@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.2.tgz" + integrity sha512-LSeBHnGli1pPKVJ79ZVJgeZWWZXkEe/5o8kcn23M8eMKCUANejchJbF/JqzM4RRjOJfNRhKJk8FuqL1GKjF5oQ== + +"@rollup/rollup-openharmony-arm64@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.2.tgz" + integrity sha512-uPj7MQ6/s+/GOpolavm6BPo+6CbhbKYyZHUDvZ/SmJM7pfDBgdGisFX3bY/CBDMg2ZO4utfhlApkSfZ92yXw7Q== + +"@rollup/rollup-win32-arm64-msvc@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.2.tgz" + integrity sha512-Z9MUCrSgIaUeeHAiNkm3cQyst2UhzjPraR3gYYfOjAuZI7tcFRTOD+4cHLPoS/3qinchth+V56vtqz1Tv+6KPA== + +"@rollup/rollup-win32-ia32-msvc@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.2.tgz" + integrity sha512-+GnYBmpjldD3XQd+HMejo+0gJGwYIOfFeoBQv32xF/RUIvccUz20/V6Otdv+57NE70D5pa8W/jVGDoGq0oON4A== + +"@rollup/rollup-win32-x64-gnu@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.2.tgz" + integrity sha512-ApXFKluSB6kDQkAqZOKXBjiaqdF1BlKi+/eqnYe9Ee7U2K3pUDKsIyr8EYm/QDHTJIM+4X+lI0gJc3TTRhd+dA== + +"@rollup/rollup-win32-x64-msvc@4.52.2": + version "4.52.2" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.2.tgz" + integrity sha512-ARz+Bs8kY6FtitYM96PqPEVvPXqEZmPZsSkXvyX19YzDqkCaIlhCieLLMI5hxO9SRZ2XtCtm8wxhy0iJ2jxNfw== + "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz" From 50fd8ec299e63eb2795640159b9aa4d8193a457e Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:07:26 +0100 Subject: [PATCH 2/6] added github action for lint --- .github/workflows/lint.yml | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..62898b4c --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,51 @@ +name: 'Lint, Build and Test' +on: + pull_request: + branches: ['main'] + push: + branches: ['main'] + +jobs: + build-lint-and-test-changed-project: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install Global Nx CLI + run: npm install -g nx + + - name: Initialize Local Nx Wrapper + # sets up the local installation wrappers (.nx) that the subsequent 'npx nx' commands rely on. + run: nx init --interactive=false --useDotNxInstallation=true + + - name: Setup Rust Toolchain + uses: dtolnay/rust-toolchain@stable + with: + # Ensure clippy and rustfmt are available for the lint tasks + components: rustfmt, clippy + + # Determines which projects have changed since the last successful build on 'main' + - name: Set up NX Base and Head + uses: nrwl/nx-set-shas@v4 + with: + main-branch-name: 'main' + + # Lint Affected Projects + - name: Lint Affected Rust Projects (with Nx) + run: npx nx affected --target=lint --parallel=3 + + - name: Build Affected Rust Projects (with Nx) + run: npx nx affected --target=build --parallel=3 + + # Run Tests for Affected Projects + - name: Run Tests for Affected Rust Projects (with Nx) + run: npx nx affected --target=test --parallel=3 From 55e2e999bc447c8048a6eb3599a6e146646e09dc Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:21:04 +0100 Subject: [PATCH 3/6] added .editorconfig --- .editorconfig | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..bfae62de --- /dev/null +++ b/.editorconfig @@ -0,0 +1,32 @@ + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true + + +[*.{js,ts,json,md,html,css,scss}] +indent_style = space +indent_size = 2 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yaml,yml}] +indent_style = space +indent_size = 2 + +# JSON Files +[*.{json,json5,webmanifest}] +indent_size = 2 + +# Markdown Files +[*.{md,mdx}] +trim_trailing_whitespace = false From 74346c10d77946da4b608efc4f86c0f99a1779cb Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:44:33 +0100 Subject: [PATCH 4/6] added more config to vscode settings.json --- .vscode/settings.json | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1d05c7f4..1746dab6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,14 +3,39 @@ // "editor.formatOnSave": true, // Rust-specific "[rust]": { + // Set line ending to LF (Linux/macOS style, common in source control) + "files.eol": "\n", + "editor.defaultFormatter": "rust-lang.rust-analyzer", // Format on save "editor.formatOnSave": true, // Indentation: Each tab indents 4 spaces "editor.tabSize": 4 + "editor.insertSpaces": true, }, "rust-analyzer.linkedProjects": [ "./back-end/Cargo.toml" ], "rust-analyzer.cargo.features": "all" -} \ No newline at end of file + + + // Use 'clippy' instead of 'check' for continuous analysis, + // which provides much more comprehensive linting. + "rust-analyzer.check.command": "clippy", + + // Treat clippy warnings/errors as VS Code diagnostics + "rust-analyzer.check.allTargets": true, + + // Enable more diagnostic details in tooltips + "rust-analyzer.diagnostics.enableExperimental": true, + + "rust-analyzer.inlayHints.parameterHints.enable": true, + + // Suggest extensions that are beneficial for a Rust project + "recommendations": [ + "rust-lang.rust-analyzer", // Official Language Server + "vadimcn.vscode-lldb", // Debugger (essential for F5 debugging) + "tamasfe.even-better-toml", // Syntax highlighting for Cargo.toml and other TOML files + "serayuzgur.crates" // Dependency version management for Cargo.toml + ] +} From abf711a2d80c7c604558a1c39b2432565173d5f6 Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:47:24 +0100 Subject: [PATCH 5/6] added zed editor settings --- .zed/settings.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .zed/settings.json diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 00000000..e69de29b From 1494f04a1e074d5cd3c4c18b344b85242a59e58a Mon Sep 17 00:00:00 2001 From: Jidechi ukor <10085056+ukor@users.noreply.github.com> Date: Sat, 18 Oct 2025 14:54:17 +0100 Subject: [PATCH 6/6] added zed editor settings --- .zed/settings.json | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.zed/settings.json b/.zed/settings.json index e69de29b..a4517770 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -0,0 +1,41 @@ +{ + "tab_size": 4, + "soft_tabs": true, + "format_on_save": "on", + + "languages": { + "Rust": { + "formatter": "language_server", + "format_on_save": "on" + } + }, + + "lsp": { + "rust-analyzer": { + "initialization_options": { + "check": { + // Use 'clippy' for additional diagnostics on save (recommended) + "command": "clippy", + // Check the entire workspace (all crates in the project) + "allTargets": true, + "features": "all" + }, + "inlayHints": { + "chainingHints": true, + "parameterNames": true, + "typeHints": true, + "lifetimeElisionHints": "skip_trivial" + }, + "diagnostics": { + "experimental": { + "enable": false + } + }, + "cargo": { + // Include documentation targets in checks + "allTargets": true + } + } + } + } +}