Skip to content

Commit a88fbb2

Browse files
authored
feat: msft teams support for critical alerts (#5113)
* feat: msft teams support for critical alerts * ee changes * ee * sqlx prep * multiple teams channels * commit file, not symlink * improve reactivity * docs link * Update ee-repo-ref.txt
1 parent e530855 commit a88fbb2

29 files changed

+387
-42
lines changed

backend/.sqlx/query-08dd2ea6b17a52bce352d6443d7d009cfc9da0d3b2bd1f40d422b550779e5324.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/.sqlx/query-44a12919fb154055f1142cc078ef131f8a0c9cdb37cfba6283a6718480b02a4b.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/.sqlx/query-84d048ea323758842dc564c700b524d1a5b196a7b77afcb02f46b84b22088bbf.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/.sqlx/query-9c72b2962d0919353cfe5af710e857d432dff44e343b8f0610208d42ff5afd14.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/ee-repo-ref.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ddcfdfc18a9833a5fc4e62ad62a265ef1e06a0aa
1+
0c89b8974ff6e1c9eda2134f09d4a03f18b57c15
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DELETE FROM global_settings WHERE name = 'teams';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
INSERT INTO global_settings (name, value) VALUES ('teams', '{}');

backend/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use windmill_common::{
4040
NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING, PIP_INDEX_URL_SETTING,
4141
REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING,
4242
RETENTION_PERIOD_SECS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING,
43-
TIMEOUT_WAIT_RESULT_SETTING,
43+
TIMEOUT_WAIT_RESULT_SETTING, TEAMS_SETTING
4444
},
4545
scripts::ScriptLang,
4646
stats_ee::schedule_stats,
@@ -734,6 +734,9 @@ Windmill Community Edition {GIT_VERSION}
734734
SMTP_SETTING => {
735735
reload_smtp_config(&db).await;
736736
},
737+
TEAMS_SETTING => {
738+
tracing::info!("Teams setting changed.");
739+
},
737740
INDEXER_SETTING => {
738741
reload_indexer_config(&db).await;
739742
},

backend/src/monitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,7 @@ pub async fn reload_base_url_setting(db: &DB) -> error::Result<()> {
14791479
#[cfg(feature = "oauth2")]
14801480
{
14811481
let mut l = windmill_api::OAUTH_CLIENTS.write().await;
1482-
*l = windmill_api::oauth2_ee::build_oauth_clients(&base_url, oauths)
1482+
*l = windmill_api::oauth2_ee::build_oauth_clients(&base_url, oauths, db).await
14831483
.map_err(|e| tracing::error!("Error building oauth clients (is the oauth.json mounted and in correct format? Use '{}' as minimal oauth.json): {}", "{}", e))
14841484
.unwrap();
14851485
}

backend/windmill-api/openapi.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,6 +3234,22 @@ paths:
32343234
type: array
32353235
items:
32363236
type: string
3237+
3238+
/teams/sync:
3239+
post:
3240+
operationId: syncTeams
3241+
summary: synchronize Microsoft Teams information (teams/channels)
3242+
tags:
3243+
- teams
3244+
responses:
3245+
'200':
3246+
description: Teams information successfully synchronized
3247+
content:
3248+
application/json:
3249+
schema:
3250+
type: array
3251+
items:
3252+
$ref: '#/components/schemas/TeamInfo'
32373253

32383254
/w/{workspace}/resources/create:
32393255
post:
@@ -14012,3 +14028,49 @@ components:
1401214028
format: date-time
1401314029
required:
1401414030
- trigger_kind
14031+
14032+
TeamInfo:
14033+
type: object
14034+
required:
14035+
- team_id
14036+
- team_name
14037+
- channels
14038+
properties:
14039+
team_id:
14040+
type: string
14041+
description: The unique identifier of the Microsoft Teams team
14042+
example: "19:abc123def456@thread.tacv2"
14043+
team_name:
14044+
type: string
14045+
description: The display name of the Microsoft Teams team
14046+
example: "Engineering Team"
14047+
channels:
14048+
type: array
14049+
description: List of channels within the team
14050+
items:
14051+
$ref: '#/components/schemas/ChannelInfo'
14052+
14053+
ChannelInfo:
14054+
type: object
14055+
required:
14056+
- channel_id
14057+
- channel_name
14058+
- tenant_id
14059+
- service_url
14060+
properties:
14061+
channel_id:
14062+
type: string
14063+
description: The unique identifier of the channel
14064+
example: "19:channel123@thread.tacv2"
14065+
channel_name:
14066+
type: string
14067+
description: The display name of the channel
14068+
example: "General"
14069+
tenant_id:
14070+
type: string
14071+
description: The Microsoft Teams tenant identifier
14072+
example: "12345678-1234-1234-1234-123456789012"
14073+
service_url:
14074+
type: string
14075+
description: The service URL for the channel
14076+
example: "https://smba.trafficmanager.net/amer/12345678-1234-1234-1234-123456789012/"

backend/windmill-api/src/ai.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use crate::{
2-
db::{ApiAuthed, DB},
3-
variables::decrypt,
4-
};
1+
use crate::db::{ApiAuthed, DB};
2+
use windmill_common::variables::decrypt;
53
use anthropic::AnthropicCache;
64
use axum::{
75
body::Bytes,

backend/windmill-api/src/apps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ use crate::{
1313
resources::get_resource_value_interpolated_internal,
1414
users::{require_owner_of_path, OptAuthed},
1515
utils::WithStarredInfoQuery,
16-
variables::encrypt,
1716
webhook_util::{WebhookMessage, WebhookShared},
1817
HTTP_CLIENT,
1918
};
19+
use windmill_common::variables::encrypt;
2020
#[cfg(feature = "parquet")]
2121
use crate::{
2222
job_helpers_ee::{

backend/windmill-api/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ mod scripts;
9696
mod service_logs;
9797
mod settings;
9898
mod slack_approvals;
99+
#[cfg(feature = "enterprise")]
100+
mod teams_ee;
99101
#[cfg(feature = "smtp")]
100102
mod smtp_server_ee;
101103
mod static_assets;
@@ -435,6 +437,17 @@ pub async fn run_server(
435437
jobs::workspace_unauthed_service().layer(cors.clone()),
436438
)
437439
.route("/slack", post(slack_approvals::slack_app_callback_handler))
440+
.nest("/teams", {
441+
#[cfg(feature = "enterprise")]
442+
{
443+
teams_ee::teams_service()
444+
}
445+
446+
#[cfg(not(feature = "enterprise"))]
447+
{
448+
Router::new()
449+
}
450+
})
438451
.route(
439452
"/w/:workspace_id/jobs/slack_approval/:job_id",
440453
get(slack_approvals::request_slack_approval),

backend/windmill-api/src/oauth2_ee.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ pub struct AllClients {
8080
}
8181

8282
#[cfg(feature = "oauth2")]
83-
pub fn build_oauth_clients(
83+
pub async fn build_oauth_clients(
8484
_base_url: &str,
8585
_oauths_from_config: Option<HashMap<String, OAuthClient>>,
86+
_db: &DB,
8687
) -> anyhow::Result<AllClients> {
8788
// Implementation is not open source
8889
return Ok(AllClients {

backend/windmill-api/src/teams_ee.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use axum::Router;
2+
3+
pub fn teams_service() -> Router {
4+
Router::new()
5+
}

backend/windmill-api/src/variables.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use windmill_common::{
3131
};
3232

3333
use lazy_static::lazy_static;
34-
use magic_crypt::{MagicCrypt256, MagicCryptError, MagicCryptTrait};
34+
use windmill_common::variables::{decrypt, encrypt};
3535
use serde::Deserialize;
3636
use sqlx::{Postgres, Transaction};
3737
use windmill_git_sync::{handle_deployment_metadata, DeployedObject};
@@ -676,17 +676,3 @@ pub async fn get_value_internal<'c>(
676676

677677
Ok(r)
678678
}
679-
680-
pub fn encrypt(mc: &MagicCrypt256, value: &str) -> String {
681-
mc.encrypt_str_to_base64(value)
682-
}
683-
684-
pub fn decrypt(mc: &MagicCrypt256, value: String) -> Result<String> {
685-
mc.decrypt_base64_to_string(value).map_err(|e| match e {
686-
MagicCryptError::DecryptError(_) => Error::InternalErr(
687-
"Could not decrypt value. The value may have been encrypted with a different key."
688-
.to_string(),
689-
),
690-
_ => Error::InternalErr(e.to_string()),
691-
})
692-
}

backend/windmill-api/src/workspaces.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ use windmill_git_sync::handle_deployment_metadata;
5252
#[cfg(feature = "enterprise")]
5353
use windmill_common::utils::require_admin_or_devops;
5454

55-
use crate::variables::{decrypt, encrypt};
55+
use windmill_common::variables::{decrypt, encrypt};
5656
use hyper::StatusCode;
5757
use serde::{Deserialize, Serialize};
5858
use sqlx::{FromRow, Postgres, Transaction};

backend/windmill-api/src/workspaces_export.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use windmill_common::{
3636
variables::ExportableListableVariable,
3737
};
3838

39-
use crate::variables::decrypt;
39+
use windmill_common::variables::decrypt;
4040
use hyper::header;
4141
use serde::{Deserialize, Serialize};
4242
use serde_json::Value;

backend/windmill-common/src/global_settings.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub const PIP_INDEX_URL_SETTING: &str = "pip_index_url";
1717
pub const SCIM_TOKEN_SETTING: &str = "scim_token";
1818
pub const SAML_METADATA_SETTING: &str = "saml_metadata";
1919
pub const SMTP_SETTING: &str = "smtp_settings";
20+
pub const TEAMS_SETTING: &str = "teams";
2021
pub const INDEXER_SETTING: &str = "indexer_settings";
2122
pub const TIMEOUT_WAIT_RESULT_SETTING: &str = "timeout_wait_result";
2223

@@ -94,3 +95,21 @@ pub const ENV_SETTINGS: [&str; 54] = [
9495
"OTEL_TRACING",
9596
"OTEL_LOGS",
9697
];
98+
99+
use crate::error;
100+
use sqlx::Pool;
101+
use sqlx::postgres::Postgres;
102+
103+
pub async fn load_value_from_global_settings(
104+
db: &Pool<Postgres>,
105+
setting_name: &str,
106+
) -> error::Result<Option<serde_json::Value>> {
107+
let r = sqlx::query!(
108+
"SELECT value FROM global_settings WHERE name = $1",
109+
setting_name
110+
)
111+
.fetch_optional(db)
112+
.await?
113+
.map(|x| x.value);
114+
Ok(r)
115+
}

backend/windmill-common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub mod job_s3_helpers_ee;
3636
pub mod jobs;
3737
pub mod more_serde;
3838
pub mod oauth2;
39+
pub mod teams_ee;
3940
pub mod otel_ee;
4041
pub mod queue;
4142
pub mod s3_helpers;

backend/windmill-common/src/oauth2.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub const WORKSPACE_SLACK_BOT_TOKEN_PATH: &str = "f/slack_bot/bot_token";
1818

1919
pub const GLOBAL_SLACK_BOT_TOKEN_PATH: &str = "f/slack_bot/global_bot_token";
2020

21+
pub const GLOBAL_TEAMS_BOT_TOKEN_PATH: &str = "f/teams_bot/global_bot_token";
22+
23+
pub const GLOBAL_TEAMS_API_TOKEN_PATH: &str = "f/teams_bot/global_api_token";
2124
lazy_static::lazy_static! {
2225

2326
pub static ref REQUIRE_PREEXISTING_USER_FOR_OAUTH: AtomicBool = AtomicBool::new(std::env::var("REQUIRE_PREEXISTING_USER_FOR_OAUTH")

backend/windmill-common/src/teams_ee.rs

Whitespace-only changes.

backend/windmill-common/src/variables.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use chrono::{SecondsFormat, Utc};
1010
use magic_crypt::{MagicCrypt256, MagicCryptError, MagicCryptTrait};
1111
use serde::{Deserialize, Serialize};
12+
use crate::error;
1213

1314
use crate::{worker::WORKER_GROUP, BASE_URL, DB};
1415

@@ -157,6 +158,20 @@ pub async fn decrypt_value_with_mc(
157158
})?)
158159
}
159160

161+
pub fn encrypt(mc: &MagicCrypt256, value: &str) -> String {
162+
mc.encrypt_str_to_base64(value)
163+
}
164+
165+
pub fn decrypt(mc: &MagicCrypt256, value: String) -> error::Result<String> {
166+
mc.decrypt_base64_to_string(value).map_err(|e| match e {
167+
MagicCryptError::DecryptError(_) => error::Error::InternalErr(
168+
"Could not decrypt value. The value may have been encrypted with a different key."
169+
.to_string(),
170+
),
171+
_ => error::Error::InternalErr(e.to_string()),
172+
})
173+
}
174+
160175
pub const WM_SCHEDULED_FOR: &str = "WM_SCHEDULED_FOR";
161176

162177
pub async fn get_reserved_variables(

0 commit comments

Comments
 (0)