Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-11-26 05:50:29 +01:00
Removed try_trait and some formatting, particularly around imports
Dieser Commit ist enthalten in:
Ursprung
fb6f96f5c3
Commit
668d5c23dc
25 geänderte Dateien mit 251 neuen und 272 gelöschten Zeilen
|
@ -1,22 +1,26 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde_json::Value;
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde_json::Value;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use rocket::http::{Cookie, Cookies, SameSite};
|
use rocket::{
|
||||||
use rocket::request::{self, FlashMessage, Form, FromRequest, Request};
|
http::{Cookie, Cookies, SameSite},
|
||||||
use rocket::response::{content::Html, Flash, Redirect};
|
request::{self, FlashMessage, Form, FromRequest, Request},
|
||||||
use rocket::{Outcome, Route};
|
response::{content::Html, Flash, Redirect},
|
||||||
|
Outcome, Route,
|
||||||
|
};
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use crate::api::{ApiResult, EmptyResult, JsonResult};
|
use crate::{
|
||||||
use crate::auth::{decode_admin, encode_jwt, generate_admin_claims, ClientIp};
|
api::{ApiResult, EmptyResult, JsonResult},
|
||||||
use crate::config::ConfigBuilder;
|
auth::{decode_admin, encode_jwt, generate_admin_claims, ClientIp},
|
||||||
use crate::db::{backup_database, models::*, DbConn};
|
config::ConfigBuilder,
|
||||||
use crate::error::Error;
|
db::{backup_database, models::*, DbConn},
|
||||||
use crate::mail;
|
error::{Error, MapResult},
|
||||||
use crate::util::get_display_size;
|
mail,
|
||||||
use crate::CONFIG;
|
util::get_display_size,
|
||||||
|
CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
if !CONFIG.disable_admin_token() && !CONFIG.is_admin_token_set() {
|
if !CONFIG.disable_admin_token() && !CONFIG.is_admin_token_set() {
|
||||||
|
@ -270,21 +274,13 @@ fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult<Html<String>> {
|
||||||
|
|
||||||
#[post("/users/<uuid>/delete")]
|
#[post("/users/<uuid>/delete")]
|
||||||
fn delete_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
fn delete_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
||||||
let user = match User::find_by_uuid(&uuid, &conn) {
|
let user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?;
|
||||||
Some(user) => user,
|
|
||||||
None => err!("User doesn't exist"),
|
|
||||||
};
|
|
||||||
|
|
||||||
user.delete(&conn)
|
user.delete(&conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/users/<uuid>/deauth")]
|
#[post("/users/<uuid>/deauth")]
|
||||||
fn deauth_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
fn deauth_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
||||||
let mut user = match User::find_by_uuid(&uuid, &conn) {
|
let mut user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?;
|
||||||
Some(user) => user,
|
|
||||||
None => err!("User doesn't exist"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Device::delete_all_by_user(&user.uuid, &conn)?;
|
Device::delete_all_by_user(&user.uuid, &conn)?;
|
||||||
user.reset_security_stamp();
|
user.reset_security_stamp();
|
||||||
|
|
||||||
|
@ -293,11 +289,7 @@ fn deauth_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
||||||
|
|
||||||
#[post("/users/<uuid>/remove-2fa")]
|
#[post("/users/<uuid>/remove-2fa")]
|
||||||
fn remove_2fa(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
fn remove_2fa(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
|
||||||
let mut user = match User::find_by_uuid(&uuid, &conn) {
|
let mut user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?;
|
||||||
Some(user) => user,
|
|
||||||
None => err!("User doesn't exist"),
|
|
||||||
};
|
|
||||||
|
|
||||||
TwoFactor::delete_all_by_user(&user.uuid, &conn)?;
|
TwoFactor::delete_all_by_user(&user.uuid, &conn)?;
|
||||||
user.totp_recover = None;
|
user.totp_recover = None;
|
||||||
user.save(&conn)
|
user.save(&conn)
|
||||||
|
@ -340,7 +332,7 @@ struct GitCommit {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_github_api<T: DeserializeOwned>(url: &str) -> Result<T, Error> {
|
fn get_github_api<T: DeserializeOwned>(url: &str) -> Result<T, Error> {
|
||||||
use reqwest::{header::USER_AGENT, blocking::Client};
|
use reqwest::{blocking::Client, header::USER_AGENT};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
let github_api = Client::builder().build()?;
|
let github_api = Client::builder().build()?;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use crate::db::models::*;
|
use crate::{
|
||||||
use crate::db::DbConn;
|
api::{EmptyResult, JsonResult, JsonUpcase, Notify, NumberOrString, PasswordData, UpdateType},
|
||||||
|
auth::{decode_delete, decode_invite, decode_verify_email, Headers},
|
||||||
|
crypto,
|
||||||
|
db::{models::*, DbConn},
|
||||||
|
mail, CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase, Notify, NumberOrString, PasswordData, UpdateType};
|
pub fn routes() -> Vec<rocket::Route> {
|
||||||
use crate::auth::{decode_delete, decode_invite, decode_verify_email, Headers};
|
|
||||||
use crate::crypto;
|
|
||||||
use crate::mail;
|
|
||||||
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
use rocket::Route;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
|
||||||
routes![
|
routes![
|
||||||
register,
|
register,
|
||||||
profile,
|
profile,
|
||||||
|
|
|
@ -1,26 +1,20 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rocket::http::ContentType;
|
use rocket::{http::ContentType, request::Form, Data, Route};
|
||||||
use rocket::{request::Form, Data, Route};
|
|
||||||
|
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use multipart::server::save::SavedData;
|
|
||||||
use multipart::server::{Multipart, SaveResult};
|
|
||||||
|
|
||||||
use data_encoding::HEXLOWER;
|
use data_encoding::HEXLOWER;
|
||||||
|
use multipart::server::{save::SavedData, Multipart, SaveResult};
|
||||||
|
|
||||||
use crate::db::models::*;
|
use crate::{
|
||||||
use crate::db::DbConn;
|
api::{self, EmptyResult, JsonResult, JsonUpcase, Notify, PasswordData, UpdateType},
|
||||||
|
auth::Headers,
|
||||||
use crate::crypto;
|
crypto,
|
||||||
|
db::{models::*, DbConn},
|
||||||
use crate::api::{self, EmptyResult, JsonResult, JsonUpcase, Notify, PasswordData, UpdateType};
|
CONFIG,
|
||||||
use crate::auth::Headers;
|
};
|
||||||
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![
|
routes![
|
||||||
|
@ -617,9 +611,8 @@ fn share_cipher_by_uuid(
|
||||||
match data.Cipher.OrganizationId.clone() {
|
match data.Cipher.OrganizationId.clone() {
|
||||||
// If we don't get an organization ID, we don't do anything
|
// If we don't get an organization ID, we don't do anything
|
||||||
// No error because this is used when using the Clone functionality
|
// No error because this is used when using the Clone functionality
|
||||||
None => {},
|
None => {}
|
||||||
Some(organization_uuid) => {
|
Some(organization_uuid) => {
|
||||||
|
|
||||||
for uuid in &data.CollectionIds {
|
for uuid in &data.CollectionIds {
|
||||||
match Collection::find_by_uuid_and_org(uuid, &organization_uuid, &conn) {
|
match Collection::find_by_uuid_and_org(uuid, &organization_uuid, &conn) {
|
||||||
None => err!("Invalid collection ID provided"),
|
None => err!("Invalid collection ID provided"),
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::db::models::*;
|
use crate::{
|
||||||
use crate::db::DbConn;
|
api::{EmptyResult, JsonResult, JsonUpcase, Notify, UpdateType},
|
||||||
|
auth::Headers,
|
||||||
|
db::{models::*, DbConn},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase, Notify, UpdateType};
|
pub fn routes() -> Vec<rocket::Route> {
|
||||||
use crate::auth::Headers;
|
|
||||||
|
|
||||||
use rocket::Route;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
|
||||||
routes![
|
routes![
|
||||||
get_folders,
|
get_folders,
|
||||||
get_folder,
|
get_folder,
|
||||||
|
|
|
@ -29,14 +29,15 @@ pub fn routes() -> Vec<Route> {
|
||||||
// Move this somewhere else
|
// Move this somewhere else
|
||||||
//
|
//
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
|
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase};
|
use crate::{
|
||||||
use crate::auth::Headers;
|
api::{EmptyResult, JsonResult, JsonUpcase},
|
||||||
use crate::db::DbConn;
|
auth::Headers,
|
||||||
use crate::error::Error;
|
db::DbConn,
|
||||||
|
error::Error,
|
||||||
|
};
|
||||||
|
|
||||||
#[put("/devices/identifier/<uuid>/clear-token")]
|
#[put("/devices/identifier/<uuid>/clear-token")]
|
||||||
fn clear_device_token(uuid: String) -> EmptyResult {
|
fn clear_device_token(uuid: String) -> EmptyResult {
|
||||||
|
@ -146,7 +147,7 @@ fn hibp_breach(username: String) -> JsonResult {
|
||||||
username
|
username
|
||||||
);
|
);
|
||||||
|
|
||||||
use reqwest::{header::USER_AGENT, blocking::Client};
|
use reqwest::{blocking::Client, header::USER_AGENT};
|
||||||
|
|
||||||
if let Some(api_key) = crate::CONFIG.hibp_api_key() {
|
if let Some(api_key) = crate::CONFIG.hibp_api_key() {
|
||||||
let hibp_client = Client::builder().build()?;
|
let hibp_client = Client::builder().build()?;
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
use rocket::request::Form;
|
use num_traits::FromPrimitive;
|
||||||
use rocket::Route;
|
use rocket::{request::Form, Route};
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
|
|
||||||
use crate::api::{
|
use crate::{
|
||||||
EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, Notify, NumberOrString, PasswordData, UpdateType,
|
api::{EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, Notify, NumberOrString, PasswordData, UpdateType},
|
||||||
|
auth::{decode_invite, AdminHeaders, Headers, OwnerHeaders},
|
||||||
|
db::{models::*, DbConn},
|
||||||
|
mail, CONFIG,
|
||||||
};
|
};
|
||||||
use crate::auth::{decode_invite, AdminHeaders, Headers, OwnerHeaders};
|
|
||||||
use crate::db::models::*;
|
|
||||||
use crate::db::DbConn;
|
|
||||||
use crate::mail;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![
|
routes![
|
||||||
|
|
|
@ -2,13 +2,16 @@ use data_encoding::BASE32;
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use crate::api::core::two_factor::_generate_recover_code;
|
use crate::{
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData};
|
api::{
|
||||||
use crate::auth::{ClientIp, Headers};
|
core::two_factor::_generate_recover_code, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData,
|
||||||
use crate::crypto;
|
},
|
||||||
use crate::db::{
|
auth::{ClientIp, Headers},
|
||||||
|
crypto,
|
||||||
|
db::{
|
||||||
models::{TwoFactor, TwoFactorType},
|
models::{TwoFactor, TwoFactorType},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::config::CONFIG;
|
pub use crate::config::CONFIG;
|
||||||
|
|
|
@ -3,16 +3,17 @@ use data_encoding::BASE64;
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use crate::api::core::two_factor::_generate_recover_code;
|
use crate::{
|
||||||
use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, PasswordData};
|
api::{core::two_factor::_generate_recover_code, ApiResult, EmptyResult, JsonResult, JsonUpcase, PasswordData},
|
||||||
use crate::auth::Headers;
|
auth::Headers,
|
||||||
use crate::crypto;
|
crypto,
|
||||||
use crate::db::{
|
db::{
|
||||||
models::{TwoFactor, TwoFactorType, User},
|
models::{TwoFactor, TwoFactorType, User},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
|
error::MapResult,
|
||||||
|
CONFIG,
|
||||||
};
|
};
|
||||||
use crate::error::MapResult;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![get_duo, activate_duo, activate_duo_put,]
|
routes![get_duo, activate_duo, activate_duo_put,]
|
||||||
|
@ -186,7 +187,7 @@ fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbC
|
||||||
fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult {
|
fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult {
|
||||||
const AGENT: &str = "bitwarden_rs:Duo/1.0 (Rust)";
|
const AGENT: &str = "bitwarden_rs:Duo/1.0 (Rust)";
|
||||||
|
|
||||||
use reqwest::{header::*, Method, blocking::Client};
|
use reqwest::{blocking::Client, header::*, Method};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
// https://duo.com/docs/authapi#api-details
|
// https://duo.com/docs/authapi#api-details
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
|
use chrono::{Duration, NaiveDateTime, Utc};
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use crate::api::core::two_factor::_generate_recover_code;
|
use crate::{
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase, PasswordData};
|
api::{core::two_factor::_generate_recover_code, EmptyResult, JsonResult, JsonUpcase, PasswordData},
|
||||||
use crate::auth::Headers;
|
auth::Headers,
|
||||||
use crate::crypto;
|
crypto,
|
||||||
use crate::db::{
|
db::{
|
||||||
models::{TwoFactor, TwoFactorType},
|
models::{TwoFactor, TwoFactorType},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
|
error::{Error, MapResult},
|
||||||
|
mail, CONFIG,
|
||||||
};
|
};
|
||||||
use crate::error::Error;
|
|
||||||
use crate::mail;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
use chrono::{Duration, NaiveDateTime, Utc};
|
|
||||||
use std::ops::Add;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![get_email, send_email_login, send_email, email,]
|
routes![get_email, send_email_login, send_email, email,]
|
||||||
|
@ -58,7 +56,7 @@ fn send_email_login(data: JsonUpcase<SendEmailLoginData>, conn: DbConn) -> Empty
|
||||||
/// Generate the token, save the data for later verification and send email to user
|
/// Generate the token, save the data for later verification and send email to user
|
||||||
pub fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
pub fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
||||||
let type_ = TwoFactorType::Email as i32;
|
let type_ = TwoFactorType::Email as i32;
|
||||||
let mut twofactor = TwoFactor::find_by_user_and_type(user_uuid, type_, &conn)?;
|
let mut twofactor = TwoFactor::find_by_user_and_type(user_uuid, type_, &conn).map_res("Two factor not found")?;
|
||||||
|
|
||||||
let generated_token = crypto::generate_token(CONFIG.email_token_size())?;
|
let generated_token = crypto::generate_token(CONFIG.email_token_size())?;
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ pub fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult {
|
||||||
twofactor.data = twofactor_data.to_json();
|
twofactor.data = twofactor_data.to_json();
|
||||||
twofactor.save(&conn)?;
|
twofactor.save(&conn)?;
|
||||||
|
|
||||||
mail::send_token(&twofactor_data.email, &twofactor_data.last_token?)?;
|
mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -134,7 +132,7 @@ fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbConn) -
|
||||||
);
|
);
|
||||||
twofactor.save(&conn)?;
|
twofactor.save(&conn)?;
|
||||||
|
|
||||||
mail::send_token(&twofactor_data.email, &twofactor_data.last_token?)?;
|
mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -158,7 +156,7 @@ fn email(data: JsonUpcase<EmailData>, headers: Headers, conn: DbConn) -> JsonRes
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_ = TwoFactorType::EmailVerificationChallenge as i32;
|
let type_ = TwoFactorType::EmailVerificationChallenge as i32;
|
||||||
let mut twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn)?;
|
let mut twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn).map_res("Two factor not found")?;
|
||||||
|
|
||||||
let mut email_data = EmailTokenData::from_json(&twofactor.data)?;
|
let mut email_data = EmailTokenData::from_json(&twofactor.data)?;
|
||||||
|
|
||||||
|
@ -188,7 +186,7 @@ fn email(data: JsonUpcase<EmailData>, headers: Headers, conn: DbConn) -> JsonRes
|
||||||
/// Validate the email code when used as TwoFactor token mechanism
|
/// Validate the email code when used as TwoFactor token mechanism
|
||||||
pub fn validate_email_code_str(user_uuid: &str, token: &str, data: &str, conn: &DbConn) -> EmptyResult {
|
pub fn validate_email_code_str(user_uuid: &str, token: &str, data: &str, conn: &DbConn) -> EmptyResult {
|
||||||
let mut email_data = EmailTokenData::from_json(&data)?;
|
let mut email_data = EmailTokenData::from_json(&data)?;
|
||||||
let mut twofactor = TwoFactor::find_by_user_and_type(&user_uuid, TwoFactorType::Email as i32, &conn)?;
|
let mut twofactor = TwoFactor::find_by_user_and_type(&user_uuid, TwoFactorType::Email as i32, &conn).map_res("Two factor not found")?;
|
||||||
let issued_token = match &email_data.last_token {
|
let issued_token = match &email_data.last_token {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
_ => err!("No token available"),
|
_ => err!("No token available"),
|
||||||
|
@ -211,7 +209,7 @@ pub fn validate_email_code_str(user_uuid: &str, token: &str, data: &str, conn: &
|
||||||
|
|
||||||
let date = NaiveDateTime::from_timestamp(email_data.token_sent, 0);
|
let date = NaiveDateTime::from_timestamp(email_data.token_sent, 0);
|
||||||
let max_time = CONFIG.email_expiration_time() as i64;
|
let max_time = CONFIG.email_expiration_time() as i64;
|
||||||
if date.add(Duration::seconds(max_time)) < Utc::now().naive_utc() {
|
if date + Duration::seconds(max_time) < Utc::now().naive_utc() {
|
||||||
err!("Token has expired")
|
err!("Token has expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,14 @@ use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::api::{JsonResult, JsonUpcase, NumberOrString, PasswordData};
|
use crate::{
|
||||||
use crate::auth::Headers;
|
api::{JsonResult, JsonUpcase, NumberOrString, PasswordData},
|
||||||
use crate::crypto;
|
auth::Headers,
|
||||||
use crate::db::{
|
crypto,
|
||||||
|
db::{
|
||||||
models::{TwoFactor, User},
|
models::{TwoFactor, User},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod authenticator;
|
pub mod authenticator;
|
||||||
|
|
|
@ -2,19 +2,25 @@ use once_cell::sync::Lazy;
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use u2f::messages::{RegisterResponse, SignResponse, U2fSignRequest};
|
use u2f::{
|
||||||
use u2f::protocol::{Challenge, U2f};
|
messages::{RegisterResponse, SignResponse, U2fSignRequest},
|
||||||
use u2f::register::Registration;
|
protocol::{Challenge, U2f},
|
||||||
|
register::Registration,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::api::core::two_factor::_generate_recover_code;
|
use crate::{
|
||||||
use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData};
|
api::{
|
||||||
use crate::auth::Headers;
|
core::two_factor::_generate_recover_code, ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString,
|
||||||
use crate::db::{
|
PasswordData,
|
||||||
|
},
|
||||||
|
auth::Headers,
|
||||||
|
db::{
|
||||||
models::{TwoFactor, TwoFactorType},
|
models::{TwoFactor, TwoFactorType},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
|
error::Error,
|
||||||
|
CONFIG,
|
||||||
};
|
};
|
||||||
use crate::error::Error;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
const U2F_VERSION: &str = "U2F_V2";
|
const U2F_VERSION: &str = "U2F_V2";
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use yubico::config::Config;
|
use yubico::{config::Config, verify};
|
||||||
use yubico::verify;
|
|
||||||
|
|
||||||
use crate::api::core::two_factor::_generate_recover_code;
|
use crate::{
|
||||||
use crate::api::{EmptyResult, JsonResult, JsonUpcase, PasswordData};
|
api::{core::two_factor::_generate_recover_code, EmptyResult, JsonResult, JsonUpcase, PasswordData},
|
||||||
use crate::auth::Headers;
|
auth::Headers,
|
||||||
use crate::db::{
|
db::{
|
||||||
models::{TwoFactor, TwoFactorType},
|
models::{TwoFactor, TwoFactorType},
|
||||||
DbConn,
|
DbConn,
|
||||||
|
},
|
||||||
|
error::{Error, MapResult},
|
||||||
|
CONFIG,
|
||||||
};
|
};
|
||||||
use crate::error::{Error, MapResult};
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![generate_yubikey, activate_yubikey, activate_yubikey_put,]
|
routes![generate_yubikey, activate_yubikey, activate_yubikey_put,]
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
|
use std::{
|
||||||
|
fs::{create_dir_all, remove_file, symlink_metadata, File},
|
||||||
|
io::prelude::*,
|
||||||
|
net::ToSocketAddrs,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::fs::{create_dir_all, remove_file, symlink_metadata, File};
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
use std::time::{Duration, SystemTime};
|
|
||||||
|
|
||||||
use rocket::http::ContentType;
|
|
||||||
use rocket::response::Content;
|
|
||||||
use rocket::Route;
|
|
||||||
|
|
||||||
use reqwest::{Url, header::HeaderMap, blocking::Client, blocking::Response};
|
|
||||||
|
|
||||||
use rocket::http::Cookie;
|
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use reqwest::{blocking::Client, blocking::Response, header::HeaderMap, Url};
|
||||||
|
use rocket::{http::ContentType, http::Cookie, response::Content, Route};
|
||||||
use soup::prelude::*;
|
use soup::prelude::*;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::{error::Error, util::Cached, CONFIG};
|
||||||
use crate::CONFIG;
|
|
||||||
use crate::util::Cached;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![icon]
|
routes![icon]
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use rocket::request::{Form, FormItems, FromForm};
|
use rocket::{
|
||||||
use rocket::Route;
|
request::{Form, FormItems, FromForm},
|
||||||
|
Route,
|
||||||
|
};
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::api::core::two_factor::email::EmailTokenData;
|
use crate::{
|
||||||
use crate::api::core::two_factor::{duo, email, yubikey};
|
api::{
|
||||||
use crate::api::{ApiResult, EmptyResult, JsonResult};
|
core::two_factor::{duo, email, email::EmailTokenData, yubikey},
|
||||||
use crate::auth::ClientIp;
|
ApiResult, EmptyResult, JsonResult,
|
||||||
use crate::db::models::*;
|
},
|
||||||
use crate::db::DbConn;
|
auth::ClientIp,
|
||||||
use crate::mail;
|
db::{models::*, DbConn},
|
||||||
use crate::util;
|
error::MapResult,
|
||||||
use crate::CONFIG;
|
mail, util, CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![login]
|
routes![login]
|
||||||
|
@ -49,10 +52,7 @@ fn _refresh_login(data: ConnectData, conn: DbConn) -> JsonResult {
|
||||||
let token = data.refresh_token.unwrap();
|
let token = data.refresh_token.unwrap();
|
||||||
|
|
||||||
// Get device by refresh token
|
// Get device by refresh token
|
||||||
let mut device = match Device::find_by_refresh_token(&token, &conn) {
|
let mut device = Device::find_by_refresh_token(&token, &conn).map_res("Invalid refresh token")?;
|
||||||
Some(device) => device,
|
|
||||||
None => err!("Invalid refresh token"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// COMMON
|
// COMMON
|
||||||
let user = User::find_by_uuid(&device.user_uuid, &conn).unwrap();
|
let user = User::find_by_uuid(&device.user_uuid, &conn).unwrap();
|
||||||
|
@ -254,10 +254,7 @@ fn twofactor_auth(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _selected_data(tf: Option<TwoFactor>) -> ApiResult<String> {
|
fn _selected_data(tf: Option<TwoFactor>) -> ApiResult<String> {
|
||||||
match tf {
|
tf.map(|t| t.data).map_res("Two factor doesn't exist")
|
||||||
Some(tf) => Ok(tf.data),
|
|
||||||
None => err!("Two factor doesn't exist"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> ApiResult<Value> {
|
fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> ApiResult<Value> {
|
||||||
|
|
|
@ -5,23 +5,25 @@ mod identity;
|
||||||
mod notifications;
|
mod notifications;
|
||||||
mod web;
|
mod web;
|
||||||
|
|
||||||
pub use self::admin::routes as admin_routes;
|
|
||||||
pub use self::core::routes as core_routes;
|
|
||||||
pub use self::icons::routes as icons_routes;
|
|
||||||
pub use self::identity::routes as identity_routes;
|
|
||||||
pub use self::notifications::routes as notifications_routes;
|
|
||||||
pub use self::notifications::{start_notification_server, Notify, UpdateType};
|
|
||||||
pub use self::web::routes as web_routes;
|
|
||||||
|
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
pub use crate::api::{
|
||||||
|
admin::routes as admin_routes,
|
||||||
|
core::routes as core_routes,
|
||||||
|
icons::routes as icons_routes,
|
||||||
|
identity::routes as identity_routes,
|
||||||
|
notifications::routes as notifications_routes,
|
||||||
|
notifications::{start_notification_server, Notify, UpdateType},
|
||||||
|
web::routes as web_routes,
|
||||||
|
};
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
// Type aliases for API methods results
|
// Type aliases for API methods results
|
||||||
type ApiResult<T> = Result<T, crate::error::Error>;
|
type ApiResult<T> = Result<T, crate::error::Error>;
|
||||||
pub type JsonResult = ApiResult<Json<Value>>;
|
pub type JsonResult = ApiResult<Json<Value>>;
|
||||||
pub type EmptyResult = ApiResult<()>;
|
pub type EmptyResult = ApiResult<()>;
|
||||||
|
|
||||||
use crate::util;
|
|
||||||
type JsonUpcase<T> = Json<util::UpCase<T>>;
|
type JsonUpcase<T> = Json<util::UpCase<T>>;
|
||||||
type JsonUpcaseVec<T> = Json<Vec<util::UpCase<T>>>;
|
type JsonUpcaseVec<T> = Json<Vec<util::UpCase<T>>>;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@ use rocket::Route;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
use crate::api::{EmptyResult, JsonResult};
|
use crate::{
|
||||||
use crate::auth::Headers;
|
api::{EmptyResult, JsonResult},
|
||||||
use crate::db::DbConn;
|
auth::Headers,
|
||||||
|
db::DbConn,
|
||||||
use crate::{Error, CONFIG};
|
Error, CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![negotiate, websockets_err]
|
routes![negotiate, websockets_err]
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rocket::http::ContentType;
|
use rocket::{http::ContentType, response::content::Content, response::NamedFile, Route};
|
||||||
use rocket::response::content::Content;
|
|
||||||
use rocket::response::NamedFile;
|
|
||||||
use rocket::Route;
|
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::{error::Error, util::Cached, CONFIG};
|
||||||
use crate::util::Cached;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
// If addding more routes here, consider also adding them to
|
// If addding more routes here, consider also adding them to
|
||||||
|
|
28
src/auth.rs
28
src/auth.rs
|
@ -1,17 +1,19 @@
|
||||||
//
|
//
|
||||||
// JWT Handling
|
// JWT Handling
|
||||||
//
|
//
|
||||||
use crate::util::read_file;
|
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use jsonwebtoken::{self, Algorithm, Header, EncodingKey, DecodingKey};
|
use jsonwebtoken::{self, Algorithm, DecodingKey, EncodingKey, Header};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::ser::Serialize;
|
use serde::ser::Serialize;
|
||||||
|
|
||||||
use crate::error::{Error, MapResult};
|
use crate::{
|
||||||
use crate::CONFIG;
|
error::{Error, MapResult},
|
||||||
|
util::read_file,
|
||||||
|
CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
|
||||||
|
|
||||||
|
@ -213,11 +215,15 @@ pub fn generate_admin_claims() -> AdminJWTClaims {
|
||||||
//
|
//
|
||||||
// Bearer token authentication
|
// Bearer token authentication
|
||||||
//
|
//
|
||||||
use rocket::request::{self, FromRequest, Request};
|
use rocket::{
|
||||||
use rocket::Outcome;
|
request::{self, FromRequest, Request},
|
||||||
|
Outcome,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::db::models::{Device, User, UserOrgStatus, UserOrgType, UserOrganization};
|
use crate::db::{
|
||||||
use crate::db::DbConn;
|
models::{Device, User, UserOrgStatus, UserOrgType, UserOrganization},
|
||||||
|
DbConn,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Headers {
|
pub struct Headers {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
|
@ -366,7 +372,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
_ => err_handler!("Error getting the organization id"),
|
_ => err_handler!("Error getting the organization id"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,7 +415,7 @@ impl Into<Headers> for AdminHeaders {
|
||||||
Headers {
|
Headers {
|
||||||
host: self.host,
|
host: self.host,
|
||||||
device: self.device,
|
device: self.device,
|
||||||
user: self.user
|
user: self.user,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::{
|
||||||
use crate::util::{get_env, get_env_bool};
|
error::Error,
|
||||||
|
util::{get_env, get_env_bool},
|
||||||
|
};
|
||||||
|
|
||||||
static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
|
static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
|
||||||
let data_folder = get_env("DATA_FOLDER").unwrap_or_else(|| String::from("data"));
|
let data_folder = get_env("DATA_FOLDER").unwrap_or_else(|| String::from("data"));
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//
|
//
|
||||||
// PBKDF2 derivation
|
// PBKDF2 derivation
|
||||||
//
|
//
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
|
use ring::{digest, hmac, pbkdf2};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use ring::{digest, hmac, pbkdf2};
|
|
||||||
use std::num::NonZeroU32;
|
|
||||||
|
|
||||||
static DIGEST_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256;
|
static DIGEST_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256;
|
||||||
const OUTPUT_LEN: usize = digest::SHA256_OUTPUT_LEN;
|
const OUTPUT_LEN: usize = digest::SHA256_OUTPUT_LEN;
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use diesel::r2d2;
|
|
||||||
use diesel::r2d2::ConnectionManager;
|
|
||||||
use diesel::{Connection as DieselConnection, ConnectionError};
|
|
||||||
|
|
||||||
use rocket::http::Status;
|
|
||||||
use rocket::request::{self, FromRequest};
|
|
||||||
use rocket::{Outcome, Request, State};
|
|
||||||
|
|
||||||
use crate::error::Error;
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use crate::CONFIG;
|
use chrono::prelude::*;
|
||||||
|
use diesel::{r2d2, r2d2::ConnectionManager, Connection as DieselConnection, ConnectionError};
|
||||||
|
use rocket::{
|
||||||
|
http::Status,
|
||||||
|
request::{self, FromRequest},
|
||||||
|
Outcome, Request, State,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{error::Error, CONFIG};
|
||||||
|
|
||||||
/// An alias to the database connection used
|
/// An alias to the database connection used
|
||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
|
@ -86,7 +82,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the convenience of using an &DbConn as a &Database.
|
// For the convenience of using an &DbConn as a &Database.
|
||||||
impl Deref for DbConn {
|
impl std::ops::Deref for DbConn {
|
||||||
type Target = Connection;
|
type Target = Connection;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
|
|
|
@ -41,7 +41,6 @@ use reqwest::Error as ReqErr;
|
||||||
use serde_json::{Error as SerdeErr, Value};
|
use serde_json::{Error as SerdeErr, Value};
|
||||||
use std::io::Error as IOErr;
|
use std::io::Error as IOErr;
|
||||||
|
|
||||||
use std::option::NoneError as NoneErr;
|
|
||||||
use std::time::SystemTimeError as TimeErr;
|
use std::time::SystemTimeError as TimeErr;
|
||||||
use u2f::u2ferror::U2fError as U2fErr;
|
use u2f::u2ferror::U2fError as U2fErr;
|
||||||
use yubico::yubicoerror::YubicoError as YubiErr;
|
use yubico::yubicoerror::YubicoError as YubiErr;
|
||||||
|
@ -84,13 +83,6 @@ make_error! {
|
||||||
FromStrError(FromStrErr): _has_source, _api_error,
|
FromStrError(FromStrErr): _has_source, _api_error,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is implemented by hand because NoneError doesn't implement neither Display nor Error
|
|
||||||
impl From<NoneErr> for Error {
|
|
||||||
fn from(_: NoneErr) -> Self {
|
|
||||||
Error::from(("NoneError", String::new()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for Error {
|
impl std::fmt::Debug for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self.source() {
|
match self.source() {
|
||||||
|
|
32
src/mail.rs
32
src/mail.rs
|
@ -1,21 +1,23 @@
|
||||||
use std::env;
|
use std::{env, str::FromStr};
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use lettre::message::{header, Mailbox, Message, MultiPart, SinglePart};
|
|
||||||
use lettre::transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism};
|
|
||||||
use lettre::transport::smtp::extension::ClientId;
|
|
||||||
use lettre::{Address, SmtpTransport, Tls, TlsParameters, Transport};
|
|
||||||
|
|
||||||
use native_tls::{Protocol, TlsConnector};
|
|
||||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
|
||||||
|
|
||||||
use crate::api::EmptyResult;
|
|
||||||
use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims};
|
|
||||||
use crate::error::Error;
|
|
||||||
use crate::CONFIG;
|
|
||||||
|
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
|
use native_tls::{Protocol, TlsConnector};
|
||||||
|
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||||
|
|
||||||
|
use lettre::{
|
||||||
|
message::{header, Mailbox, Message, MultiPart, SinglePart},
|
||||||
|
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
|
||||||
|
transport::smtp::extension::ClientId,
|
||||||
|
Address, SmtpTransport, Tls, TlsParameters, Transport,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
api::EmptyResult,
|
||||||
|
auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims},
|
||||||
|
error::Error,
|
||||||
|
CONFIG,
|
||||||
|
};
|
||||||
|
|
||||||
fn mailer() -> SmtpTransport {
|
fn mailer() -> SmtpTransport {
|
||||||
let host = CONFIG.smtp_host().unwrap();
|
let host = CONFIG.smtp_host().unwrap();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![feature(proc_macro_hygiene, try_trait, ip)]
|
#![feature(proc_macro_hygiene, ip)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
extern crate openssl;
|
extern crate openssl;
|
||||||
|
|
26
src/util.rs
26
src/util.rs
|
@ -1,12 +1,15 @@
|
||||||
//
|
//
|
||||||
// Web Headers and caching
|
// Web Headers and caching
|
||||||
//
|
//
|
||||||
use rocket::fairing::{Fairing, Info, Kind};
|
|
||||||
use rocket::http::{ContentType, Header, HeaderMap, Method, Status};
|
|
||||||
use rocket::response::{self, Responder};
|
|
||||||
use rocket::{Data, Request, Response, Rocket};
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use rocket::{
|
||||||
|
fairing::{Fairing, Info, Kind},
|
||||||
|
http::{ContentType, Header, HeaderMap, Method, Status},
|
||||||
|
response::{self, Responder},
|
||||||
|
Data, Request, Response, Rocket,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::CONFIG;
|
use crate::CONFIG;
|
||||||
|
|
||||||
pub struct AppHeaders();
|
pub struct AppHeaders();
|
||||||
|
@ -189,9 +192,11 @@ impl Fairing for BetterLogging {
|
||||||
//
|
//
|
||||||
// File handling
|
// File handling
|
||||||
//
|
//
|
||||||
use std::fs::{self, File};
|
use std::{
|
||||||
use std::io::{Read, Result as IOResult};
|
fs::{self, File},
|
||||||
use std::path::Path;
|
io::{Read, Result as IOResult},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn file_exists(path: &str) -> bool {
|
pub fn file_exists(path: &str) -> bool {
|
||||||
Path::new(path).exists()
|
Path::new(path).exists()
|
||||||
|
@ -253,7 +258,6 @@ pub fn get_uuid() -> String {
|
||||||
// String util methods
|
// String util methods
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::ops::Try;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub fn upcase_first(s: &str) -> String {
|
pub fn upcase_first(s: &str) -> String {
|
||||||
|
@ -264,12 +268,12 @@ pub fn upcase_first(s: &str) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_parse_string<S, T, U>(string: impl Try<Ok = S, Error = U>) -> Option<T>
|
pub fn try_parse_string<S, T>(string: Option<S>) -> Option<T>
|
||||||
where
|
where
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
T: FromStr,
|
T: FromStr,
|
||||||
{
|
{
|
||||||
if let Ok(Ok(value)) = string.into_result().map(|s| s.as_ref().parse::<T>()) {
|
if let Some(Ok(value)) = string.map(|s| s.as_ref().parse::<T>()) {
|
||||||
Some(value)
|
Some(value)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -286,7 +290,7 @@ pub fn get_env<V>(key: &str) -> Option<V>
|
||||||
where
|
where
|
||||||
V: FromStr,
|
V: FromStr,
|
||||||
{
|
{
|
||||||
try_parse_string(env::var(key))
|
try_parse_string(env::var(key).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
const TRUE_VALUES: &[&str] = &["true", "t", "yes", "y", "1"];
|
const TRUE_VALUES: &[&str] = &["true", "t", "yes", "y", "1"];
|
||||||
|
|
Laden …
In neuem Issue referenzieren