Skip to content

Commit

Permalink
Merge pull request #111 from nightly-labs/stats-api
Browse files Browse the repository at this point in the history
Stats api init methods
  • Loading branch information
Giems authored Mar 6, 2024
2 parents b749ce0 + fa4094d commit d21eb27
Show file tree
Hide file tree
Showing 40 changed files with 493 additions and 57 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ anyhow = "1.0.79"
serde_json = "1.0.113"
strum = { version = "0.26.1", features = ["derive"] }
dotenvy = "0.15.7"
ts-rs = "6.2.1"
ts-rs = { version = "6.2.1", features = ["serde-compat", "chrono-impl"] }
uuid7 = { version = "0.7.2" }
log = "0.4.20"

Expand All @@ -28,4 +28,6 @@ reqwest = "0.11.24"
tokio = { version = "1.35.1", features = ["full"] }
async-trait = "0.1.77"

sqlx = { version = "0.7.3", features = [ "runtime-tokio", "tls-rustls", "macros", "postgres", "chrono"] }
# If you're updating sqlx, make sure that chrono version below is the same as the one in sqlx
sqlx = { version = "0.7.3", features = [ "runtime-tokio", "tls-rustls", "macros", "postgres", "chrono"] }
chrono = { version = "0.4.22", features = ["serde"] }
1 change: 1 addition & 0 deletions database/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
sqlx = { workspace = true }
serde = { workspace = true }
ts-rs = { workspace = true }
tokio = { workspace = true }
dotenvy = { workspace = true }
anyhow = { workspace = true }
Expand Down
3 changes: 3 additions & 0 deletions database/bindings/Subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export interface Subscription { subscription_type: string, valid_from: bigint, valid_till: bigint, }
4 changes: 2 additions & 2 deletions database/migrations/0004_registered_apps.sql
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
CREATE TABLE registered_apps(
team_id TEXT NOT NULL REFERENCES team(team_id) ON DELETE CASCADE,
app_id TEXT NOT NULL UNIQUE,
app_name TEXT NOT NULL,
app_name TEXT NOT NULL UNIQUE,
whitelisted_domains TEXT [] NOT NULL,
ack_public_keys TEXT [] NOT NULL,
email TEXT,
registration_timestamp BIGINT NOT NULL,
registration_timestamp TIMESTAMPTZ NOT NULL,
pass_hash TEXT
);

Expand Down
16 changes: 8 additions & 8 deletions database/src/aggregated_views_queries/requests_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ mod test {
consts::DAY_IN_SECONDS, request_status::RequestStatus, session_type::SessionType,
},
tables::{
registered_app::table_struct::RegisteredApp, requests::table_struct::Request,
sessions::table_struct::DbNcSession,
registered_app::table_struct::DbRegisteredApp, requests::table_struct::Request,
sessions::table_struct::DbNcSession, utils::to_microsecond_precision,
},
};
use sqlx::types::chrono::{DateTime, Utc};
Expand Down Expand Up @@ -199,7 +199,7 @@ mod test {
network: "test_network".to_string(),
client_profile_id: None,
client: None,
session_open_timestamp: DateTime::from(Utc::now()),
session_open_timestamp: to_microsecond_precision(&Utc::now()),
session_close_timestamp: None,
};

