diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b144616e2..aa18682e30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,5 @@ jobs: DEFGUARD_DB_NAME: defguard DEFGUARD_DB_USER: defguard DEFGUARD_DB_PASSWORD: defguard - DEFGUARD_LICENSE: BwAAAAAAAAB0ZW9uaXRlCgAAAAAAAAAyMDUwLTEwLTEwAAAAAAFiayfBptq8pZXjPo4FV3VnmmwR/ipZHLriVPTW3AFyRq4c2wR+DzWC4BUACu3YMS27kX116JVKWB3/edYKNELFSiqYc6vsfoOrXnnQQJDI8RoyAQB6MpLv/EcgRZh47iI4L+tp44jKFQZ+EqqvMNt3G41u13P72HdkUv8yzQ7dmm3BrYQGJSCh/xiLna+mtQ9IQdqXOmYVInPXiWtIvi157Utfnow3gS0Ak45jci0DhtH+RWmFfiMOQCc4Qx0kEF9PsHl6Hn9Ay4oRTAnSYEPdWfQlVh5Rp276bLqnHDdyJ3/o2RSNK+QUXR7V2iuN1M3sWyW1rCGXtV5miHGI97CS SQLX_OFFLINE: true run: cargo test --locked --no-fail-fast --features mock-license-key diff --git a/Cargo.lock b/Cargo.lock index 7742a8eecf..34a4b98b47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,7 +105,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.15", + "time 0.3.16", ] [[package]] @@ -266,9 +266,9 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64ct" @@ -282,7 +282,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d02340c3f25c8422ba85d481123406dd7506505485bac1c694b26eb538da8daf" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "serde", "serde_json", ] @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.22" +version = "3.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7" dependencies = [ "atty", "bitflags", @@ -459,7 +459,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5656b98b1584764a52906e67caec20dfb9b0179ac2052d0d5937b083bc39a120" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "base64urlsafedata", "hex", "openssl", @@ -489,14 +489,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "aes-gcm", - "base64 0.13.0", + "base64 0.13.1", "hkdf", "hmac", "percent-encoding", "rand", "sha2", "subtle", - "time 0.3.15", + "time 0.3.16", "version_check", ] @@ -620,9 +620,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" dependencies = [ "cc", "cxxbridge-flags", @@ -632,9 +632,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" dependencies = [ "cc", "codespan-reporting", @@ -647,15 +647,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" [[package]] name = "cxxbridge-macro" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", @@ -673,7 +673,7 @@ name = "defguard" version = "0.3.0" dependencies = [ "argon2", - "base64 0.13.0", + "base64 0.13.1", "bincode", "chrono", "clap", @@ -973,13 +973,13 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -1380,7 +1380,7 @@ version = "8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa4b4af834c6cfd35d8763d359661b90f2e45d8f750a0849156c7f4671af09c" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "pem", "ring", "serde", @@ -1728,7 +1728,7 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d62c436394991641b970a92e23e8eeb4eb9bca74af4f5badc53bcd568daadbd" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "chrono", "getrandom 0.2.8", "http", @@ -1768,7 +1768,7 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e26afc60b2bf11b9a039db1f3a3c0d5fe201eebdbe646a8ecb8342c8240e3271" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "chrono", "http", "itertools", @@ -1820,9 +1820,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.76" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg 1.1.0", "cc", @@ -1869,7 +1869,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e580c9b15905cc585d44bc6010113a3225c4b664d40d0a175d5a0a4022235d89" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "chrono", "hmac", "once_cell", @@ -1897,17 +1897,6 @@ dependencies = [ "url", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -1915,21 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.4", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -1991,7 +1966,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -2335,7 +2310,7 @@ version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "bytes", "encoding_rs", "futures-core", @@ -2423,7 +2398,7 @@ dependencies = [ "memchr", "multer", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "rand", "ref-cast", @@ -2433,7 +2408,7 @@ dependencies = [ "serde_json", "state", "tempfile", - "time 0.3.15", + "time 0.3.16", "tokio", "tokio-stream", "tokio-util", @@ -2480,7 +2455,7 @@ dependencies = [ "smallvec", "stable-pattern", "state", - "time 0.3.15", + "time 0.3.16", "tokio", "uncased", ] @@ -2521,7 +2496,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "blake2b_simd", "constant_time_eq", "crossbeam-utils", @@ -2566,7 +2541,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", ] [[package]] @@ -2662,9 +2637,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.145" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] @@ -2691,9 +2666,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.145" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -2792,7 +2767,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.15", + "time 0.3.16", ] [[package]] @@ -2870,7 +2845,7 @@ checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" dependencies = [ "ahash", "atoi", - "base64 0.13.0", + "base64 0.13.1", "bitflags", "byteorder", "bytes", @@ -3043,9 +3018,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" @@ -3089,21 +3064,32 @@ dependencies = [ [[package]] name = "time" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" dependencies = [ "itoa", "libc", "num_threads", + "serde", + "time-core", "time-macros", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" +checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +dependencies = [ + "time-core", +] [[package]] name = "tiny-keccak" @@ -3233,7 +3219,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.13.0", + "base64 0.13.1", "bytes", "flate2", "futures-core", @@ -3671,7 +3657,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6528b4769d8fbe020e0e8c2e66bab6035982a2e9c3f8dac384120718f4763f4" dependencies = [ - "base64 0.13.0", + "base64 0.13.1", "base64urlsafedata", "compact_jwt", "der-parser", @@ -3934,7 +3920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" dependencies = [ "asn1-rs", - "base64 0.13.0", + "base64 0.13.1", "data-encoding", "der-parser", "lazy_static", @@ -3942,7 +3928,7 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.15", + "time 0.3.16", ] [[package]] diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index 6f2773ecf3..19d4b99103 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -9,7 +9,8 @@ pub mod webauthn; pub mod webhook; pub mod wireguard; -use super::DbPool; +use super::{DbPool, Group}; +#[cfg(feature = "openid")] use crate::enterprise::db::openid::AuthorizedApp; use device::Device; use sqlx::Error as SqlxError; @@ -30,7 +31,6 @@ pub struct SecurityKey { pub name: String, } -// FIXME: [`UserInfo`] does not belong here. #[derive(Deserialize, Serialize)] pub struct UserInfo { pub username: String, @@ -41,10 +41,10 @@ pub struct UserInfo { pub ssh_key: Option, pub pgp_key: Option, pub pgp_cert_id: Option, - #[serde(default)] pub groups: Vec, #[serde(default)] pub devices: Vec, + #[cfg(feature = "openid")] #[serde(default)] pub authorized_apps: Vec, #[serde(default)] @@ -58,9 +58,12 @@ impl UserInfo { pub async fn from_user(pool: &DbPool, user: User) -> Result { let groups = user.member_of(pool).await?; let devices = user.devices(pool).await?; - let authorized_apps = AuthorizedApp::all_for_user(pool, user.id.unwrap()).await?; let wallets = user.wallets(pool).await?; let security_keys = user.security_keys(pool).await?; + + #[cfg(feature = "openid")] + let authorized_apps = AuthorizedApp::all_for_user(pool, &user).await?; + Ok(Self { username: user.username, last_name: user.last_name, @@ -72,6 +75,7 @@ impl UserInfo { pgp_cert_id: user.pgp_cert_id, groups, devices, + #[cfg(feature = "openid")] authorized_apps, wallets, security_keys, @@ -79,15 +83,162 @@ impl UserInfo { }) } - pub fn into_user(self, user: &mut User) { - user.username = self.username; - user.last_name = self.last_name; - user.first_name = self.first_name; - user.email = self.email; + /// Copy groups to [`User`]. This function should be used by administrators. + async fn handle_user_groups( + &mut self, + pool: &DbPool, + user: &mut User, + ) -> Result<(), SqlxError> { + // handle groups + let mut present_groups = user.member_of(pool).await?; + + // add to groups if not already a member + for groupname in &self.groups { + match present_groups.iter().position(|name| name == groupname) { + Some(index) => { + present_groups.swap_remove(index); + } + None => { + if let Some(group) = Group::find_by_name(pool, groupname).await? { + user.add_to_group(pool, &group).await?; + } + } + } + } + + // remove from remaining groups + for groupname in present_groups { + if let Some(group) = Group::find_by_name(pool, &groupname).await? { + user.remove_from_group(pool, &group).await?; + } + } + + Ok(()) + } + + /// Copy authorized apps to [`User`]. This function is safe to call by a non-admin user. + #[cfg(feature = "openid")] + async fn handle_user_authorized_apps( + &mut self, + pool: &DbPool, + user: &mut User, + ) -> Result<(), SqlxError> { + let mut present_apps = AuthorizedApp::all_for_user(pool, user).await?; + + // create applications that don't already exist + for mut auth_app in &mut self.authorized_apps { + match present_apps + .iter() + .position(|app| app.client_id == auth_app.client_id) + { + Some(index) => { + present_apps.swap_remove(index); + } + None => { + if let Some(id) = user.id { + auth_app.id = None; + auth_app.user_id = id; + auth_app.save(pool).await?; + } + } + } + } + + // remove from remaining applications + for app in present_apps { + app.delete(pool).await?; + } + + Ok(()) + } + + /// Copy fields to [`User`]. This function is safe to call by a non-admin user. + pub async fn into_user_safe_fields( + mut self, + pool: &DbPool, + user: &mut User, + ) -> Result<(), SqlxError> { + #[cfg(feature = "openid")] + self.handle_user_authorized_apps(pool, user).await?; + + user.phone = self.phone; + user.ssh_key = self.ssh_key; + user.pgp_key = self.pgp_key; + user.pgp_cert_id = self.pgp_cert_id; + user.mfa_method = self.mfa_method; + + Ok(()) + } + + /// Copy fields to [`User`]. This function should be used by administrators. + pub async fn into_user_all_fields( + mut self, + pool: &DbPool, + user: &mut User, + ) -> Result<(), SqlxError> { + self.handle_user_groups(pool, user).await?; + #[cfg(feature = "openid")] + self.handle_user_authorized_apps(pool, user).await?; + user.phone = self.phone; user.ssh_key = self.ssh_key; user.pgp_key = self.pgp_key; user.pgp_cert_id = self.pgp_cert_id; user.mfa_method = self.mfa_method; + + user.username = self.username; + user.last_name = self.last_name; + user.first_name = self.first_name; + user.email = self.email; + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[sqlx::test] + async fn test_user_info(pool: DbPool) { + let mut user = User::new( + "hpotter".into(), + "pass123", + "Potter".into(), + "Harry".into(), + "h.potter@hogwart.edu.uk".into(), + None, + ); + user.save(&pool).await.unwrap(); + + let mut group1 = Group::new("Gryffindor"); + group1.save(&pool).await.unwrap(); + let mut group2 = Group::new("Hufflepuff"); + group2.save(&pool).await.unwrap(); + let mut group3 = Group::new("Ravenclaw"); + group3.save(&pool).await.unwrap(); + let mut group4 = Group::new("Slytherin"); + group4.save(&pool).await.unwrap(); + + user.add_to_group(&pool, &group1).await.unwrap(); + user.add_to_group(&pool, &group2).await.unwrap(); + + let mut user_info = UserInfo::from_user(&pool, user).await.unwrap(); + assert_eq!(user_info.groups, ["Gryffindor", "Hufflepuff"]); + + user_info.groups = vec!["Gryffindor".into(), "Ravenclaw".into()]; + let mut user = User::find_by_username(&pool, "hpotter") + .await + .unwrap() + .unwrap(); + user_info + .into_user_all_fields(&pool, &mut user) + .await + .unwrap(); + + assert_eq!(group1.member_usernames(&pool).await.unwrap(), ["hpotter"]); + assert_eq!(group3.member_usernames(&pool).await.unwrap(), ["hpotter"]); + assert!(group2.member_usernames(&pool).await.unwrap().is_empty()); + assert!(group4.member_usernames(&pool).await.unwrap().is_empty()); } } diff --git a/src/enterprise/db/openid.rs b/src/enterprise/db/openid.rs index 64649432b8..ebc3ab341a 100644 --- a/src/enterprise/db/openid.rs +++ b/src/enterprise/db/openid.rs @@ -1,4 +1,4 @@ -use crate::DbPool; +use crate::db::{DbPool, User}; use model_derive::Model; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use sqlx::{query_as, Error as SqlxError}; @@ -115,7 +115,7 @@ impl OpenIDClientAuth { } } -#[derive(Deserialize, Model, Serialize)] +#[derive(Deserialize, Model, PartialEq, Serialize)] #[table(authorizedapps)] pub struct AuthorizedApp { #[serde(default)] @@ -163,14 +163,18 @@ impl AuthorizedApp { .await } - pub async fn all_for_user(pool: &DbPool, user_id: i64) -> Result, SqlxError> { - query_as!( - Self, - "SELECT id \"id?\", user_id, client_id, home_url, date, name \ - FROM authorizedapps WHERE user_id = $1", - user_id - ) - .fetch_all(pool) - .await + pub async fn all_for_user(pool: &DbPool, user: &User) -> Result, SqlxError> { + if let Some(id) = user.id { + query_as!( + Self, + "SELECT id \"id?\", user_id, client_id, home_url, date, name \ + FROM authorizedapps WHERE user_id = $1", + id + ) + .fetch_all(pool) + .await + } else { + Ok(Vec::new()) + } } } diff --git a/src/enterprise/handlers/openid_clients.rs b/src/enterprise/handlers/openid_clients.rs index 4a6bb448a6..c5615d97d9 100644 --- a/src/enterprise/handlers/openid_clients.rs +++ b/src/enterprise/handlers/openid_clients.rs @@ -125,7 +125,7 @@ pub async fn get_user_apps( username: &str, ) -> ApiResult { debug!("Listing apps authorized by user: {}", username); - let apps = AuthorizedApp::all_for_user(&appstate.pool, session_info.user.id.unwrap()).await?; + let apps = AuthorizedApp::all_for_user(&appstate.pool, &session_info.user).await?; Ok(ApiResponse { json: json!(apps), status: Status::Ok, diff --git a/src/grpc/mod.rs b/src/grpc/mod.rs index 0a126823f3..eb154eca80 100644 --- a/src/grpc/mod.rs +++ b/src/grpc/mod.rs @@ -9,6 +9,7 @@ use crate::{ use auth::{auth_service_server::AuthServiceServer, AuthServer}; #[cfg(feature = "wireguard")] use gateway::{gateway_service_server::GatewayServiceServer, GatewayServer}; +#[cfg(any(feature = "wireguard", feature = "worker"))] use interceptor::jwt_auth_interceptor; use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, @@ -19,6 +20,7 @@ use tonic::transport::{Identity, Server, ServerTlsConfig}; mod auth; #[cfg(feature = "wireguard")] mod gateway; +#[cfg(any(feature = "wireguard", feature = "worker"))] mod interceptor; /// Runs gRPC server with core services. diff --git a/src/handlers/user.rs b/src/handlers/user.rs index e6fd5b62bd..b664b7687c 100644 --- a/src/handlers/user.rs +++ b/src/handlers/user.rs @@ -107,7 +107,6 @@ pub async fn username_available( }) } -// XXX: must ignore UserInfo.groups #[put("/user/", format = "json", data = "")] pub async fn modify_user( session: SessionInfo, @@ -117,8 +116,18 @@ pub async fn modify_user( ) -> ApiResult { debug!("Modifing user {}", username); let mut user = user_for_admin_or_self(&appstate.pool, &session, username).await?; - data.into_inner().into_user(&mut user); + let user_info = data.into_inner(); + if session.is_admin { + user_info + .into_user_all_fields(&appstate.pool, &mut user) + .await?; + } else { + user_info + .into_user_safe_fields(&appstate.pool, &mut user) + .await?; + } user.save(&appstate.pool).await?; + if appstate.license.validate(&Features::Ldap) { let _result = ldap_modify_user(&appstate.config, username, &user).await; }; diff --git a/src/lib.rs b/src/lib.rs index 640b159f65..36c5756177 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,9 @@ use crate::enterprise::handlers::{ }; #[cfg(feature = "oauth")] use crate::enterprise::oauth_state::OAuthState; -use crate::license::{Features, License}; +#[cfg(any(feature = "oauth", feature = "openid", feature = "worker"))] +use crate::license::Features; +use crate::license::License; use appstate::AppState; use config::DefGuardConfig; use db::{init_db, AppEvent, DbPool, Device, GatewayEvent, WireguardNetwork}; @@ -224,9 +226,8 @@ pub async fn run_web_server( pool: DbPool, ) -> Result, RocketError> { let webapp = build_webapp(config.clone(), webhook_tx, webhook_rx, wireguard_tx, pool).await; - let license_decoded = License::decode(&config.license); #[cfg(feature = "worker")] - let webapp = if license_decoded.validate(&Features::Worker) { + let webapp = if License::decode(&config.license).validate(&Features::Worker) { info!("Worker feature is enabled"); webapp.manage(worker_state).mount( "/api/v1/worker",