mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-11 17:44:19 -05:00
* start 1.19.4 * deploy 1.19.4-dev-1 * try smaller binaries with cargo strip * deploy 1.19.4-dev-2 * smaller binaries with cargo strip * Fix Submit Dialog Button Behavior with 500 Errors on Duplicate Names (#819) * Implement enhanced error handling and messaging for resource creation * Implement improved error handling for resource creation across alerter, build, and sync * Implement error handling improvements for resource copying and validation feedback * Adjust error handling for resource creation to distinguish validation errors from unexpected system errors * Refactor resource creation error handling by removing redundant match statements and simplifying the error propagation in multiple API modules. * fmt * bump indexmap * fix account selector showing empty when account no longer found * clean up theme logic, ensure monaco and others get up to date current theme * enforce disable_non_admin_create for tags. Clean up status code responses * update server cache concurrency controller * deploy 1.19.4-dev-3 * Allow signing in by pressing enter (#830) * Improve dialog overflow handling to prevent clipping of content (#828) * Add Email notification entry to community.md (#824) * Add clickable file path to show/hide file contents in StackInfo (#827) * add clickable file path to show/hide file contents in StackInfo Also added CopyButton due to the new functionality making the file path not selectable. * Move clicking interaction to CardHeader * Avoid sync edge cases of having toggle show function capturing showContents from outside Co-authored-by: Maxwell Becker <49575486+mbecker20@users.noreply.github.com> * Format previous change * Add `default_show_contents` to `handleToggleShow` --------- Co-authored-by: Maxwell Becker <49575486+mbecker20@users.noreply.github.com> * deploy 1.19.4-dev-4 * avoid stake info ShowHideButton double toggle * Allow multiple simultaneous Action runs for use with Args * deploy 1.19.4-dev-5 * feat: persist all table sorting states including unsorted (#832) - Always save sorting state to localStorage, even when empty/unsorted - Fixes issue where 'unsorted' state was not persisted across page reloads - Ensures consistent and predictable sorting behavior for all DataTable components * autofocus on login username field (#837) * Fix unnecessary auth queries flooding console on login page (#842) * Refactor authentication error handling to use serror::Result and status codes * Enable user query only when JWT is present * Enable query execution in useRead only if JWT is present * Revert backend auth changes - keep PR focused on frontend only * Fix unnecessary API queries to unreachable servers flooding console (#843) * Implement server availability checks in various components * Refactor server availability check to ensure only healthy servers are identified * cargo fmt * fmt * Auth error handling with status codes (#841) * Refactor authentication error handling to use serror::Result and status codes * Refactor error messages * Refactor authentication error handling to include status codes and improve error messages * clean up * clean * fmt * invalid user id also UNAUTHORIZED * deploy 1.19.4-dev-6 * deploy 1.19.4-dev-7 --------- Co-authored-by: Marcel Pfennig <82059270+MP-Tool@users.noreply.github.com> Co-authored-by: jack <45038833+jackra1n@users.noreply.github.com> Co-authored-by: Guten <ywzhaifei@gmail.com> Co-authored-by: Paulo Roberto Albuquerque <paulora2405@gmail.com> Co-authored-by: Lorenzo Farnararo <2814802+baldarn@users.noreply.github.com>
245 lines
5.5 KiB
Rust
245 lines
5.5 KiB
Rust
use anyhow::Context;
|
|
use komodo_client::{
|
|
api::read::*,
|
|
entities::{
|
|
config::core::CoreConfig,
|
|
permission::PermissionLevel,
|
|
sync::{
|
|
ResourceSync, ResourceSyncActionState, ResourceSyncListItem,
|
|
},
|
|
},
|
|
};
|
|
use resolver_api::Resolve;
|
|
|
|
use crate::{
|
|
config::core_config,
|
|
helpers::query::get_all_tags,
|
|
permission::get_check_permissions,
|
|
resource,
|
|
state::{action_states, github_client},
|
|
};
|
|
|
|
use super::ReadArgs;
|
|
|
|
impl Resolve<ReadArgs> for GetResourceSync {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<ResourceSync> {
|
|
Ok(
|
|
get_check_permissions::<ResourceSync>(
|
|
&self.sync,
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
)
|
|
.await?,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Resolve<ReadArgs> for ListResourceSyncs {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<Vec<ResourceSyncListItem>> {
|
|
let all_tags = if self.query.tags.is_empty() {
|
|
vec![]
|
|
} else {
|
|
get_all_tags(None).await?
|
|
};
|
|
Ok(
|
|
resource::list_for_user::<ResourceSync>(
|
|
self.query,
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
&all_tags,
|
|
)
|
|
.await?,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Resolve<ReadArgs> for ListFullResourceSyncs {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<ListFullResourceSyncsResponse> {
|
|
let all_tags = if self.query.tags.is_empty() {
|
|
vec![]
|
|
} else {
|
|
get_all_tags(None).await?
|
|
};
|
|
Ok(
|
|
resource::list_full_for_user::<ResourceSync>(
|
|
self.query,
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
&all_tags,
|
|
)
|
|
.await?,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Resolve<ReadArgs> for GetResourceSyncActionState {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<ResourceSyncActionState> {
|
|
let sync = get_check_permissions::<ResourceSync>(
|
|
&self.sync,
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
)
|
|
.await?;
|
|
let action_state = action_states()
|
|
.sync
|
|
.get(&sync.id)
|
|
.await
|
|
.unwrap_or_default()
|
|
.get()?;
|
|
Ok(action_state)
|
|
}
|
|
}
|
|
|
|
impl Resolve<ReadArgs> for GetResourceSyncsSummary {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<GetResourceSyncsSummaryResponse> {
|
|
let resource_syncs =
|
|
resource::list_full_for_user::<ResourceSync>(
|
|
Default::default(),
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
&[],
|
|
)
|
|
.await
|
|
.context("failed to get resource_syncs from db")?;
|
|
|
|
let mut res = GetResourceSyncsSummaryResponse::default();
|
|
|
|
let action_states = action_states();
|
|
|
|
for resource_sync in resource_syncs {
|
|
res.total += 1;
|
|
|
|
if !(resource_sync.info.pending_deploy.to_deploy == 0
|
|
&& resource_sync.info.resource_updates.is_empty()
|
|
&& resource_sync.info.variable_updates.is_empty()
|
|
&& resource_sync.info.user_group_updates.is_empty())
|
|
{
|
|
res.pending += 1;
|
|
continue;
|
|
} else if resource_sync.info.pending_error.is_some()
|
|
|| !resource_sync.info.remote_errors.is_empty()
|
|
{
|
|
res.failed += 1;
|
|
continue;
|
|
}
|
|
if action_states
|
|
.sync
|
|
.get(&resource_sync.id)
|
|
.await
|
|
.unwrap_or_default()
|
|
.get()?
|
|
.syncing
|
|
{
|
|
res.syncing += 1;
|
|
continue;
|
|
}
|
|
res.ok += 1;
|
|
}
|
|
|
|
Ok(res)
|
|
}
|
|
}
|
|
|
|
impl Resolve<ReadArgs> for GetSyncWebhooksEnabled {
|
|
async fn resolve(
|
|
self,
|
|
ReadArgs { user }: &ReadArgs,
|
|
) -> serror::Result<GetSyncWebhooksEnabledResponse> {
|
|
let Some(github) = github_client() else {
|
|
return Ok(GetSyncWebhooksEnabledResponse {
|
|
managed: false,
|
|
refresh_enabled: false,
|
|
sync_enabled: false,
|
|
});
|
|
};
|
|
|
|
let sync = get_check_permissions::<ResourceSync>(
|
|
&self.sync,
|
|
user,
|
|
PermissionLevel::Read.into(),
|
|
)
|
|
.await?;
|
|
|
|
if sync.config.git_provider != "github.com"
|
|
|| sync.config.repo.is_empty()
|
|
{
|
|
return Ok(GetSyncWebhooksEnabledResponse {
|
|
managed: false,
|
|
refresh_enabled: false,
|
|
sync_enabled: false,
|
|
});
|
|
}
|
|
|
|
let mut split = sync.config.repo.split('/');
|
|
let owner = split.next().context("Sync repo has no owner")?;
|
|
|
|
let Some(github) = github.get(owner) else {
|
|
return Ok(GetSyncWebhooksEnabledResponse {
|
|
managed: false,
|
|
refresh_enabled: false,
|
|
sync_enabled: false,
|
|
});
|
|
};
|
|
|
|
let repo_name =
|
|
split.next().context("Repo repo has no repo after the /")?;
|
|
|
|
let github_repos = github.repos();
|
|
|
|
let webhooks = github_repos
|
|
.list_all_webhooks(owner, repo_name)
|
|
.await
|
|
.context("failed to list all webhooks on repo")?
|
|
.body;
|
|
|
|
let CoreConfig {
|
|
host,
|
|
webhook_base_url,
|
|
..
|
|
} = core_config();
|
|
|
|
let host = if webhook_base_url.is_empty() {
|
|
host
|
|
} else {
|
|
webhook_base_url
|
|
};
|
|
let refresh_url =
|
|
format!("{host}/listener/github/sync/{}/refresh", sync.id);
|
|
let sync_url =
|
|
format!("{host}/listener/github/sync/{}/sync", sync.id);
|
|
|
|
let mut refresh_enabled = false;
|
|
let mut sync_enabled = false;
|
|
|
|
for webhook in webhooks {
|
|
if webhook.active && webhook.config.url == refresh_url {
|
|
refresh_enabled = true
|
|
}
|
|
if webhook.active && webhook.config.url == sync_url {
|
|
sync_enabled = true
|
|
}
|
|
}
|
|
|
|
Ok(GetSyncWebhooksEnabledResponse {
|
|
managed: true,
|
|
refresh_enabled,
|
|
sync_enabled,
|
|
})
|
|
}
|
|
}
|