Skip to content

Commit

Permalink
Merge pull request #125 from nightly-labs/finish-api-tests
Browse files Browse the repository at this point in the history
Finish api tests
  • Loading branch information
Giems authored Mar 13, 2024
2 parents 7de02e3 + 40289c5 commit 8306918
Show file tree
Hide file tree
Showing 29 changed files with 1,196 additions and 89 deletions.
3 changes: 3 additions & 0 deletions database/bindings/PrivilegeLevel.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 type PrivilegeLevel = "Read" | "Edit" | "Admin";
4 changes: 1 addition & 3 deletions database/migrations/0004_registered_apps.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ CREATE TABLE registered_apps(
app_name TEXT NOT NULL,
whitelisted_domains TEXT [] NOT NULL,
ack_public_keys TEXT [] NOT NULL,
email TEXT,
registration_timestamp TIMESTAMPTZ NOT NULL,
pass_hash TEXT
registration_timestamp TIMESTAMPTZ NOT NULL
);

CREATE UNIQUE INDEX app_id_idx ON registered_apps(app_id);
3 changes: 0 additions & 3 deletions database/src/aggregated_views_queries/requests_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,8 @@ mod test {
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: to_microsecond_precision(&Utc::now()),
pass_hash: None,
};
db_arc.register_new_app(&app).await.unwrap();

Expand Down
5 changes: 4 additions & 1 deletion database/src/structs/privilege_level.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(Debug, Clone, Eq, PartialEq, Type)]
#[derive(Debug, Clone, Eq, PartialEq, Type, Serialize, Deserialize, TS)]
#[ts(export)]
#[sqlx(type_name = "privilege_level_enum")]
pub enum PrivilegeLevel {
Read,
Expand Down
11 changes: 2 additions & 9 deletions database/src/tables/registered_app/table_struct.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
use crate::structs::subscription::Subscription;
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";
pub const REGISTERED_APPS_KEYS: &str =
"team_id, app_id, app_name, whitelisted_domains, ack_public_keys, registration_timestamp";

#[derive(Clone, Debug, Eq, PartialEq)]
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: DateTime<Utc>,
pub pass_hash: Option<String>,
}

