stack_profile/lib.rs
1// Security lints
2#![deny(unsafe_code)]
3#![warn(clippy::unwrap_used)]
4#![warn(clippy::expect_used)]
5#![warn(clippy::panic)]
6// Prevent mem::forget from bypassing ZeroizeOnDrop
7#![warn(clippy::mem_forget)]
8// Prevent accidental data leaks via output
9#![warn(clippy::print_stdout)]
10#![warn(clippy::print_stderr)]
11#![warn(clippy::dbg_macro)]
12// Code quality
13#![warn(unreachable_pub)]
14#![warn(unused_results)]
15#![warn(clippy::todo)]
16#![warn(clippy::unimplemented)]
17// Relax in tests
18#![cfg_attr(test, allow(clippy::unwrap_used))]
19#![cfg_attr(test, allow(clippy::expect_used))]
20#![cfg_attr(test, allow(clippy::panic))]
21#![cfg_attr(test, allow(unused_results))]
22
23//! Centralised `~/.cipherstash/` profile file management.
24//!
25//! The core type is [`ProfileStore`], a directory-scoped JSON file store that
26//! handles reading, writing, and deleting profile data on disk.
27//!
28//! # Example
29//!
30//! ```no_run
31//! use stack_profile::ProfileStore;
32//! use serde::{Serialize, Deserialize};
33//!
34//! #[derive(Serialize, Deserialize)]
35//! struct MyConfig {
36//! name: String,
37//! }
38//!
39//! # fn main() -> Result<(), stack_profile::ProfileError> {
40//! let store = ProfileStore::default();
41//!
42//! store.save("my-config.json", &MyConfig { name: "example".into() })?;
43//! let config: MyConfig = store.load("my-config.json")?;
44//! # Ok(())
45//! # }
46//! ```
47//!
48//! For sensitive files, use [`ProfileStore::save_with_mode`] to restrict permissions:
49//!
50//! ```no_run
51//! # use stack_profile::ProfileStore;
52//! # use serde::{Serialize, Deserialize};
53//! # #[derive(Serialize, Deserialize)]
54//! # struct Secret { key: String }
55//! # fn main() -> Result<(), stack_profile::ProfileError> {
56//! let store = ProfileStore::default();
57//! store.save_with_mode("secret.json", &Secret { key: "shhh".into() }, 0o600)?;
58//! # Ok(())
59//! # }
60//! ```
61
62use serde::de::DeserializeOwned;
63use serde::Serialize;
64
65mod device_identity;
66mod error;
67mod profile_store;
68
69pub use device_identity::DeviceIdentity;
70pub use error::ProfileError;
71pub use profile_store::ProfileStore;
72
73/// A type that can be stored in a profile directory.
74pub trait ProfileData: Serialize + DeserializeOwned {
75 /// The filename used when saving/loading this type (e.g. `"secretkey.json"`).
76 const FILENAME: &'static str;
77
78 /// Unix file permissions for this file. `None` uses the default umask.
79 /// Sensitive files should return `Some(0o600)`.
80 const MODE: Option<u32> = None;
81}