diff --git a/.drone.yml b/.drone.yml index d038898d..04f388c8 100644 --- a/.drone.yml +++ b/.drone.yml @@ -27,26 +27,34 @@ steps: - name: cargo-format image: rust:1.64 commands: - - rustup component add rustfmt && - cargo fmt --all -- --check + - rustup component add rustfmt && cargo fmt --all -- --check environment: CARGO_HOME: /drone/src/.cargo depends_on: - cargo-deps +- name: cargo-doc-ci + image: rust:1.64 + commands: + - cargo doc --document-private-items --workspace --all-features --no-deps + environment: + RUSTDOCFLAGS: -Dwarnings + depends_on: + - cargo-format + - name: cargo-clippy-ci image: rust:1.64 commands: - - rustup component add clippy && - cargo clippy -- -D warnings && - cargo clippy --features toggle -- -D warnings && - cargo clippy --release -- -D warnings && - cargo clippy --release --features toggle -- -D warnings + - rustup component add clippy + - cargo clippy --workspace -- -D warnings + - cargo clippy --workspace --all-features -- -D warnings + - cargo clippy --workspace --release -- -D warnings + - cargo clippy --workspace --release --all-features -- -D warnings environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo depends_on: - - cargo-format + - cargo-doc-ci - name: cargo-test image: rust:1.64 @@ -55,7 +63,6 @@ steps: environment: BUILD_ENV: dev CARGO_HOME: /drone/src/.cargo - CARGO_HTTP_CAINFO: "" depends_on: - cargo-clippy-ci @@ -131,8 +138,9 @@ trigger: depends_on: - default - build-production + --- kind: signature -hmac: 28171a0fb4c198384e0176ef1a6b6f120771b30b4146113488c7ff81b2e7c006 +hmac: 66badf18a9b2157be8df165e445ffeb0d793c1a9031ad1aafb32f30da1a0edfd ... diff --git a/examples/enums.rs b/examples/enums.rs index 83de4c6d..62103631 100644 --- a/examples/enums.rs +++ b/examples/enums.rs @@ -3,7 +3,7 @@ use veil::Redact; #[derive(Redact)] -#[redact(all, variant)] +#[redact(all, variant)] // Redact all the variant names! We can still skip individual variants later on by marking them as `#[redact(variant, skip)]` enum CreditCardIssuer { Visa, Mastercard, @@ -13,8 +13,11 @@ enum CreditCardIssuer { Jcb, UnionPay, - #[redact(skip, variant)] - Other(#[redact] String), + #[redact(variant, skip)] // Don't redact the name of this variant + Other( + #[redact] // But do redact the contents of this field! + String, + ), } fn main() { diff --git a/examples/manual_builder.rs b/examples/manual_builder.rs new file mode 100644 index 00000000..7c851727 --- /dev/null +++ b/examples/manual_builder.rs @@ -0,0 +1,33 @@ +use veil::redactor::{Redactor, RedactorBuilder}; + +fn main() { + // Build a new Redactor. + // We'll set up the Redactor to use flags that are equivalent to: + // `#[redact(with = 'X', partial))]` + // on a field, when using the `Redact` derive macro. + let redactor: Redactor = RedactorBuilder::new().char('X').partial().build().unwrap(); + + // We can now redact any string we want in a number of different ways... + + // Firstly, we can simply redact directly to a `String`: + assert_eq!(redactor.redact("Hello, world!".to_string()), "HelXX, XXrld!"); + + // Or, we can redact a `String` in-place, which is slightly more efficient, + // and allows us to chain multiple redactions together: + let mut hello = "Hello, world!".to_string(); + let mut goodbye = "Goodbye, world!".to_string(); + redactor.redact_in_place(&mut hello).redact_in_place(&mut goodbye); + assert_eq!(hello, "HelXX, XXrld!"); + assert_eq!(goodbye, "GooXXXX, XXrld!"); + + // Finally, we can use the `wrap` method to wrap a string in a `RedactWrapped` struct, + // which implements `Debug` and `Display` to redact the string when displayed or debugged. + let hello = "Hello, world!".to_string(); + let hello_wrapped = redactor.wrap(&hello); + + assert_ne!(hello_wrapped.to_string(), hello); + assert_ne!(format!("{:?}", hello_wrapped), format!("{:?}", hello)); + + assert_eq!(hello_wrapped.to_string(), "HelXX, XXrld!"); + assert_eq!(format!("{:?}", hello_wrapped), "\"HelXX, XXrld!\""); +} diff --git a/examples/manual_redactable.rs b/examples/manual_redactable.rs new file mode 100644 index 00000000..0130ce84 --- /dev/null +++ b/examples/manual_redactable.rs @@ -0,0 +1,36 @@ +use veil::Redactable; + +// As an alternative to redacting in a type's `std::fmt::Debug` implementation (which is what the `Redact` derive macro implements), +// you can also use the `Redactable` type to more explicitly redact structured data. +// +// The `Redactable` trait requires that a type implements `std::fmt::Display`, as this is what will be used to redact the type. + +#[derive(Redactable, Debug)] // `Redactable` doesn't touch `Debug` at all, so you can still derive it. +#[redact(with = 'X', partial)] // All the modifier flags you know and love from the `Redact` derive macro are also available here. +struct EmailAddress(String); + +// Our `Display` implementation for `EmailAddress` will simply print out the email address as-is. +// This is what will be used to redact the type. +impl std::fmt::Display for EmailAddress { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +fn main() { + let email = EmailAddress("john.doe@prima.it".to_string()); + + // The `Debug` implementation is untouched and will work as expected. + assert_eq!(format!("{:?}", email), "EmailAddress(\"john.doe@prima.it\")"); + + // So will the `Display` implementation. + assert_eq!(format!("{}", email), "john.doe@prima.it"); + + // And this is how we redact the data! + assert_eq!(email.redact(), "johX.XXX@XXXXa.it"); + + // We can also redact the data into an existing buffer, which is slightly more efficient if you've already got one lying around. + let mut buffer = String::new(); + email.redact_into(&mut buffer).unwrap(); + assert_eq!(buffer, "johX.XXX@XXXXa.it"); +} diff --git a/src/lib.rs b/src/lib.rs index 5e8025b7..9dd90ff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ -#![deny(missing_docs)] +#![warn(missing_docs)] #![cfg_attr(docsrs, feature(doc_cfg))] -//! Implements [`std::fmt::Debug`] for a struct or enum variant, with certain fields redacted. +//! Implements [`Debug`] for a struct or enum variant, with certain fields redacted. //! //! The purpose of this macro is to allow for easy, configurable and efficient redaction of sensitive data in structs and enum variants. //! This can be used to hide sensitive data in logs or anywhere where personal data should not be exposed or stored. @@ -12,7 +12,7 @@ //! //! Using the `#[redact]` attribute, you can control which fields are redacted and how. //! -//! **Fields without this attribute will NOT be redacted and will be shown using their default [`std::fmt::Debug`] implementation.** +//! **Fields without this attribute will NOT be redacted and will be shown using their default [`Debug`] implementation.** //! //! Modifiers can be applied to control how the field is redacted: //! @@ -21,7 +21,7 @@ //! | `#[redact(partial)]` | | If the string is long enough, a small part of the
beginning and end will be exposed. If the string is too short to securely expose a portion of it, it will be redacted entirely. | | Disabled. The entire string will be redacted. | //! | `#[redact(with = 'X')]` | | Specifies the `char` the string will be redacted with. | | `'*'` | //! | `#[redact(fixed = )]` | | If this modifier is present, the length and contents of
the string are completely ignored and the string will always
be redacted as a fixed number of redaction characters. | | Disabled. | -//! | `#[redact(display)]` | | Overrides the redaction behavior to use the type's [`std::fmt::Display`] implementation instead of [`std::fmt::Debug`]. | | Disabled. | +//! | `#[redact(display)]` | | Overrides the redaction behavior to use the type's [`Display`](std::fmt::Display) implementation instead of [`Debug`]. | | Disabled. | //! //! # Redacting All Fields in a Struct or Enum Variant //! @@ -210,15 +210,25 @@ //! //! # Limitations //! -//! Currently, this macro only supports [`std::fmt::Debug`] formatting with no modifiers (`{:?}`) or the "alternate" modifier (`{:#?}`). -//! Modifiers like padding, alignment, etc. are not supported as the Rust standard library does not expose any of this behaviour for us. +//! Currently, this macro only supports [`Debug`] formatting with no modifiers (`{:?}`) or the "alternate" modifier (`{:#?}`). +//! Modifiers like padding, alignment, etc. are not supported as the Rust standard library does not expose any of this behavior for us. //! -//! ## A note on [`std::fmt::Display`] +//! ## A note on [`Display`](std::fmt::Display) //! -//! This derive macro does **NOT** implement [`std::fmt::Display`]. If you want to implement it, you can do so manually. +//! This derive macro does **NOT** implement [`Display`](std::fmt::Display). If you want to implement it, you can do so manually. //! -//! [`std::fmt::Display`] should NOT be redacted. It is meant to be human-readable, and also has a snowball effect on [`ToString`] -//! as [`std::fmt::Display`] automatically implements it, leading to confusing and unexpected behaviour. +//! [`Display`](std::fmt::Display) should NOT be redacted. It is meant to be human-readable, and also has a snowball effect on [`ToString`] +//! as [`Display`](std::fmt::Display) automatically implements it, leading to confusing and unexpected behavior. +//! +//! If you want to use a type's [`Display`](std::fmt::Display) implementation during redaction, you can use the `#[redact(display)]` flag described in the [Controlling Redaction](#controlling-redaction) section. +//! +//! # Manually Redacting Data +//! +//! If you want to manually redact data, you have a few options: +//! +//! * Use the [`Redactable`](derive.Redactable.html) derive macro to generate a [`Redactable`] trait implementation for your type. +//! * Implement the [`Redactable`] trait manually. +//! * Use the provided [`RedactorBuilder`](redactor::RedactorBuilder) to build a [`Redactor`](redactor::Redactor) instance. //! //! # Environmental Awareness //! @@ -230,7 +240,7 @@ //! //! - Calling the [`veil::disable`](disable) function. See this [example](https://github.com/primait/veil/blob/master/examples/disable_redaction.rs). //! -//! These are only checked ONCE for security purposes. +//! These are only checked ONCE for security reasons. pub use veil_macros::{Redact, Redactable}; diff --git a/src/toggle.rs b/src/toggle.rs index 625454ab..782a76e5 100644 --- a/src/toggle.rs +++ b/src/toggle.rs @@ -1,10 +1,10 @@ #![cfg_attr(docsrs, doc(cfg(feature = "toggle")))] -//! Makes it possible to disable veil's redaction behaviour +//! Makes it possible to disable veil's redaction behavior use once_cell::sync::OnceCell; -/// Enum describing how Veil should behave when `std::fmt::Debug` is called on a `#[derive(Redact)]` item +/// Enum describing how Veil should behave when `Debug` is called on a `#[derive(Redact)]` item #[derive(Debug, Copy, Clone)] #[cfg_attr(docsrs, doc(cfg(feature = "toggle")))] pub enum RedactionBehavior { @@ -33,7 +33,7 @@ static DEBUG_FORMAT: OnceCell = OnceCell::new(); /// See the "Environmental Awareness" section in the [crate level documentation](../index.html) for more information. /// /// Should only be called once, preferrably at the top of main, -/// before any calls to [`std::fmt::Debug`], otherwise `Err` will be returned. +/// before any calls to [`Debug`], otherwise `Err` will be returned. /// /// Overrides the `VEIL_DISABLE_REDACTION` environment variable, if set. /// ``` diff --git a/veil-macros/src/flags.rs b/veil-macros/src/flags.rs index 2d6e6b7e..9d0b30fd 100644 --- a/veil-macros/src/flags.rs +++ b/veil-macros/src/flags.rs @@ -217,7 +217,7 @@ pub struct FieldFlags { /// Fields are not redacted by default unless their parent is marked as `#[redact(all)]`, and this flag turns off that redaction for this specific field. pub skip: bool, - /// Whether to use the type's [`Display`] implementation instead of [`Debug`]. + /// Whether to use the type's [`Display`](std::fmt::Display) implementation instead of [`Debug`]. pub display: bool, /// Flags that modify the redaction behavior. diff --git a/veil-macros/src/lib.rs b/veil-macros/src/lib.rs index ad3d70cc..3679bfeb 100644 --- a/veil-macros/src/lib.rs +++ b/veil-macros/src/lib.rs @@ -1,7 +1,6 @@ //! Macros for `veil` -#![deny(missing_docs)] -#![deny(rustdoc::broken_intra_doc_links)] +#![warn(missing_docs)] #[macro_use] extern crate quote; diff --git a/veil-tests/src/compile_tests/fail/redactable_multiple_fields.rs b/veil-tests/src/compile_tests/fail/redactable_multiple_fields.rs index cf9f7276..5d9c480a 100644 --- a/veil-tests/src/compile_tests/fail/redactable_multiple_fields.rs +++ b/veil-tests/src/compile_tests/fail/redactable_multiple_fields.rs @@ -3,7 +3,7 @@ fn main() {} #[derive(veil::Redactable)] struct Foo { bar: String, - baz: String + baz: String, } #[derive(veil::Redactable)]