lrau/
lib.rs

1//! # LrAU
2//! 
3//! LrAU is an authentication and permission management system for rust. It uses Argon2id to hash passwords to prevent against rainbow table and brute-forcing.
4//!
5//! ## Note for migrators
6//! 
7//! Since version 3.0, instead of paths being strings they are now slices. This will cause issues with legacy code, preventing it to compile, and preventing serde information from being read.
8//! 
9//! 
10//! ## Example
11//! 
12//! ```rust
13//! #[test]
14//! fn generic() {
15//!     // Load from a toml file.
16//!     let permissions: lrau::Permissions =
17//!         toml::from_str(include_str!("./generic.toml")).unwrap();
18//!     
19//!     // Create a password typical of someone who thinks their being clever.
20//!     let mut user = lrau::User::new(
21//!         String::from("john_t"),
22//!         String::from("1234"),
23//!         permissions,
24//!     );
25//! 
26//!         
27//!     // Valid their password
28//!     assert!(user.validate("1234"));
29//!     // Invalid their password
30//!     assert!(!user.validate("12345"));
31//! 
32//!     // Permissions
33//! 
34//!     // See if we have permissions to access contacts without
35//!     // mutable access.  
36//!     assert!(user.get_permission(&["contacts", "name"], false));
37//! 
38//!     // See if we can change users passwords with mut access.
39//!     assert!(user.get_permission(&["admin", "passwords"], true));
40//! 
41//!     // Nonexisting paths inherit from paths further up the tree
42//!     assert!(user.get_permission(&["admin", "passwords", "reset"], true));
43//!     
44//!     // Or are nothing if they are completely irrelevant.
45//!     assert!(!user.get_permission(&["notathing"], false));
46//! 
47//!     // Checks if we have logged in (we haven't)
48//!     assert!(!user.check_login());
49//!     assert!(!user.check_valid_login());
50//! 
51//!     // User Login
52//!     user.log_in("1234", std::time::Duration::from_secs(1));
53//! 
54//!     // Checks for logins
55//!     assert!(user.check_login());
56//!     assert!(user.check_valid_login());
57//! 
58//!     // Timeouts
59//!     std::thread::sleep(std::time::Duration::from_secs(1));
60//!     
61//!     // We are still logged in...
62//!     assert!(user.check_login());
63//!     
64//!     // But not validly.
65//!     assert!(!user.check_valid_login());
66//!     
67//!     // And so getting vaild permissions does not work.
68//!     assert_eq!(
69//!         user.get_valid_permissions(&["admin", "passwords", "reset"], true),
70//!         Err(lrau::user::SessionExpired {}),
71//!     );
72//! }
73//! ```
74//! 
75//! ## Serde
76//! 
77//! Serde is supported through the `serde` feature. If you configure in toml, you can get something like this:
78//! 
79//! ```toml
80//! [[permissions]]
81//! path = ["contacts"]
82//! auth = false
83//! 
84//! [[permissions]]
85//! path = ["contacts", "name"]
86//! auth = true
87//! 
88//! [[permissions]]
89//! path = ["contacts", "name", "middle"]
90//! auth = false
91//! 
92//! [[permissions]]
93//! path = ["contacts", "name", "last"]
94//! auth = true
95//! 
96//! [[permissions]]
97//! path = ["admin"]
98//! auth = false
99//! 
100//! [[permissions]]
101//! path = ["admin", "passwords"]
102//! auth = true
103//! mut = true
104//! ```
105//! 
106//! `mut`, be default, is assumed to be `false`, so you only need to write it if you are enabling it.
107//! 
108//! ## Features
109//! 
110//!  * Serde `serde`.
111//!  * Diesel `diesel-support`.
112//!  * Sqlx `sqlx-support`
113#![warn(clippy::pedantic)]
114#![allow(clippy::doc_markdown, clippy::missing_errors_doc)]
115
116pub mod permission;
117pub mod user;
118
119pub use permission::Permission;
120pub use permission::Permissions;
121pub use user::User;
122
123use rand::Rng;
124#[cfg(feature = "diesel-support")]
125#[macro_use]
126extern crate diesel;
127
128#[cfg(feature = "diesel-support")]
129#[macro_use]
130extern crate diesel_migrations;
131
132#[cfg(feature = "diesel-support")]
133pub mod schema;
134
135#[cfg(feature = "sql")]
136pub mod sql_support;
137
138/// Generates a random salt, this is automatically done when
139/// creating a user.
140#[must_use]
141pub fn salt() -> String {
142    // Base64 characters
143    let chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
144		abcdefghijklmnopqrstuvwxyz\
145		0123456789+/";
146
147    // Salt variable
148    let mut salt = String::new();
149
150    for _ in 0..128 {
151        // Random Number
152        let num: usize = rand::thread_rng().gen::<usize>() % chars.len();
153
154        salt.push(chars[num].into());
155    }
156
157    salt
158}