mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-13 16:01:21 +00:00
paginated list updates
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{anyhow, Context};
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{
|
||||
@@ -14,7 +14,7 @@ use monitor_types::{
|
||||
ServerListItem,
|
||||
},
|
||||
};
|
||||
use mungos::mongodb::bson::{doc, oid::ObjectId, Document};
|
||||
use mungos::mongodb::bson::{doc, oid::ObjectId};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, state::State};
|
||||
@@ -25,7 +25,7 @@ const ALL_RESOURCE_TYPES: [ResourceTargetVariant; 4] = [Server, Build, Deploymen
|
||||
impl Resolve<FindResources, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
FindResources { tags }: FindResources,
|
||||
FindResources { search, tags }: FindResources,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<FindResourcesResponse> {
|
||||
let SeperateTags {
|
||||
@@ -34,7 +34,16 @@ impl Resolve<FindResources, RequestUser> for State {
|
||||
custom_tag_ids,
|
||||
} = seperate_tags(tags);
|
||||
|
||||
let mut query = Document::new();
|
||||
let mut query = doc! {
|
||||
"name": { "$regex": search }
|
||||
};
|
||||
|
||||
if !user.is_admin {
|
||||
query.insert(
|
||||
format!("permissions.{}", user.id),
|
||||
doc! { "$in": ["read", "execute", "update"] },
|
||||
);
|
||||
}
|
||||
|
||||
if !custom_tag_ids.is_empty() {
|
||||
query.insert("tags", doc! { "$all": custom_tag_ids });
|
||||
@@ -55,13 +64,10 @@ impl Resolve<FindResources, RequestUser> for State {
|
||||
.context("failed to parse server id as ObjectId")
|
||||
})
|
||||
.collect::<anyhow::Result<Vec<_>>>()?;
|
||||
self.db
|
||||
.servers
|
||||
.get_some(doc! { "_id": { "$in": server_ids } }, None)
|
||||
.await?
|
||||
}
|
||||
.into_iter()
|
||||
.filter(|s| s.get_user_permissions(&user.id) > PermissionLevel::None);
|
||||
let mut query = query.clone();
|
||||
query.insert("_id", doc! { "$in": server_ids });
|
||||
self.db.servers.get_some(query, None).await?
|
||||
};
|
||||
for server in servers {
|
||||
let status = self
|
||||
.server_status_cache
|
||||
@@ -163,7 +169,7 @@ impl Resolve<FindResources, RequestUser> for State {
|
||||
response.repos.push(item);
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
_ => return Err(anyhow!("{resource_type} is not compatible with this route")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +192,7 @@ fn seperate_tags(tags: Vec<Tag>) -> SeperateTags {
|
||||
Tag::Custom { tag_id } => seperated.custom_tag_ids.push(tag_id),
|
||||
Tag::Server { server_id } => seperated.server_ids.push(server_id),
|
||||
Tag::ResourceType { resource } => {
|
||||
if !matches!(resource, Builder | System,)
|
||||
if !matches!(resource, Builder | Alerter | System,)
|
||||
&& !seperated.resource_types.contains(&resource)
|
||||
{
|
||||
seperated.resource_types.push(resource);
|
||||
|
||||
@@ -1,34 +1,73 @@
|
||||
use async_trait::async_trait;
|
||||
use monitor_types::{
|
||||
entities::{build::Build, update::Update},
|
||||
requests::read::ListUpdates,
|
||||
entities::{
|
||||
alerter::Alerter, build::Build, builder::Builder, deployment::Deployment, repo::Repo,
|
||||
server::Server,
|
||||
},
|
||||
requests::read::{ListUpdates, ListUpdatesResponse},
|
||||
};
|
||||
use mungos::mongodb::{bson::doc, options::FindOptions};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{auth::RequestUser, resource::Resource, state::State};
|
||||
|
||||
const UPDATES_PER_PAGE: i64 = 20;
|
||||
|
||||
#[async_trait]
|
||||
impl Resolve<ListUpdates, RequestUser> for State {
|
||||
async fn resolve(
|
||||
&self,
|
||||
ListUpdates { query }: ListUpdates,
|
||||
ListUpdates { query, page }: ListUpdates,
|
||||
user: RequestUser,
|
||||
) -> anyhow::Result<Vec<Update>> {
|
||||
if user.is_admin {
|
||||
let updates = self
|
||||
.db
|
||||
.updates
|
||||
.get_some(
|
||||
query,
|
||||
FindOptions::builder().sort(doc! { "ts": -1 }).build(),
|
||||
)
|
||||
.await?;
|
||||
Ok(updates)
|
||||
) -> anyhow::Result<ListUpdatesResponse> {
|
||||
let query = if user.is_admin {
|
||||
query
|
||||
} else {
|
||||
let server_ids =
|
||||
<State as Resource<Server>>::get_resource_ids_for_non_admin(self, &user.id).await?;
|
||||
let deployment_ids =
|
||||
<State as Resource<Deployment>>::get_resource_ids_for_non_admin(self, &user.id)
|
||||
.await?;
|
||||
let build_ids =
|
||||
<State as Resource<Build>>::get_resource_ids_for_non_admin(self, &user.id).await?;
|
||||
todo!()
|
||||
}
|
||||
let repo_ids =
|
||||
<State as Resource<Repo>>::get_resource_ids_for_non_admin(self, &user.id).await?;
|
||||
let builder_ids =
|
||||
<State as Resource<Builder>>::get_resource_ids_for_non_admin(self, &user.id)
|
||||
.await?;
|
||||
let alerter_ids =
|
||||
<State as Resource<Alerter>>::get_resource_ids_for_non_admin(self, &user.id)
|
||||
.await?;
|
||||
let mut query = query.unwrap_or_default();
|
||||
query.extend(doc! {
|
||||
"$or": [
|
||||
{ "target.type": "Server", "target.id": { "$in": &server_ids } },
|
||||
{ "target.type": "Deployment", "target.id": { "$in": &deployment_ids } },
|
||||
{ "target.type": "Build", "target.id": { "$in": &build_ids } },
|
||||
{ "target.type": "Repo", "target.id": { "$in": &repo_ids } },
|
||||
{ "target.type": "Builder", "target.id": { "$in": &builder_ids } },
|
||||
{ "target.type": "Alerter", "target.id": { "$in": &alerter_ids } },
|
||||
]
|
||||
});
|
||||
query.into()
|
||||
};
|
||||
let updates = self
|
||||
.db
|
||||
.updates
|
||||
.get_some(
|
||||
query,
|
||||
FindOptions::builder()
|
||||
.sort(doc! { "ts": -1 })
|
||||
.skip(page as u64 * UPDATES_PER_PAGE as u64)
|
||||
.limit(UPDATES_PER_PAGE)
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
let next_page = if updates.len() == UPDATES_PER_PAGE as usize {
|
||||
Some(page + 1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(ListUpdatesResponse { updates, next_page })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export type ReadResponses = {
|
||||
ListTags: Types.CustomTag[];
|
||||
|
||||
// ==== UPDATE ====
|
||||
ListUpdates: Types.Update[];
|
||||
ListUpdates: Types.ListUpdatesResponse;
|
||||
|
||||
// ==== SERVER STATS ====
|
||||
GetAllSystemStats: Types.AllSystemStats;
|
||||
|
||||
@@ -918,6 +918,7 @@ export type Tag =
|
||||
}};
|
||||
|
||||
export interface FindResources {
|
||||
search: string;
|
||||
tags: Tag[];
|
||||
}
|
||||
|
||||
@@ -1033,6 +1034,12 @@ export interface ListTags {
|
||||
|
||||
export interface ListUpdates {
|
||||
query?: MongoDocument;
|
||||
page?: number;
|
||||
}
|
||||
|
||||
export interface ListUpdatesResponse {
|
||||
updates: Update[];
|
||||
next_page?: number;
|
||||
}
|
||||
|
||||
export type PartialAlerterConfig =
|
||||
|
||||
@@ -12,6 +12,7 @@ use super::{BuildListItem, DeploymentListItem, RepoListItem, ServerListItem};
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(FindResourcesResponse)]
|
||||
pub struct FindResources {
|
||||
pub search: String,
|
||||
pub tags: Vec<Tag>,
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,16 @@ use crate::{entities::update::Update, MongoDocument};
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||
#[response(Vec<Update>)]
|
||||
#[response(ListUpdatesResponse)]
|
||||
pub struct ListUpdates {
|
||||
pub query: Option<MongoDocument>,
|
||||
#[serde(default)]
|
||||
pub page: u32,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ListUpdatesResponse {
|
||||
pub updates: Vec<Update>,
|
||||
pub next_page: Option<u32>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user