impl FromRow<'_, PgRow> for DbRegisteredApp {
Expand All @@ -28,12 +25,8 @@ impl FromRow<'_, PgRow> for DbRegisteredApp {
app_id: row.get("app_id"),
app_name: row.get("app_name"),
whitelisted_domains: row.get("whitelisted_domains"),
// TEMP
subscription: None,
ack_public_keys: row.get("ack_public_keys"),
email: row.get("email"),
registration_timestamp: row.get("registration_timestamp"),
pass_hash: row.get("pass_hash"),
})
}
}
8 changes: 2 additions & 6 deletions database/src/tables/registered_app/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use sqlx::{query, Transaction};
impl Db {
pub async fn register_new_app(&self, app: &DbRegisteredApp) -> Result<(), DbError> {
let query_body = format!(
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({REGISTERED_APPS_KEYS}) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)"
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({REGISTERED_APPS_KEYS}) VALUES ($1, $2, $3, $4, $5, $6)"
);

let query_result = query(&query_body)
Expand All @@ -14,9 +14,7 @@ impl Db {
.bind(&app.app_name)
.bind(&app.whitelisted_domains)
.bind(&app.ack_public_keys)
.bind(&app.email)
.bind(&app.registration_timestamp)
.bind(&app.pass_hash)
.execute(&self.connection_pool)
.await;

Expand All @@ -32,7 +30,7 @@ impl Db {
app: &DbRegisteredApp,
) -> Result<(), DbError> {
let query_body = format!(
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({}) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
"INSERT INTO {REGISTERED_APPS_TABLE_NAME} ({}) VALUES ($1, $2, $3, $4, $5, $6)",
REGISTERED_APPS_KEYS
);

Expand All @@ -42,9 +40,7 @@ impl Db {
.bind(&app.app_name)
.bind(&app.whitelisted_domains)
.bind(&app.ack_public_keys)
.bind(&app.email)
.bind(&app.registration_timestamp)
.bind(&app.pass_hash)
.execute(&mut **tx)
.await;

Expand Down
3 changes: 0 additions & 3 deletions database/src/tables/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ pub mod test_utils {
app_id: app_id.clone(),
app_name: "test_app".to_string(),
whitelisted_domains: vec!["localhost".to_string()],
subscription: None,
ack_public_keys: vec!["key".to_string()],
email: None,
pass_hash: None,
registration_timestamp: registration_timestamp,
};

Expand Down
123 changes: 118 additions & 5 deletions database/src/tables/user_app_privileges/select.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
use super::table_struct::UserAppPrivilege;
use crate::db::Db;
use crate::structs::db_error::DbError;
use crate::tables::registered_app::table_struct::REGISTERED_APPS_TABLE_NAME;
use crate::tables::user_app_privileges::table_struct::USER_APP_PRIVILEGES_TABLE_NAME;
use sqlx::query_as;
use crate::{
db::Db,
structs::db_error::DbError,
tables::{
grafana_users::table_struct::GRAFANA_USERS_TABLE_NAME,
registered_app::table_struct::{DbRegisteredApp, REGISTERED_APPS_TABLE_NAME},
team::table_struct::{Team, TEAM_TABLE_NAME},
user_app_privileges::table_struct::USER_APP_PRIVILEGES_TABLE_NAME,
},
};
use sqlx::{query_as, types::chrono::DateTime};
use sqlx::{types::chrono::Utc, Row};
use std::collections::HashMap;

impl Db {
pub async fn get_privilege_by_user_id_and_app_id(
Expand Down Expand Up @@ -89,4 +97,109 @@ impl Db {
.await
.map_err(|e| e.into());
}

pub async fn get_joined_teams_by_user_id(
&self,
user_id: &String,
) -> Result<
Vec<(
Team,
String,
DateTime<Utc>,
Vec<(DbRegisteredApp, UserAppPrivilege)>,
)>,
DbError,
> {
let query = format!(
"WITH RelevantTeams AS (
SELECT DISTINCT t.team_id, t.team_name, t.personal, t.subscription,
t.registration_timestamp, gu.email AS team_admin_email,
gu.user_id AS team_admin_id,
CASE
WHEN t.team_admin_id = $1 THEN t.registration_timestamp
ELSE MAX(uap.creation_timestamp) OVER (PARTITION BY t.team_id)
END as user_joined_team_timestamp
FROM {TEAM_TABLE_NAME} t
LEFT JOIN {REGISTERED_APPS_TABLE_NAME} ra ON t.team_id = ra.team_id
LEFT JOIN {USER_APP_PRIVILEGES_TABLE_NAME} uap ON ra.app_id = uap.app_id AND uap.user_id = $1
JOIN {GRAFANA_USERS_TABLE_NAME} gu ON t.team_admin_id = gu.user_id
WHERE t.team_admin_id = $1 OR uap.user_id = $1
)
SELECT rt.team_id, rt.team_name, rt.personal, rt.subscription, rt.registration_timestamp,
rt.team_admin_email, rt.team_admin_id, ra.app_id, ra.app_name, ra.whitelisted_domains,
ra.ack_public_keys, ra.registration_timestamp AS app_registration_timestamp,
uap.user_id, uap.privilege_level, uap.creation_timestamp AS privilege_creation_timestamp,
rt.user_joined_team_timestamp
FROM RelevantTeams rt
LEFT JOIN {REGISTERED_APPS_TABLE_NAME} ra ON rt.team_id = ra.team_id
LEFT JOIN {USER_APP_PRIVILEGES_TABLE_NAME} uap ON ra.app_id = uap.app_id AND uap.user_id = $1
ORDER BY rt.team_id, ra.app_id"
);

let rows = sqlx::query(&query)
.bind(user_id)
.fetch_all(&self.connection_pool)
.await;

let rows = match rows {
Ok(rows) => rows,
Err(err) => {
return Err(err.into());
}
};

let mut team_app_map: HashMap<
String,
(
Team,
String,
DateTime<Utc>,
Vec<(DbRegisteredApp, UserAppPrivilege)>,
),
> = HashMap::new();

for row in rows {
let team = Team {
team_id: row.get("team_id"),
personal: row.get("personal"),
team_name: row.get("team_name"),
subscription: row.get("subscription"),
registration_timestamp: row.get("registration_timestamp"),
team_admin_id: row.get("team_admin_id"),
};

let admin_email = row.get("team_admin_email");
let user_joined_team_timestamp: DateTime<Utc> = row.get("user_joined_team_timestamp");

let team_id = team.team_id.clone();
let team_entry = team_app_map
.entry(team.team_id.clone())
.or_insert_with(|| (team, admin_email, user_joined_team_timestamp, Vec::new()));

if let Ok(app_id) = row.try_get("app_id") {
if app_id != "" {
// Checking if app_id is present and not an empty string
let app = DbRegisteredApp {
team_id: team_id.clone(),
app_id,
app_name: row.get("app_name"),
whitelisted_domains: row.get("whitelisted_domains"),
ack_public_keys: row.get("ack_public_keys"),
registration_timestamp: row.get("app_registration_timestamp"),
};

let privilege = UserAppPrivilege {
user_id: row.get("user_id"),
app_id: app.app_id.clone(),
privilege_level: row.get("privilege_level"),
creation_timestamp: row.get("privilege_creation_timestamp"),
};

team_entry.3.push((app, privilege));
}
}
}

Ok(team_app_map.into_values().collect())
}
}
9 changes: 3 additions & 6 deletions database/src/tables/user_app_privileges/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ impl Db {
}
}

// Commit the transaction
tx.commit().await?;

Ok(())
}

Expand Down Expand Up @@ -284,10 +287,7 @@ mod tests {
app_id: app_id.clone(),
app_name: format!("test_app_name_{}", i),
team_id: team_id.clone(),
email: None,
pass_hash: None,
registration_timestamp: to_microsecond_precision(&Utc::now()),
subscription: None,
};

db.register_new_app(&app).await.unwrap();
Expand Down Expand Up @@ -323,10 +323,7 @@ mod tests {
app_id: app_id.clone(),
app_name: format!("test_app_name_{}", i),
team_id: team_id.clone(),
email: None,
pass_hash: None,
registration_timestamp: to_microsecond_precision(&Utc::now()),
subscription: None,
};

db.register_new_app(&app).await.unwrap();
Expand Down
3 changes: 3 additions & 0 deletions server/bindings/AppInfo.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 AppInfo { teamId: string, appId: string, appName: string, registeredAt: string, whitelistedDomains: Array<string>, ackPublicKeys: Array<string>, }
2 changes: 1 addition & 1 deletion server/bindings/HttpCloudEndpoint.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type HttpCloudEndpoint = "/register_new_app" | "/register_with_password" | "/login_with_password" | "/register_new_team" | "/add_user_to_team" | "/remove_user_from_team";
export type HttpCloudEndpoint = "/register_new_app" | "/register_with_password" | "/login_with_password" | "/register_new_team" | "/add_user_to_team" | "/remove_user_from_team" | "/get_user_joined_teams";
6 changes: 6 additions & 0 deletions server/bindings/HttpGetUserJoinedTeamsResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AppInfo } from "./AppInfo";
import type { JoinedTeam } from "./JoinedTeam";
import type { UserPrivilege } from "./UserPrivilege";

export interface HttpGetUserJoinedTeamsResponse { teams: Record<string, JoinedTeam>, teams_apps: Record<string, Array<AppInfo>>, user_privileges: Record<string, Record<string, UserPrivilege>>, }
3 changes: 3 additions & 0 deletions server/bindings/JoinedTeam.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 JoinedTeam { teamId: string, teamName: string, creatorEmail: string, createdAt: string, joinedAt: string, personal: boolean, }
4 changes: 4 additions & 0 deletions server/bindings/UserPrivilege.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PrivilegeLevel } from "./PrivilegeLevel";

export interface UserPrivilege { appId: string, grantedAt: string, privilege: PrivilegeLevel, }
2 changes: 1 addition & 1 deletion server/src/bin/nightly-connect-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tracing_subscriber::EnvFilter;

#[tokio::main]
async fn main() {
let filter: EnvFilter = "debug,tower_http=trace,hyper=warn"
let filter: EnvFilter = "debug,sqlx=warn,tower_http=trace,hyper=warn"
.parse()
.expect("filter should parse");

Expand Down
Loading

0 comments on commit 8306918

Please sign in to comment.