Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[server] Add db auditing #979 #1037

Merged
merged 12 commits into from
Feb 5, 2024
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ agdb_server.yaml
agdb_benchmarks.agdb
.agdb_server.agdb
agdb_server.agdb
agdb_server_data/
!.github/workflows/agdb_benchmarks.yaml
!.github/workflows/agdb_server.yaml
54 changes: 54 additions & 0 deletions agdb/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ use crate::{
#[cfg(any(feature = "serde", feature = "opeanapi"))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub enum QueryType {
InsertAlias(InsertAliasesQuery),
InsertEdges(InsertEdgesQuery),
Expand Down Expand Up @@ -193,3 +194,56 @@ impl From<SelectValuesQuery> for QueryType {
QueryType::SelectValues(value)
}
}

#[cfg(any(feature = "serde", feature = "opeanapi"))]
#[cfg(test)]
mod tests {
use super::*;
use crate::QueryBuilder;

#[test]
fn derived_from_debug_and_partial_eq() {
let queries: Vec<QueryType> = vec![
QueryBuilder::insert().nodes().count(2).query().into(),
QueryBuilder::insert()
.aliases(vec!["node1", "node2"])
.ids(vec![1, 2])
.query()
.into(),
QueryBuilder::insert()
.edges()
.from("node1")
.to("node2")
.query()
.into(),
QueryBuilder::insert()
.values(vec![vec![("key", 1.1).into()]])
.ids("node1")
.query()
.into(),
QueryBuilder::insert().index("key").query().into(),
QueryBuilder::search().from(1).query().into(),
QueryBuilder::select().ids(1).query().into(),
QueryBuilder::select().aliases().ids(1).query().into(),
QueryBuilder::select().aliases().query().into(),
QueryBuilder::select().indexes().query().into(),
QueryBuilder::select().keys().ids(1).query().into(),
QueryBuilder::select().key_count().ids(1).query().into(),
QueryBuilder::select()
.values(vec!["key".into()])
.ids(1)
.query()
.into(),
QueryBuilder::remove().aliases("node2").query().into(),
QueryBuilder::remove().index("key").query().into(),
QueryBuilder::remove()
.values(vec!["key".into()])
.ids(1)
.query()
.into(),
QueryBuilder::remove().ids("node1").query().into(),
];
format!("{:?}", queries);
assert_eq!(queries, queries);
}
}
1 change: 1 addition & 0 deletions agdb/src/query/insert_aliases_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::StorageData;
/// The result will contain number of aliases inserted/updated but no elements.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct InsertAliasesQuery {
/// Ids to be aliased
pub ids: QueryIds,
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/insert_edges_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::StorageData;
/// their ids but no properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct InsertEdgesQuery {
/// Origins
pub from: QueryIds,
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/insert_index_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::StorageData;
/// a given key.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct InsertIndexQuery(pub DbValue);

impl QueryMut for InsertIndexQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/insert_nodes_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::StorageData;
/// their ids but no properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct InsertNodesQuery {
/// Number of nodes to be inserted.
pub count: u64,
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/insert_values_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::StorageData;
/// NOTE: The result is NOT number of affected elements but individual properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct InsertValuesQuery {
/// Ids whose properties should be updated
pub ids: QueryIds,
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/query_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::DbValue;
/// and multiple (`Multi`) values in database queries.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub enum QueryValues {
/// Single list of properties (key-value pairs)
/// to be applied to all elements in a query.
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/remove_aliases_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::StorageData;
/// many aliases have been actually removed.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct RemoveAliasesQuery(pub Vec<String>);

impl QueryMut for RemoveAliasesQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/remove_index_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::StorageData;
/// a given key.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct RemoveIndexQuery(pub DbValue);

impl QueryMut for RemoveIndexQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/remove_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::StorageData;
/// also removed along with their properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct RemoveQuery(pub QueryIds);

impl QueryMut for RemoveQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/remove_values_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::StorageData;
/// do not exist on any of the elements).
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct RemoveValuesQuery(pub SelectValuesQuery);

