-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sdf, dal): Adding the ability to set a webhook url for a workspace
We currently only post to that webhook from the change set approval flow but we want to make this more of an opt-in to what you can / can't to
- Loading branch information
Showing
19 changed files
with
496 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<template> | ||
<Modal | ||
ref="modalRef" | ||
type="save" | ||
size="sm" | ||
saveLabel="Save" | ||
title="Save Integrations" | ||
@save="updateIntegrations" | ||
> | ||
<VormInput ref="labelRef" v-model="webhookUrl" label="Slack Webhook Url" /> | ||
</Modal> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { Modal, VormInput } from "@si/vue-lib/design-system"; | ||
import { ref, computed } from "vue"; | ||
import { useWorkspacesStore } from "@/store/workspaces.store"; | ||
const workspacesStore = useWorkspacesStore(); | ||
const modalRef = ref<InstanceType<typeof Modal>>(); | ||
const integration = computed(() => workspacesStore.getIntegrations); | ||
function open() { | ||
if ( | ||
integration.value && | ||
integration.value.slackWebhookUrl && | ||
integration.value.slackWebhookUrl !== "" | ||
) { | ||
webhookUrl.value = integration.value.slackWebhookUrl; | ||
} | ||
modalRef.value?.open(); | ||
} | ||
const webhookUrl = ref(""); | ||
const updateIntegrations = () => { | ||
if (!webhookUrl.value || webhookUrl.value === "" || !integration.value?.pk) | ||
return; | ||
workspacesStore.UPDATE_INTEGRATION(integration.value?.pk, webhookUrl.value); | ||
modalRef.value?.close(); | ||
webhookUrl.value = ""; | ||
}; | ||
defineExpose({ open }); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
CREATE TABLE workspace_integrations | ||
( | ||
pk ident primary key default ident_create_v1(), | ||
slack_webhook_url text NULL, | ||
workspace_pk ident NOT NULL | ||
); | ||
CREATE UNIQUE INDEX ON workspace_integrations (pk); | ||
CREATE UNIQUE INDEX ON workspace_integrations (workspace_pk); | ||
CREATE UNIQUE INDEX ON workspace_integrations (slack_webhook_url, workspace_pk); | ||
CREATE INDEX ON workspace_integrations (slack_webhook_url); | ||
CREATE INDEX ON workspace_integrations (workspace_pk); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
use crate::{workspace::WorkspaceId, DalContext, TransactionsError}; | ||
use serde::{Deserialize, Serialize}; | ||
use si_data_pg::{PgError, PgRow}; | ||
use thiserror::Error; | ||
|
||
#[remain::sorted] | ||
#[derive(Error, Debug)] | ||
pub enum WorkspaceIntegrationsError { | ||
#[error(transparent)] | ||
Pg(#[from] PgError), | ||
#[error("transactions error: {0}")] | ||
Transactions(#[from] TransactionsError), | ||
} | ||
|
||
pub type WorkspaceIntegrationsResult<T> = Result<T, WorkspaceIntegrationsError>; | ||
|
||
pub use si_id::WorkspaceIntegrationId; | ||
|
||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] | ||
pub struct WorkspaceIntegration { | ||
pk: WorkspaceIntegrationId, | ||
workspace_pk: WorkspaceId, | ||
slack_webhook_url: Option<String>, | ||
} | ||
|
||
impl TryFrom<PgRow> for WorkspaceIntegration { | ||
type Error = WorkspaceIntegrationsError; | ||
|
||
fn try_from(row: PgRow) -> Result<Self, Self::Error> { | ||
Ok(Self { | ||
pk: row.try_get("pk")?, | ||
workspace_pk: row.try_get("workspace_pk")?, | ||
slack_webhook_url: row.try_get("slack_webhook_url")?, | ||
}) | ||
} | ||
} | ||
|
||
impl WorkspaceIntegration { | ||
pub fn pk(&self) -> &WorkspaceIntegrationId { | ||
&self.pk | ||
} | ||
|
||
pub fn slack_webhook_url(&self) -> Option<String> { | ||
self.slack_webhook_url.clone() | ||
} | ||
|
||
pub async fn update_webhook_url( | ||
&mut self, | ||
ctx: &DalContext, | ||
webhook_url: String, | ||
) -> WorkspaceIntegrationsResult<()> { | ||
ctx.txns() | ||
.await? | ||
.pg() | ||
.query_none( | ||
"UPDATE workspace_integrations SET slack_webhook_url = $2 WHERE pk = $1", | ||
&[&self.pk, &webhook_url], | ||
) | ||
.await?; | ||
self.slack_webhook_url = Some(webhook_url); | ||
|
||
Ok(()) | ||
} | ||
|
||
pub async fn new( | ||
ctx: &DalContext, | ||
webhook_url: Option<String>, | ||
) -> WorkspaceIntegrationsResult<Self> { | ||
let workspace_pk = ctx.workspace_pk()?; | ||
|
||
let row = ctx | ||
.txns() | ||
.await? | ||
.pg() | ||
.query_one( | ||
"INSERT INTO workspace_integrations (workspace_pk, slack_webhook_url) VALUES ($1, $2) RETURNING *", | ||
&[&workspace_pk, &webhook_url], | ||
) | ||
.await?; | ||
|
||
let workspace_integration = Self::try_from(row)?; | ||
|
||
Ok(workspace_integration) | ||
} | ||
|
||
pub async fn get_integrations_for_workspace_pk( | ||
ctx: &DalContext, | ||
) -> WorkspaceIntegrationsResult<Option<Self>> { | ||
let workspace_pk = ctx.workspace_pk()?; | ||
|
||
let maybe_row = ctx | ||
.txns() | ||
.await? | ||
.pg() | ||
.query_opt( | ||
"SELECT * FROM workspace_integrations AS w WHERE workspace_pk = $1", | ||
&[&workspace_pk], | ||
) | ||
.await?; | ||
let maybe_workspace_integration = match maybe_row { | ||
Some(found) => Some(Self::try_from(found)?), | ||
None => None, | ||
}; | ||
Ok(maybe_workspace_integration) | ||
} | ||
|
||
pub async fn get_by_pk( | ||
ctx: &DalContext, | ||
workspace_integration_id: WorkspaceIntegrationId, | ||
) -> WorkspaceIntegrationsResult<Option<Self>> { | ||
let maybe_row = ctx | ||
.txns() | ||
.await? | ||
.pg() | ||
.query_opt( | ||
"SELECT * FROM workspace_integrations AS w WHERE pk = $1", | ||
&[&workspace_integration_id], | ||
) | ||
.await?; | ||
let maybe_workspace_integration = match maybe_row { | ||
Some(found) => Some(Self::try_from(found)?), | ||
None => None, | ||
}; | ||
Ok(maybe_workspace_integration) | ||
} | ||
} |
Oops, something went wrong.