#[cfg(feature = "private")] #[allow(unused)] pub use crate::oauth2_ee::*; /* * Author: Ruben Fiszel * Copyright: Windmill Labs, Inc 2022 * This file and its contents are licensed under the AGPLv3 License. * Please see the included NOTICE for copyright information and * LICENSE-AGPL for a copy of the license. */ #[cfg(not(feature = "private"))] use std::{collections::HashMap, fmt::Debug}; #[cfg(not(feature = "private"))] use axum::{routing::get, Json, Router}; #[cfg(not(feature = "private"))] use hmac::Mac; #[cfg(all(feature = "oauth2", not(feature = "private")))] use itertools::Itertools; #[cfg(all(feature = "oauth2", not(feature = "private")))] use oauth2::{Client as OClient, *}; #[cfg(not(feature = "private"))] use serde::{Deserialize, Serialize}; #[cfg(not(feature = "private"))] use sqlx::{Postgres, Transaction}; #[cfg(all(feature = "oauth2", not(feature = "private")))] use windmill_common::more_serde::maybe_number_opt; #[cfg(all(feature = "oauth2", not(feature = "private")))] use crate::OAUTH_CLIENTS; #[cfg(not(feature = "private"))] use windmill_common::error; #[cfg(not(feature = "private"))] use windmill_common::oauth2::*; #[cfg(not(feature = "private"))] use crate::db::DB; #[cfg(not(feature = "private"))] use std::str; #[cfg(not(feature = "private"))] pub fn global_service() -> Router { Router::new() .route("/list_logins", get(list_logins)) .route("/list_connects", get(list_connects)) } #[cfg(not(feature = "private"))] pub fn workspaced_service() -> Router { Router::new() } #[cfg(all(feature = "oauth2", not(feature = "private")))] #[derive(Debug, Clone)] pub struct ClientWithScopes { _client: OClient, _scopes: Vec, _extra_params: Option>, _extra_params_callback: Option>, _allowed_domains: Option>, _userinfo_url: Option, } #[cfg(all(feature = "oauth2", not(feature = "private")))] pub type BasicClientsMap = HashMap; #[cfg(not(feature = "private"))] #[derive(Clone, Debug, Serialize, Deserialize)] pub struct OAuthConfig { auth_url: String, token_url: String, userinfo_url: Option, scopes: Option>, extra_params: Option>, extra_params_callback: Option>, req_body_auth: Option, } #[cfg(not(feature = "private"))] #[derive(Clone, Debug, Serialize, Deserialize)] pub struct OAuthClient { id: String, secret: String, allowed_domains: Option>, connect_config: Option, login_config: Option, } #[cfg(all(feature = "oauth2", not(feature = "private")))] #[derive(Debug)] pub struct AllClients { pub logins: BasicClientsMap, pub connects: BasicClientsMap, pub slack: Option, } #[cfg(all(feature = "oauth2", not(feature = "private")))] pub async fn build_oauth_clients( _base_url: &str, _oauths_from_config: Option>, _db: &DB, ) -> anyhow::Result { // Implementation is not open source return Ok(AllClients { logins: HashMap::default(), connects: HashMap::default(), slack: None, }); } #[cfg(all(feature = "oauth2", not(feature = "private")))] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct TokenResponse { access_token: AccessToken, #[serde(deserialize_with = "maybe_number_opt")] #[serde(default)] expires_in: Option, refresh_token: Option, #[serde(deserialize_with = "helpers::deserialize_space_delimited_vec")] #[serde(serialize_with = "helpers::serialize_space_delimited_vec")] #[serde(default)] scope: Option>, } #[cfg(not(feature = "private"))] #[derive(Serialize)] struct Logins { oauth: Vec, saml: Option, } #[cfg(not(feature = "private"))] async fn list_logins() -> error::JsonResult { // Implementation is not open source return Ok(Json(Logins { oauth: vec![], saml: None })); } #[allow(unused)] #[cfg(all(feature = "oauth2", not(feature = "private")))] async fn list_connects() -> error::JsonResult> { Ok(Json( (&OAUTH_CLIENTS.read().await.connects) .keys() .map(|x| x.to_owned()) .collect_vec(), )) } #[allow(unused)] #[cfg(not(all(feature = "oauth2", not(feature = "private"))))] async fn list_connects() -> windmill_common::error::JsonResult> { // Implementation is not open source return Ok(axum::Json(vec![])); } #[cfg(not(feature = "private"))] pub async fn _refresh_token<'c>( _tx: Transaction<'c, Postgres>, _path: &str, _w_id: &str, _id: i32, _db: &DB, ) -> error::Result { // Implementation is not open source Err(error::Error::BadRequest( "Not implemented in Windmill's Open Source repository".to_string(), )) } #[cfg(not(feature = "private"))] pub async fn check_nb_of_user(db: &DB) -> error::Result<()> { let nb_users_sso = sqlx::query_scalar!("SELECT COUNT(*) FROM password WHERE login_type != 'password'",) .fetch_one(db) .await?; if nb_users_sso.unwrap_or(0) >= 10 { return Err(error::Error::BadRequest( "You have reached the maximum number of oauth users accounts (10) without an enterprise license" .to_string(), )); } let nb_users = sqlx::query_scalar!("SELECT COUNT(*) FROM password",) .fetch_one(db) .await?; if nb_users.unwrap_or(0) >= 50 { return Err(error::Error::BadRequest( "You have reached the maximum number of accounts (50) without an enterprise license" .to_string(), )); } return Ok(()); } #[derive(Clone, Debug)] #[cfg(not(feature = "private"))] pub struct SlackVerifier { _mac: HmacSha256, } #[cfg(not(feature = "private"))] impl SlackVerifier { pub fn new>(secret: S) -> anyhow::Result { HmacSha256::new_from_slice(secret.as_ref()) .map(|mac| SlackVerifier { _mac: mac }) .map_err(|_| anyhow::anyhow!("invalid secret")) } }