1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! # 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 (
//!     &self, user_auth: &lrau::User,
//!     contact: &mut Contact,
//!     name: String
//! ) -> Result<(), &'static str> {
//!     // 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("no_auth"),
//!     }
//!     // Return
//!     Ok(())
//! }
//! ```
//!

pub mod permission;
pub mod user;

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

use rand::Rng;

/// 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
}