impl QueryMut for RemoveValuesQuery {
Expand Down
2 changes: 1 addition & 1 deletion agdb/src/query/search_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use crate::StorageData;
use std::cmp::Ordering;

/// Search algorithm to be used
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SearchQueryAlgorithm {
/// Examines each distance level from the search origin in full
/// before continuing with the next level. E.g. when starting at
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_aliases_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::StorageData;
/// the value `String`.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectAliasesQuery(pub QueryIds);

impl Query for SelectAliasesQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_all_aliases_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::StorageData;
/// the value `String`.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectAllAliasesQuery {}

impl Query for SelectAllAliasesQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_indexes_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::StorageData;
/// index.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectIndexesQuery {}

impl Query for SelectIndexesQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_key_count_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::StorageData;
/// a value `u64`.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectKeyCountQuery(pub QueryIds);

impl Query for SelectKeyCountQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_keys_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::StorageData;
/// of elements with all properties except all values will be empty.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectKeysQuery(pub QueryIds);

impl Query for SelectKeysQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::StorageData;
/// list of elements with all properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectQuery(pub QueryIds);

impl Query for SelectQuery {
Expand Down
1 change: 1 addition & 0 deletions agdb/src/query/select_values_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::StorageData;
/// list of elements with the requested properties.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[derive(Debug, PartialEq)]
pub struct SelectValuesQuery {
pub keys: Vec<DbValue>,
pub ids: QueryIds,
Expand Down
21 changes: 18 additions & 3 deletions agdb_api/rust/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use agdb::QueryResult;
use agdb::QueryType;

use crate::api_result::AgdbApiResult;
use crate::api_types::DbType;
use crate::api_types::ServerDatabase;
use crate::api_types::UserCredentials;
use crate::http_client::HttpClient;
use crate::ChangePassword;
use crate::DbAudit;
use crate::DbUser;
use crate::DbUserRole;
use crate::UserLogin;
use crate::UserStatus;
use agdb::QueryResult;
use agdb::QueryType;

pub struct AgdbApi<T: HttpClient> {
client: T,
Expand Down Expand Up @@ -41,6 +41,15 @@ impl<T: HttpClient> AgdbApi<T> {
.0)
}

pub async fn admin_db_audit(&self, owner: &str, db: &str) -> AgdbApiResult<(u16, DbAudit)> {
self.client
.get(
&self.url(&format!("/admin/db/{owner}/{db}/audit")),
&self.token,
)
.await
}

pub async fn admin_db_backup(&self, owner: &str, db: &str) -> AgdbApiResult<u16> {
Ok(self
.client
Expand Down Expand Up @@ -268,6 +277,12 @@ impl<T: HttpClient> AgdbApi<T> {
.0)
}

pub async fn db_audit(&self, owner: &str, db: &str) -> AgdbApiResult<(u16, DbAudit)> {
self.client
.get(&self.url(&format!("/db/{owner}/{db}/audit")), &self.token)
.await
}

pub async fn db_backup(&self, owner: &str, db: &str) -> AgdbApiResult<u16> {
Ok(self
.client
Expand Down
32 changes: 32 additions & 0 deletions agdb_api/rust/src/api_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ pub struct Queries(pub Vec<QueryType>);
#[derive(Serialize, ToSchema)]
pub struct QueriesResults(pub Vec<QueryResult>);

#[derive(Debug, Deserialize, Serialize, ToSchema, PartialEq)]
pub struct QueryAudit {
pub timestamp: u64,
pub user: String,
pub query: QueryType,
}

#[derive(Debug, Deserialize, Serialize, ToSchema, PartialEq)]
pub struct DbAudit(pub Vec<QueryAudit>);

#[derive(Debug, Default, Deserialize, Serialize, ToSchema, PartialEq, Eq, PartialOrd, Ord)]
pub struct ServerDatabase {
pub name: String,
Expand Down Expand Up @@ -139,6 +149,8 @@ impl Display for DbUserRole {

#[cfg(test)]
mod tests {
use agdb::SelectIndexesQuery;

use super::*;

#[test]
Expand Down Expand Up @@ -168,6 +180,26 @@ mod tests {
name: "user".to_string()
}
);
format!(
"{:?}",
QueryAudit {
timestamp: 0,
user: "user".to_string(),
query: QueryType::SelectIndexes(SelectIndexesQuery {})
}
);
format!("{:?}", DbAudit(vec![]));
}

#[test]
fn derived_from_partial_eq() {
let query_audit = QueryAudit {
timestamp: 0,
user: "user".to_string(),
query: QueryType::SelectIndexes(SelectIndexesQuery {}),
};
let audit = DbAudit(vec![query_audit]);
assert_eq!(audit, audit);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions agdb_api/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ pub use api::AgdbApi;
pub use api_error::AgdbApiError;
pub use api_result::AgdbApiResult;
pub use api_types::ChangePassword;
pub use api_types::DbAudit;
pub use api_types::DbType;
pub use api_types::DbUser;
pub use api_types::DbUserRole;
pub use api_types::Queries;
pub use api_types::QueriesResults;
pub use api_types::QueryAudit;
pub use api_types::ServerDatabase;
pub use api_types::UserCredentials;
pub use api_types::UserLogin;
Expand Down
Loading
Loading