lrau 0.6.0

LrAU is an authentication and permission management system.
Documentation
//! # LrAU
//! 
//! LrAU is an authentication and permission management system for rust. It uses Argon2id to hash passwords to prevent against rainbow table and brute-forcing.
//!
//! ## Note for migrators
//! 
//! 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.
//! 
//! 
//! ## Example
//! 
//! ```rust
//! #[test]
//! fn generic() {
//!     // Load from a toml file.
//!     let permissions: lrau::Permissions =
//!         toml::from_str(include_str!("./generic.toml")).unwrap();
//!     
//!     // Create a password typical of someone who thinks their being clever.
//!     let mut user = lrau::User::new(
//!         String::from("john_t"),
//!         String::from("1234"),
//!         permissions,
//!     );
//! 
//!         
//!     // Valid their password
//!     assert!(user.validate("1234"));
//!     // Invalid their password
//!     assert!(!user.validate("12345"));
//! 
//!     // Permissions
//! 
//!     // See if we have permissions to access contacts without
//!     // mutable access.  
//!     assert!(user.get_permission(&["contacts", "name"], false));
//! 
//!     // See if we can change users passwords with mut access.
//!     assert!(user.get_permission(&["admin", "passwords"], true));
//! 
//!     // Nonexisting paths inherit from paths further up the tree
//!     assert!(user.get_permission(&["admin", "passwords", "reset"], true));
//!     
//!     // Or are nothing if they are completely irrelevant.
//!     assert!(!user.get_permission(&["notathing"], false));
//! 
//!     // Checks if we have logged in (we haven't)
//!     assert!(!user.check_login());
//!     assert!(!user.check_valid_login());
//! 
//!     // User Login
//!     user.log_in("1234", std::time::Duration::from_secs(1));
//! 
//!     // Checks for logins
//!     assert!(user.check_login());
//!     assert!(user.check_valid_login());
//! 
//!     // Timeouts
//!     std::thread::sleep(std::time::Duration::from_secs(1));
//!     
//!     // We are still logged in...
//!     assert!(user.check_login());
//!     
//!     // But not validly.
//!     assert!(!user.check_valid_login());
//!     
//!     // And so getting vaild permissions does not work.
//!     assert_eq!(
//!         user.get_valid_permissions(&["admin", "passwords", "reset"], true),
//!         Err(lrau::user::SessionExpired {}),
//!     );
//! }
//! ```
//! 
//! ## Serde
//! 
//! Serde is supported through the `serde` feature. If you configure in toml, you can get something like this:
//! 
//! ```toml
//! [[permissions]]
//! path = ["contacts"]
//! auth = false
//! 
//! [[permissions]]
//! path = ["contacts", "name"]
//! auth = true
//! 
//! [[permissions]]
//! path = ["contacts", "name", "middle"]
//! auth = false
//! 
//! [[permissions]]
//! path = ["contacts", "name", "last"]
//! auth = true
//! 
//! [[permissions]]
//! path = ["admin"]
//! auth = false
//! 
//! [[permissions]]
//! path = ["admin", "passwords"]
//! auth = true
//! mut = true
//! ```
//! 
//! `mut`, be default, is assumed to be `false`, so you only need to write it if you are enabling it.
//! 
//! ## Features
//! 
//!  * Serde `serde`.
//!  * Diesel `diesel-support`.
//!  * Sqlx `sqlx-support`
#![warn(clippy::pedantic)]
#![allow(clippy::doc_markdown, clippy::missing_errors_doc)]

pub mod permission;
pub mod user;

pub use permission::Permission;
pub use permission::Permissions;
pub use user::User;

use rand::Rng;
#[cfg(feature = "diesel-support")]
#[macro_use]
extern crate diesel;

#[cfg(feature = "diesel-support")]
#[macro_use]
extern crate diesel_migrations;

#[cfg(feature = "diesel-support")]
pub mod schema;

#[cfg(feature = "sql")]
pub mod sql_support;

/// Generates a random salt, this is automatically done when
/// creating a user.
#[must_use]
pub fn salt() -> String {
    // Base64 characters
    let chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
		abcdefghijklmnopqrstuvwxyz\
		0123456789+/";

    // Salt variable
    let mut salt = String::new();

    for _ in 0..128 {
        // Random Number
        let num: usize = rand::thread_rng().gen::<usize>() % chars.len();

        salt.push(chars[num].into());
    }

    salt
}