Merge remote-tracking branch 'upstream/main' into feed-edit-button
This commit is contained in:
		
						commit
						eac76e6806
					
				| @ -45,3 +45,12 @@ ROCKET_ADDRESS=127.0.0.1 | ||||
| #PLUME_LOGO_192=icons/trwnh/paragraphs/plumeParagraphs192.png | ||||
| #PLUME_LOGO_256=icons/trwnh/paragraphs/plumeParagraphs256.png | ||||
| #PLUME_LOGO_512=icons/trwnh/paragraphs/plumeParagraphs512.png | ||||
| 
 | ||||
| ## LDAP CONFIG ## | ||||
| # the object that will be bound is "${USER_NAME_ATTR}=${username},${BASE_DN}" | ||||
| #LDAP_ADDR=ldap://127.0.0.1:1389 | ||||
| #LDAP_BASE_DN="ou=users,dc=your-org,dc=eu" | ||||
| #LDAP_USER_NAME_ATTR=cn | ||||
| #LDAP_USER_MAIL_ATTR=mail | ||||
| #LDAP_TLS=false | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										83
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										83
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -169,6 +169,16 @@ name = "askama_escape" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "async-trait" | ||||
| version = "0.1.41" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "atom_syndication" | ||||
| version = "0.6.0" | ||||
| @ -1680,6 +1690,39 @@ name = "lazycell" | ||||
| version = "1.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lber" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ldap3" | ||||
| version = "0.7.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "async-trait 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lber 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio-native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lettre" | ||||
| version = "0.9.3" | ||||
| @ -2158,6 +2201,11 @@ dependencies = [ | ||||
|  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "nom" | ||||
| version = "2.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "nom" | ||||
| version = "4.2.3" | ||||
| @ -2604,6 +2652,7 @@ dependencies = [ | ||||
|  "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ldap3 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lindera-tantivy 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "migrations_internals 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "openssl 0.10.30 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| @ -3788,6 +3837,24 @@ dependencies = [ | ||||
|  "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thiserror" | ||||
| version = "1.0.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thiserror-impl" | ||||
| version = "1.0.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "thread_local" | ||||
| version = "1.0.1" | ||||
| @ -3924,6 +3991,15 @@ dependencies = [ | ||||
|  "syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-native-tls" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "tokio-reactor" | ||||
| version = "0.1.12" | ||||
| @ -4535,6 +4611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" | ||||
| "checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" | ||||
| "checksum askama_escape 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "719b48039ffac1564f67d70162109ba9341125cee0096a540e478355b3c724a7" | ||||
| "checksum async-trait 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b246867b8b3b6ae56035f1eb1ed557c1d8eae97f0d53696138a50fa0e3a3b8c0" | ||||
| "checksum atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9a7ab83635ff7a3b04856f4ad95324dccc9b947ab1e790fc5c769ee6d6f60c" | ||||
| "checksum atomicwrites 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6a2baf2feb820299c53c7ad1cc4f5914a220a1cb76d7ce321d2522a94b54651f" | ||||
| "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | ||||
| @ -4705,6 +4782,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" | ||||
| "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | ||||
| "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" | ||||
| "checksum lber 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a749954d43fcfb8d4381aa0c6cf291065053e0590d622f4f830393a9bd8278a5" | ||||
| "checksum ldap3 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a38aff2ff62165b59d3a1508f158ee166ff66e82a22ddf357e00fb51b24cf471" | ||||
| "checksum lettre 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bf43f3202a879fbdab4ecafec3349b0139f81d31c626246d53bcbb546253ffaa" | ||||
| "checksum lettre_email 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd02480f8dcf48798e62113974d6ccca2129a51d241fa20f1ea349c8a42559d5" | ||||
| "checksum levenshtein_automata 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73a004f877f468548d8d0ac4977456a249d8fabbdb8416c36db163dfc8f2e8ca" | ||||
| @ -4754,6 +4833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" | ||||
| "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" | ||||
| "checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" | ||||
| "checksum nom 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff" | ||||
| "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" | ||||
| "checksum nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" | ||||
| "checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" | ||||
| @ -4911,6 +4991,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" | ||||
| "checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" | ||||
| "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" | ||||
| "checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" | ||||
| "checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" | ||||
| "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" | ||||
| "checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" | ||||
| "checksum tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" | ||||
| @ -4923,6 +5005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" | ||||
| "checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" | ||||
| "checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" | ||||
| "checksum tokio-native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd608593a919a8e05a7d1fc6df885e40f6a88d3a70a3a7eff23ff27964eda069" | ||||
| "checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" | ||||
| "checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" | ||||
| "checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" | ||||
|  | ||||
| @ -132,7 +132,7 @@ fn new<'a>(args: &ArgMatches<'a>, conn: &Connection) { | ||||
|         role, | ||||
|         &bio, | ||||
|         email, | ||||
|         User::hash_pass(&password).expect("Couldn't hash password"), | ||||
|         Some(User::hash_pass(&password).expect("Couldn't hash password")), | ||||
|     ) | ||||
|     .expect("Couldn't save new user"); | ||||
| } | ||||
|  | ||||
| @ -13,6 +13,7 @@ guid-create = "0.1" | ||||
| heck = "0.3.0" | ||||
| itertools = "0.8.0" | ||||
| lazy_static = "1.0" | ||||
| ldap3 = "0.7.1" | ||||
| migrations_internals= "1.4.0" | ||||
| openssl = "0.10.22" | ||||
| rocket = "0.4.5" | ||||
|  | ||||
| @ -20,6 +20,7 @@ pub struct Config { | ||||
|     pub logo: LogoConfig, | ||||
|     pub default_theme: String, | ||||
|     pub media_directory: String, | ||||
|     pub ldap: Option<LdapConfig>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| @ -240,6 +241,42 @@ impl SearchTokenizerConfig { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct LdapConfig { | ||||
|     pub addr: String, | ||||
|     pub base_dn: String, | ||||
|     pub tls: bool, | ||||
|     pub user_name_attr: String, | ||||
|     pub mail_attr: String, | ||||
| } | ||||
| 
 | ||||
| fn get_ldap_config() -> Option<LdapConfig> { | ||||
|     let addr = var("LDAP_ADDR").ok(); | ||||
|     let base_dn = var("LDAP_BASE_DN").ok(); | ||||
|     match (addr, base_dn) { | ||||
|         (Some(addr), Some(base_dn)) => { | ||||
|             let tls = var("LDAP_TLS").unwrap_or_else(|_| "false".to_owned()); | ||||
|             let tls = match tls.as_ref() { | ||||
|                 "1" | "true" | "TRUE" => true, | ||||
|                 "0" | "false" | "FALSE" => false, | ||||
|                 _ => panic!("Invalid LDAP configuration : tls"), | ||||
|             }; | ||||
|             let user_name_attr = var("LDAP_USER_NAME_ATTR").unwrap_or_else(|_| "cn".to_owned()); | ||||
|             let mail_attr = var("LDAP_USER_MAIL_ATTR").unwrap_or_else(|_| "mail".to_owned()); | ||||
|             Some(LdapConfig { | ||||
|                 addr, | ||||
|                 base_dn, | ||||
|                 tls, | ||||
|                 user_name_attr, | ||||
|                 mail_attr, | ||||
|             }) | ||||
|         } | ||||
|         (None, None) => None, | ||||
|         (_, _) => { | ||||
|             panic!("Invalid LDAP configuration : both LDAP_ADDR and LDAP_BASE_DN must be set") | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| lazy_static! { | ||||
|     pub static ref CONFIG: Config = Config { | ||||
|         base_url: var("BASE_URL").unwrap_or_else(|_| format!( | ||||
| @ -267,5 +304,6 @@ lazy_static! { | ||||
|         default_theme: var("DEFAULT_THEME").unwrap_or_else(|_| "default-light".to_owned()), | ||||
|         media_directory: var("MEDIA_UPLOAD_DIRECTORY") | ||||
|             .unwrap_or_else(|_| "static/media".to_owned()), | ||||
|         ldap: get_ldap_config(), | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| use crate::{ | ||||
|     ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow, | ||||
|     instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post, | ||||
|     safe_string::SafeString, schema::users, search::Searcher, timeline::Timeline, Connection, | ||||
|     Error, PlumeRocket, Result, ITEMS_PER_PAGE, | ||||
|     ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, config::CONFIG, db_conn::DbConn, | ||||
|     follows::Follow, instance::*, medias::Media, notifications::Notification, | ||||
|     post_authors::PostAuthor, posts::Post, safe_string::SafeString, schema::users, | ||||
|     search::Searcher, timeline::Timeline, Connection, Error, PlumeRocket, Result, ITEMS_PER_PAGE, | ||||
| }; | ||||
| use activitypub::{ | ||||
|     activity::Delete, | ||||
| @ -14,6 +14,7 @@ use activitypub::{ | ||||
| use bcrypt; | ||||
| use chrono::{NaiveDateTime, Utc}; | ||||
| use diesel::{self, BelongingToDsl, ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl}; | ||||
| use ldap3::{LdapConn, Scope, SearchEntry}; | ||||
| use openssl::{ | ||||
|     hash::MessageDigest, | ||||
|     pkey::{PKey, Private}, | ||||
| @ -292,11 +293,116 @@ impl User { | ||||
|         bcrypt::hash(pass, 10).map_err(Error::from) | ||||
|     } | ||||
| 
 | ||||
|     pub fn auth(&self, pass: &str) -> bool { | ||||
|         self.hashed_password | ||||
|             .clone() | ||||
|             .map(|hashed| bcrypt::verify(pass, hashed.as_ref()).unwrap_or(false)) | ||||
|             .unwrap_or(false) | ||||
|     fn ldap_register(conn: &Connection, name: &str, password: &str) -> Result<User> { | ||||
|         if CONFIG.ldap.is_none() { | ||||
|             return Err(Error::NotFound); | ||||
|         } | ||||
|         let ldap = CONFIG.ldap.as_ref().unwrap(); | ||||
| 
 | ||||
|         let mut ldap_conn = LdapConn::new(&ldap.addr).map_err(|_| Error::NotFound)?; | ||||
|         let ldap_name = format!("{}={},{}", ldap.user_name_attr, name, ldap.base_dn); | ||||
|         let bind = ldap_conn | ||||
|             .simple_bind(&ldap_name, password) | ||||
|             .map_err(|_| Error::NotFound)?; | ||||
| 
 | ||||
|         if bind.success().is_err() { | ||||
|             return Err(Error::NotFound); | ||||
|         } | ||||
| 
 | ||||
|         let search = ldap_conn | ||||
|             .search( | ||||
|                 &ldap_name, | ||||
|                 Scope::Base, | ||||
|                 "(|(objectClass=person)(objectClass=user))", | ||||
|                 vec![&ldap.mail_attr], | ||||
|             ) | ||||
|             .map_err(|_| Error::NotFound)? | ||||
|             .success() | ||||
|             .map_err(|_| Error::NotFound)?; | ||||
|         for entry in search.0 { | ||||
|             let entry = SearchEntry::construct(entry); | ||||
|             let email = entry.attrs.get("mail").and_then(|vec| vec.first()); | ||||
|             if let Some(email) = email { | ||||
|                 let _ = ldap_conn.unbind(); | ||||
|                 return NewUser::new_local( | ||||
|                     conn, | ||||
|                     name.to_owned(), | ||||
|                     name.to_owned(), | ||||
|                     Role::Normal, | ||||
|                     "", | ||||
|                     email.to_owned(), | ||||
|                     None, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         let _ = ldap_conn.unbind(); | ||||
|         Err(Error::NotFound) | ||||
|     } | ||||
| 
 | ||||
|     fn ldap_login(&self, password: &str) -> bool { | ||||
|         if let Some(ldap) = CONFIG.ldap.as_ref() { | ||||
|             let mut conn = if let Ok(conn) = LdapConn::new(&ldap.addr) { | ||||
|                 conn | ||||
|             } else { | ||||
|                 return false; | ||||
|             }; | ||||
|             let name = format!( | ||||
|                 "{}={},{}", | ||||
|                 ldap.user_name_attr, &self.username, ldap.base_dn | ||||
|             ); | ||||
|             if let Ok(bind) = conn.simple_bind(&name, password) { | ||||
|                 bind.success().is_ok() | ||||
|             } else { | ||||
|                 false | ||||
|             } | ||||
|         } else { | ||||
|             false | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn login(conn: &Connection, ident: &str, password: &str) -> Result<User> { | ||||
|         let local_id = Instance::get_local()?.id; | ||||
|         let user = match User::find_by_email(conn, ident) { | ||||
|             Ok(user) => Ok(user), | ||||
|             _ => User::find_by_name(conn, ident, local_id), | ||||
|         } | ||||
|         .and_then(|u| { | ||||
|             if u.instance_id == local_id { | ||||
|                 Ok(u) | ||||
|             } else { | ||||
|                 Err(Error::NotFound) | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         match user { | ||||
|             Ok(user) if user.hashed_password.is_some() => { | ||||
|                 if bcrypt::verify(password, user.hashed_password.as_ref().unwrap()).unwrap_or(false) | ||||
|                 { | ||||
|                     Ok(user) | ||||
|                 } else { | ||||
|                     Err(Error::NotFound) | ||||
|                 } | ||||
|             } | ||||
|             Ok(user) => { | ||||
|                 if user.ldap_login(password) { | ||||
|                     Ok(user) | ||||
|                 } else { | ||||
|                     Err(Error::NotFound) | ||||
|                 } | ||||
|             } | ||||
|             e => { | ||||
|                 if let Ok(user) = User::ldap_register(conn, ident, password) { | ||||
|                     return Ok(user); | ||||
|                 } | ||||
|                 // if no user was found, and we were unable to auto-register from ldap
 | ||||
|                 // fake-verify a password, and return an error.
 | ||||
|                 let other = User::get(&*conn, 1) | ||||
|                     .expect("No user is registered") | ||||
|                     .hashed_password; | ||||
|                 other.map(|pass| bcrypt::verify(password, &pass)); | ||||
|                 e | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn reset_password(&self, conn: &Connection, pass: &str) -> Result<()> { | ||||
| @ -983,7 +1089,7 @@ impl NewUser { | ||||
|         role: Role, | ||||
|         summary: &str, | ||||
|         email: String, | ||||
|         password: String, | ||||
|         password: Option<String>, | ||||
|     ) -> Result<User> { | ||||
|         let (pub_key, priv_key) = gen_keypair(); | ||||
|         let instance = Instance::get_local()?; | ||||
| @ -1001,7 +1107,7 @@ impl NewUser { | ||||
|                 summary: summary.to_owned(), | ||||
|                 summary_html: SafeString::new(&utils::md_to_html(&summary, None, false, None).0), | ||||
|                 email: Some(email), | ||||
|                 hashed_password: Some(password), | ||||
|                 hashed_password: password, | ||||
|                 instance_id: instance.id, | ||||
|                 public_key: String::from_utf8(pub_key).or(Err(Error::Signature))?, | ||||
|                 private_key: Some(String::from_utf8(priv_key).or(Err(Error::Signature))?), | ||||
| @ -1043,7 +1149,7 @@ pub(crate) mod tests { | ||||
|             Role::Admin, | ||||
|             "Hello there, I'm the admin", | ||||
|             "admin@example.com".to_owned(), | ||||
|             "invalid_admin_password".to_owned(), | ||||
|             Some("invalid_admin_password".to_owned()), | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         let user = NewUser::new_local( | ||||
| @ -1053,7 +1159,7 @@ pub(crate) mod tests { | ||||
|             Role::Normal, | ||||
|             "Hello there, I'm no one", | ||||
|             "user@example.com".to_owned(), | ||||
|             "invalid_user_password".to_owned(), | ||||
|             Some("invalid_user_password".to_owned()), | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         let other = NewUser::new_local( | ||||
| @ -1063,7 +1169,7 @@ pub(crate) mod tests { | ||||
|             Role::Normal, | ||||
|             "Hello there, I'm someone else", | ||||
|             "other@example.com".to_owned(), | ||||
|             "invalid_other_password".to_owned(), | ||||
|             Some("invalid_other_password".to_owned()), | ||||
|         ) | ||||
|         .unwrap(); | ||||
|         vec![admin, user, other] | ||||
| @ -1082,7 +1188,7 @@ pub(crate) mod tests { | ||||
|                 Role::Normal, | ||||
|                 "Hello I'm a test", | ||||
|                 "test@example.com".to_owned(), | ||||
|                 User::hash_pass("test_password").unwrap(), | ||||
|                 Some(User::hash_pass("test_password").unwrap()), | ||||
|             ) | ||||
|             .unwrap(); | ||||
|             assert_eq!( | ||||
| @ -1165,12 +1271,15 @@ pub(crate) mod tests { | ||||
|                 Role::Normal, | ||||
|                 "Hello I'm a test", | ||||
|                 "test@example.com".to_owned(), | ||||
|                 User::hash_pass("test_password").unwrap(), | ||||
|                 Some(User::hash_pass("test_password").unwrap()), | ||||
|             ) | ||||
|             .unwrap(); | ||||
| 
 | ||||
|             assert!(test_user.auth("test_password")); | ||||
|             assert!(!test_user.auth("other_password")); | ||||
|             assert_eq!( | ||||
|                 User::login(conn, "test", "test_password").unwrap().id, | ||||
|                 test_user.id | ||||
|             ); | ||||
|             assert!(User::login(conn, "test", "other_password").is_err()); | ||||
|             Ok(()) | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -62,30 +62,20 @@ pub fn oauth( | ||||
|     let conn = &*rockets.conn; | ||||
|     let app = App::find_by_client_id(conn, &query.client_id)?; | ||||
|     if app.client_secret == query.client_secret { | ||||
|         if let Ok(user) = User::find_by_fqn(&rockets, &query.username) { | ||||
|             if user.auth(&query.password) { | ||||
|                 let token = ApiToken::insert( | ||||
|                     conn, | ||||
|                     NewApiToken { | ||||
|                         app_id: app.id, | ||||
|                         user_id: user.id, | ||||
|                         value: random_hex(), | ||||
|                         scopes: query.scopes.clone(), | ||||
|                     }, | ||||
|                 )?; | ||||
|                 Ok(Json(json!({ | ||||
|                     "token": token.value | ||||
|                 }))) | ||||
|             } else { | ||||
|                 Ok(Json(json!({ | ||||
|                     "error": "Invalid credentials" | ||||
|                 }))) | ||||
|             } | ||||
|         if let Ok(user) = User::login(conn, &query.username, &query.password) { | ||||
|             let token = ApiToken::insert( | ||||
|                 conn, | ||||
|                 NewApiToken { | ||||
|                     app_id: app.id, | ||||
|                     user_id: user.id, | ||||
|                     value: random_hex(), | ||||
|                     scopes: query.scopes.clone(), | ||||
|                 }, | ||||
|             )?; | ||||
|             Ok(Json(json!({ | ||||
|                 "token": token.value | ||||
|             }))) | ||||
|         } else { | ||||
|             // Making fake password verification to avoid different
 | ||||
|             // response times that would make it possible to know
 | ||||
|             // if a username is registered or not.
 | ||||
|             User::get(conn, 1)?.auth(&query.password); | ||||
|             Ok(Json(json!({ | ||||
|                 "error": "Invalid credentials" | ||||
|             }))) | ||||
|  | ||||
| @ -48,38 +48,19 @@ pub fn create( | ||||
|     rockets: PlumeRocket, | ||||
| ) -> RespondOrRedirect { | ||||
|     let conn = &*rockets.conn; | ||||
|     let user = User::find_by_email(&*conn, &form.email_or_name) | ||||
|         .or_else(|_| User::find_by_fqn(&rockets, &form.email_or_name)); | ||||
|     let mut errors = match form.validate() { | ||||
|         Ok(_) => ValidationErrors::new(), | ||||
|         Err(e) => e, | ||||
|     }; | ||||
| 
 | ||||
|     let user = User::login(conn, &form.email_or_name, &form.password); | ||||
|     let user_id = if let Ok(user) = user { | ||||
|         if !user.auth(&form.password) { | ||||
|             let mut err = ValidationError::new("invalid_login"); | ||||
|             err.message = Some(Cow::from("Invalid username, or password")); | ||||
|             errors.add("email_or_name", err); | ||||
|             String::new() | ||||
|         } else { | ||||
|             user.id.to_string() | ||||
|         } | ||||
|         user.id.to_string() | ||||
|     } else { | ||||
|         // Fake password verification, only to avoid different login times
 | ||||
|         // that could be used to see if an email adress is registered or not
 | ||||
|         User::get(&*conn, 1) | ||||
|             .map(|u| u.auth(&form.password)) | ||||
|             .expect("No user is registered"); | ||||
| 
 | ||||
|         let mut err = ValidationError::new("invalid_login"); | ||||
|         err.message = Some(Cow::from("Invalid username, or password")); | ||||
|         errors.add("email_or_name", err); | ||||
|         String::new() | ||||
|     }; | ||||
| 
 | ||||
|     if !errors.is_empty() { | ||||
|         return render!(session::login(&rockets.to_context(), None, &*form, errors)).into(); | ||||
|     } | ||||
|     }; | ||||
| 
 | ||||
|     cookies.add_private( | ||||
|         Cookie::build(AUTH_COOKIE, user_id) | ||||
|  | ||||
| @ -541,7 +541,7 @@ pub fn create( | ||||
|                 Role::Normal, | ||||
|                 "", | ||||
|                 form.email.to_string(), | ||||
|                 User::hash_pass(&form.password).map_err(to_validation)?, | ||||
|                 Some(User::hash_pass(&form.password).map_err(to_validation)?), | ||||
|             ).map_err(to_validation)?; | ||||
|             Ok(Flash::success( | ||||
|                 Redirect::to(uri!(super::session::new: m = _)), | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user