Expand Down Expand Up @@ -236,7 +236,7 @@ mod test {
app_id: app_id.to_string(),
session_id: "test_session_id".to_string(),
network: "test_network".to_string(),
creation_timestamp: creation_time,
creation_timestamp: to_microsecond_precision(&creation_time),
request_status: status,
request_type: "test_request_type".to_string(),
};
Expand Down Expand Up @@ -311,15 +311,15 @@ mod test {
// Test missing success due to all requests having pending status
// Add new app to have a "clean" state
let second_app_id = "test_app_id2".to_string();
let app = RegisteredApp {
let app = DbRegisteredApp {
team_id: team_id.clone(),
app_id: second_app_id.to_string(),
app_name: "test_app_name".to_string(),
whitelisted_domains: vec!["test_domain".to_string()],
subscription: None,
ack_public_keys: vec!["test_key".to_string()],
email: None,
registration_timestamp: 0,
registration_timestamp: to_microsecond_precision(&Utc::now()),
pass_hash: None,
};
db_arc.register_new_app(&app).await.unwrap();
Expand All @@ -341,7 +341,7 @@ mod test {
network: "test_network".to_string(),
client_profile_id: None,
client: None,
session_open_timestamp: DateTime::from(Utc::now()),
session_open_timestamp: to_microsecond_precision(&Utc::now()),
session_close_timestamp: None,
};

Expand All @@ -365,7 +365,7 @@ mod test {
app_id: app_id.to_string(),
session_id: "test_session_id".to_string(),
network: "test_network".to_string(),
creation_timestamp: creation_time,
creation_timestamp: to_microsecond_precision(&creation_time),
request_status: RequestStatus::Pending,
request_type: "test_request_type".to_string(),
};
Expand Down
5 changes: 4 additions & 1 deletion database/src/structs/subscription.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use serde::{Deserialize, Serialize};
use sqlx::Type;
use ts_rs::TS;

#[derive(Clone, Debug, Eq, PartialEq, Type)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TS, Type)]
#[ts(export)]
#[sqlx(type_name = "subscription")]
pub struct Subscription {
pub subscription_type: String,
Expand Down
10 changes: 10 additions & 0 deletions database/src/tables/grafana_users/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@ impl Db {
.fetch_one(&self.connection_pool)
.await;
}

pub async fn get_user_by_email(&self, email: &String) -> Result<GrafanaUser, sqlx::Error> {
let query = format!("SELECT * FROM {GRAFANA_USERS_TABLE_NAME} WHERE email = $1");
let typed_query = query_as::<_, GrafanaUser>(&query);

return typed_query
.bind(&email)
.fetch_one(&self.connection_pool)
.await;
}
}
19 changes: 16 additions & 3 deletions database/src/tables/registered_app/select.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::table_struct::{RegisteredApp, REGISTERED_APPS_TABLE_NAME};
use super::table_struct::{DbRegisteredApp, REGISTERED_APPS_TABLE_NAME};
use crate::tables::requests::table_struct::REQUESTS_TABLE_NAME;
use crate::{db::Db, tables::requests::table_struct::Request};
use sqlx::query_as;
Expand All @@ -7,9 +7,9 @@ impl Db {
pub async fn get_registered_app_by_app_id(
&self,
app_id: &String,
) -> Result<RegisteredApp, sqlx::Error> {
) -> Result<DbRegisteredApp, sqlx::Error> {
let query = format!("SELECT * FROM {REGISTERED_APPS_TABLE_NAME} WHERE app_id = $1");
let typed_query = query_as::<_, RegisteredApp>(&query);
let typed_query = query_as::<_, DbRegisteredApp>(&query);

return typed_query
.bind(&app_id)
Expand All @@ -34,4 +34,17 @@ impl Db {
.fetch_all(&self.connection_pool)
.await;
}

pub async fn get_registered_app_by_app_name(
&self,
app_name: &String,
) -> Result<DbRegisteredApp, sqlx::Error> {
let query = format!("SELECT * FROM {REGISTERED_APPS_TABLE_NAME} WHERE app_name = $1");
let typed_query = query_as::<_, DbRegisteredApp>(&query);

return typed_query
.bind(&app_name)
.fetch_one(&self.connection_pool)
.await;
}
}
17 changes: 10 additions & 7 deletions database/src/tables/registered_app/table_struct.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
use crate::structs::subscription::Subscription;
use sqlx::{postgres::PgRow, FromRow, Row};
use sqlx::{
postgres::PgRow,
types::chrono::{DateTime, Utc},
FromRow, Row,
};

pub const REGISTERED_APPS_TABLE_NAME: &str = "registered_apps";
pub const REGISTERED_APPS_KEYS: &str = "team_id, app_id, app_name, whitelisted_domains, ack_public_keys, email, registration_timestamp, pass_hash";

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RegisteredApp {
pub struct DbRegisteredApp {
pub team_id: String,
pub app_id: String,
pub app_name: String,
pub whitelisted_domains: Vec<String>,
pub subscription: Option<Subscription>,
pub ack_public_keys: Vec<String>,
pub email: Option<String>,
pub registration_timestamp: u64,
pub registration_timestamp: DateTime<Utc>,
pub pass_hash: Option<String>,
}

impl FromRow<'_, PgRow> for RegisteredApp {
impl FromRow<'_, PgRow> for DbRegisteredApp {
fn from_row(row: &sqlx::postgres::PgRow) -> std::result::Result<Self, sqlx::Error> {
let registration_timestamp: i64 = row.get("registration_timestamp");
Ok(RegisteredApp {
Ok(DbRegisteredApp {
team_id: row.get("team_id"),
app_id: row.get("app_id"),
app_name: row.get("app_name"),
Expand All @@ -29,7 +32,7 @@ impl FromRow<'_, PgRow> for RegisteredApp {
subscription: None,
ack_public_keys: row.get("ack_public_keys"),
email: row.get("email"),
registration_timestamp: registration_timestamp as u64,
registration_timestamp: row.get("registration_timestamp"),
pass_hash: row.get("pass_hash"),
})
}
Expand Down
10 changes: 5 additions & 5 deletions database/src/tables/registered_app/update.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use super::table_struct::{RegisteredApp, REGISTERED_APPS_KEYS, REGISTERED_APPS_TABLE_NAME};
use super::table_struct::{DbRegisteredApp, REGISTERED_APPS_KEYS, REGISTERED_APPS_TABLE_NAME};
use crate::db::Db;
use sqlx::{query, Transaction};

impl Db {
pub async fn register_new_app(&self, app: &RegisteredApp) -> Result<(), sqlx::Error> {
pub async fn register_new_app(&self, app: &DbRegisteredApp) -> Result<(), sqlx::Error> {
let query_body = format!(
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({REGISTERED_APPS_KEYS}) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)"
);
Expand All @@ -15,7 +15,7 @@ impl Db {
.bind(&app.whitelisted_domains)
.bind(&app.ack_public_keys)
.bind(&app.email)
.bind(&(app.registration_timestamp as i64))
.bind(&app.registration_timestamp)
.bind(&app.pass_hash)
.execute(&self.connection_pool)
.await;
Expand All @@ -29,7 +29,7 @@ impl Db {
pub async fn register_new_app_within_tx(
&self,
tx: &mut Transaction<'_, sqlx::Postgres>,
app: &RegisteredApp,
app: &DbRegisteredApp,
) -> Result<(), sqlx::Error> {
let query_body = format!(
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({}) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
Expand All @@ -43,7 +43,7 @@ impl Db {
.bind(&app.whitelisted_domains)
.bind(&app.ack_public_keys)
.bind(&app.email)
.bind(&(app.registration_timestamp as i64))
.bind(&app.registration_timestamp)
.bind(&app.pass_hash)
.execute(&mut **tx)
.await;
Expand Down
2 changes: 1 addition & 1 deletion database/src/tables/session_public_keys/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ mod tests {

// Create Public key
let mut tx = db.connection_pool.begin().await.unwrap();
let (client_profile_id, public_key) = db
let (client_profile_id, _public_key) = db
.handle_public_keys_entries(&mut tx, &vec![public_key_str.clone()])
.await
.unwrap();
Expand Down
27 changes: 23 additions & 4 deletions database/src/tables/team/select.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
use super::table_struct::Team;
use crate::db::Db;
use crate::tables::registered_app::table_struct::REGISTERED_APPS_TABLE_NAME;
use crate::tables::team::table_struct::TEAM_TABLE_NAME;
use crate::{db::Db, tables::registered_app::table_struct::DbRegisteredApp};
use sqlx::{query_as, Transaction};

impl Db {
pub async fn get_team_by_team_id(
&self,
tx: Option<&mut Transaction<'_, sqlx::Postgres>>,
team_id: &String,
) -> Result<Team, sqlx::Error> {
) -> Result<Option<Team>, sqlx::Error> {
let query = format!("SELECT * FROM {TEAM_TABLE_NAME} WHERE team_id = $1");
let typed_query = query_as::<_, Team>(&query);

match tx {
Some(tx) => return typed_query.bind(&team_id).fetch_one(&mut **tx).await,
Some(tx) => return typed_query.bind(&team_id).fetch_optional(&mut **tx).await,
None => {
return typed_query
.bind(&team_id)
.fetch_one(&self.connection_pool)
.fetch_optional(&self.connection_pool)
.await
}
}
}

pub async fn get_registered_apps_by_team_id(
&self,
team_id: &String,
) -> Result<Vec<DbRegisteredApp>, sqlx::Error> {
let query = format!(
"SELECT r.* FROM {REGISTERED_APPS_TABLE_NAME} r
INNER JOIN team t ON r.team_id = t.team_id
WHERE t.team_id = $1
ORDER BY t.registration_timestamp DESC"
);
let typed_query = query_as::<_, DbRegisteredApp>(&query);

return typed_query
.bind(&team_id)
.fetch_all(&self.connection_pool)
.await;
}
}
16 changes: 8 additions & 8 deletions database/src/tables/team/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
db::Db,
structs::subscription::Subscription,
tables::{
registered_app::table_struct::RegisteredApp,
registered_app::table_struct::DbRegisteredApp,
team::table_struct::{Team, TEAM_TABLE_NAME},
user_app_privileges::table_struct::UserAppPrivilege,
},
Expand Down Expand Up @@ -55,7 +55,7 @@ impl Db {
pub async fn setup_team(
&self,
team: &Team,
app: &RegisteredApp,
app: &DbRegisteredApp,
admin: &UserAppPrivilege,
) -> Result<(), sqlx::Error> {
// Start a transaction
Expand Down Expand Up @@ -96,9 +96,9 @@ mod tests {
use crate::{
structs::privelage_level::PrivilegeLevel,
tables::{
grafana_users::table_struct::GrafanaUser, registered_app::table_struct::RegisteredApp,
team::table_struct::Team, user_app_privileges::table_struct::UserAppPrivilege,
utils::to_microsecond_precision,
grafana_users::table_struct::GrafanaUser,
registered_app::table_struct::DbRegisteredApp, team::table_struct::Team,
user_app_privileges::table_struct::UserAppPrivilege, utils::to_microsecond_precision,
},
};
use sqlx::types::chrono::Utc;
Expand Down Expand Up @@ -126,15 +126,15 @@ mod tests {
registration_timestamp: to_microsecond_precision(&Utc::now()),
};

let app = RegisteredApp {
let app = DbRegisteredApp {
app_id: "test_app_id".to_string(),
team_id: "test_team_id".to_string(),
app_name: "test_app_name".to_string(),
ack_public_keys: vec!["test_ack_public_key".to_string()],
whitelisted_domains: vec!["test_whitelisted_domain".to_string()],
email: None,
pass_hash: None,
registration_timestamp: 0,
registration_timestamp: to_microsecond_precision(&Utc::now()),
subscription: None,
};

Expand All @@ -148,7 +148,7 @@ mod tests {
db.setup_team(&team, &app, &admin_privilege).await.unwrap();

let team_result = db.get_team_by_team_id(None, &team.team_id).await.unwrap();
assert_eq!(team_result, team);
assert_eq!(team_result, Some(team));

let admin_result = db.get_user_by_user_id(&admin.user_id).await.unwrap();
assert_eq!(admin_result, admin);
Expand Down
Loading

0 comments on commit d21eb27

Please sign in to comment.