lrau 0.2.0

LrAU is an authentication and permission management system for rust.
Documentation
//! # LrAU
//!
//! LrAU is an authentication and permission management system
//! for rust. LrAU uses Argon2id to hash its passwords, so they
//! are protected from Rainbow Table / brute force attacks.
//!
//! ## Toml permissions
//!
//! ### Example
//!
//! ```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
//! ```
//!
//! ### Breakdown
//!
//! As you can see one specifies paths and then wether a user
//! has authentication. By default a user **does not** have
//! authentication, and so instead it must be explicitly
//! specified wether they are. Then in sub paths one can
//! change this authentication, as shown in the example of
//! only giving a user access to a contacts name
//! *(see line 1-6)*. There is also mutability, where you can
//! specify if a user has mutable access to something, or
//! wether not they are read only. This, like everything else,
//! is assumed off by default. It is only available if you
//! already give the user authentication.
//!
//! ### Simple Instructions
//!
//! First specify an individual element in a `permissions`
//! array. In this you need to specify a path `path` , and
//! wether the user has permission `auth`. Then you can
//! specify mutability `mut`.
//!
//! ```toml
//! # Create an array element
//! [[permissions]]
//! # Specify the path
//! path = "/contacts"
//! # Specify the authentication
//! auth = true
//! # Specify if they can mutate the contacts
//! mut = true
//! ```
//!
//! This creates a permission in the `/contacts` path,
//!  where the user can both read and mutate it.
//!
//! ## In Rust
//!
//! ### Users
//!
//! #### First time
//!
//! The main struct you need to worry about is the `User`
//! struct, which represents a logged in user. On initial
//! instantiation you must provide:
//!  * An id/username.
//!  * A password (in plain text when you give it, transferred into a hash using
//!    the Argon2 algorithm.)
//!  * A `Permissions` struct, see the permission management section above/
//!
//! From there the algorithm will generate a salt and hash it using Argon2id.
//!
//! #### Restoration
//!
//! After this it is possible to use `new_basic` to create a
//! User from an existing Argon2id hash. This can be used if
//! you are reading from SQL or suchlike.
//!
//! ### Logging in
//!
//! With a user you can call the `.log_in(&str: password)`
//! method to attempt authentication. The password given is
//! **not** hashed and is then hashed by the internals.
//!
//! ### Matching Permissions
//!
//! In rust you can call the function
//! `User.get_valid_permissions()` given the parameters
//! `path` and `mut`. The parameter `path` is the path
//! to the permission. Note that if not specified it will use
//! the permission of any parents (or however far up the tree
//! it has to go.) `mut` is wether you need mutable
//! permissions or not.
//!
//! ```rust
//!
//! /// This function lets a user over the network modify a contacts name,
//! /// ensuring that they have permission
//! pub fn modify_contact (
//!     user_auth: &lrau::User,
//!     contact: &mut Contact,
//!     name: String
//! ) -> Result<(), Box<dyn std::error::Error>> {
//!     // Checks the user has permissions
//!     // This ensures they have mut permissions
//!     match user_auth.get_valid_permissions("/contacts/name", true)? {
//!         // If they have permissions change the name
//!         true => contact.name = name,
//!         
//!         // If not return an error
//!         false => return Err(Box::new("no_auth".to_string())),
//!     }
//!     // Return
//!     Ok(())
//! }
//! ```

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")]
pub mod schema;

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

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

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

        salt.push_str(chars.get(num..=num).unwrap());
    }

    salt
}