rocket_auth/
lib.rs

1//! rocket_auth provides a ready-to-use  backend agnostic API for authentication management.
2//! It supports connections for SQLite and Postgresql. It lets you create, delete, and authenticate users.
3//! The available features are:
4//! * `sqlx-sqlite`: for interacting with a SQLite database using `sqlx`.
5//! * `sqlx-postgres`: for interacting with a Postgresql database with `sqlx`.
6//! * `sqlx-mysql`: for interacting with a MySql database with `sqlx`.
7//! * `redis`: for storing sessions on a redis server using `redis`.
8//! * `rusqlite`: for interacting with a SQLite database using `rusqlite`.
9//! * `tokio-postgres`: for interacting with a Postgresql database with `tokio-postgres`.
10//!
11//!
12//! `rocket_auth` uses private cookies to store session data.
13//! This means that in order for cookies to be properly decrypted between launches, a `secret_key` must be set.
14//! For more information visit rocket's [configuration guide](https://rocket.rs/v0.5-rc/guide/configuration/#configuration).
15//!
16//!
17//!
18//! To use `rocket_auth` include it as a dependency in your Cargo.toml file:
19//! ```
20//! [dependencies.rocket_auth]
21//! version = "0.4.0"
22//! features = ["sqlx-sqlite"]
23//! ```
24//! # Quick overview
25//! This crate provides three guards:
26//! * [`Auth`]: Manages authentication.
27//! * [`Session`]: Used to retrieve session data from client cookies.
28//! * [`User`]: Restricts content, so it can be viewed by authenticated clients only.
29//!
30//!
31//! It also includes two structs to be parsed from forms and json data:
32//! * [`Signup`]: Used to create new users.
33//! * [`Login`]: Used to authenticate users.
34//!
35//!
36//! Finally it has two structures for queries:
37//! * [`Users`]: It allows to query users to the database.
38//! * [`User`]: It is the response of a query.
39//!
40//!
41//! ## Auth guard
42//! The [`Auth`] guard allows to log in, log out, sign up, modify, and delete the currently (un)authenticated user.
43//! For more information see [`Auth`]. Because of Rust's ownership rules, you may not retrieve both [`rocket::http::CookieJar`] and the [`Auth`] guard
44//! simultaneously. However, retrieving cookies is not needed since `Auth` stores them in the public field [`Auth::cookies`].
45//!  A working example:
46//! ```rust,no_run
47//! use rocket::{get, post, form::Form, routes};
48//! use rocket_auth::{Users, Error, Auth, Signup, Login};
49//!
50//! #[post("/signup", data="<form>")]
51//! async fn signup(form: Form<Signup>, auth: Auth<'_>) -> Result<&'static str, Error> {
52//!     auth.signup(&form).await?;
53//!     auth.login(&form.into());
54//!     Ok("You signed up.")
55//! }
56//!
57//! #[post("/login", data="<form>")]
58//! async fn login(form: rocket::serde::json::Json<Login>, auth: Auth<'_>) -> Result<&'static str, Error> {
59//!     auth.login(&form).await?;
60//!     Ok("You're logged in.")
61//! }
62//!
63//! #[get("/logout")]
64//! fn logout(auth: Auth<'_>) {
65//!     auth.logout();
66//! }
67//! #[tokio::main]
68//! async fn main() -> Result<(), Error>{
69//!     let users = Users::open_sqlite("mydb.db").await?;
70//!
71//!     rocket::build()
72//!         .mount("/", routes![signup, login, logout])
73//!         .manage(users)
74//!         .launch();
75//!     Ok(())
76//! }
77//! ```
78//!
79//! ## Users struct
80//! The [`Users`] struct administers interactions with the database.
81//! It lets you query, create, modify and delete users.
82//! Unlike the [`Auth`] guard, a [`Users`] instance can manage any user in the database.
83//! Note that the [`Auth`] guards includes a `Users` instance stored on the public `users` field.
84//! So it is not necessary to retrieve Users when using `Auth`.
85//! A simple example of how to query a user with the [`Users`] struct:
86//!
87//! ```rust
88//! # use rocket::{get, State};
89//! # use serde_json::json;
90//! use rocket_auth::Users;
91//!
92//! #[get("/see-user/<id>")]
93//! async fn see_user(id: i32, users: &State<Users>) -> String {
94//!     let user = users.get_by_id(id).await.unwrap();
95//!     format!("{}", json!(user))
96//! }
97//! # fn main() {}
98//! ```
99//!
100//! A [`Users`] instance can be constructed by connecting it to the database with the methods [`open_sqlite`](Users::open_sqlite),
101//! [`open_postgres`](Users::open_postgres) or [`open_rusqlite`](Users::open_rusqlite). Furthermore, it can be constructed from a working connection.
102//!
103//!
104//! ## User guard
105//! The [`User`] guard can be used to restrict content so it can only be viewed by authenticated users.
106//! Additionally, you can use it to render special content if the client is authenticated or not.
107//! ```rust
108//! # use rocket::*;
109//! # use rocket_auth::User;
110//! #[get("/private-content")]
111//! fn private_content(user: User) -> &'static str {
112//!     "If you can see this, you are logged in."
113//! }
114//!
115//! #[get("/special-content")]
116//! fn special_content(option: Option<User>) -> String {
117//!     if let Some(user) = option {
118//!         format!("hello, {}.", user.email())
119//!     } else {
120//!         "hello, anonymous user".into()
121//!     }
122//! }
123//! ```
124//!
125//! ## AdminUser guard
126//! The [`AdminUser`] guard can be used analogously to [`User`].
127//! It will restrict content so it can be viewed by admins only.
128//! ```
129//! # use rocket::*;
130//! # use rocket_auth::AdminUser;
131//! #[get("/admin-panel")]
132//! fn admin_panel(user: AdminUser) -> String {
133//!    format!("Hello {}.", user.email())
134//! }
135//! ```
136
137
138mod cookies;
139mod db;
140mod error;
141mod forms;
142pub mod prelude;
143mod session;
144mod user;
145
146#[cfg(test)]
147mod tests;
148
149use std::fmt::Debug;
150
151pub use prelude::*;
152
153// pub use language::Language;
154pub use crate::user::auth::Auth;
155pub use cookies::Session;
156pub use error::Error;
157
158/// The `User` guard can be used to restrict content so it can only be viewed by authenticated users.
159/// ```rust
160/// #
161/// # use rocket::{get};
162/// # use rocket_auth::User;
163/// #[get("/private-content")]
164/// fn private_content(user: User) -> &'static str {
165///     "If you can see this, you are logged in."
166/// }
167/// # fn main() {}
168/// ```
169#[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))]
170#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
171pub struct User {
172    id: i32,
173    email: String,
174    pub is_admin: bool,
175    #[serde(skip_serializing)]
176    password: String,
177}
178
179/// The [`AdminUser`] guard can be used analogously to [`User`].
180/// It will restrict content so it can be viewed by admins only.
181/// ```
182/// # use rocket::*;
183/// # use rocket_auth::AdminUser;
184/// #[get("/admin-panel")]
185/// fn admin_panel(user: AdminUser) -> String {
186///    format!("Hello {}.", user.email())
187/// }
188/// ```
189#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
190pub struct AdminUser(User);
191
192impl Debug for AdminUser {
193    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194        write!(f, "Admin{:?}", self.0)
195    }
196}
197
198/// The `Users` struct is used to query users from the database, as well as to create, modify and delete them.
199pub struct Users {
200    conn: Box<dyn DBConnection>,
201    sess: Box<dyn SessionManager>,
202}