Skip to content

Commit

Permalink
fix: conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
zerj9 committed Dec 12, 2024
1 parent 3ff2978 commit 769c124
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 244 deletions.
28 changes: 18 additions & 10 deletions DATA_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@
This is the data model used for the Gridwalk application. Currently, only DynamoDB is supported, with plans to add support for other databases in the future.

## DynamoDB (Single Table)
| PK | SK | Attributes | GSIs |
|---|---|---|---|
| USER#<user_id> | USER#<user_id> | user_name<br>created_at<br>primary_email | |
| EMAIL#<email_address> | EMAIL#<email_address> | user_id | |
| WSP#<workspace_id> | WSP#<workspace_id> | workspace_name<br>workspace_owner<br>created_at | GSI_WORKSPACE_BY_NAME<br>workspace_name: <workspace_name> |
| WSP#<workspace_id> | USER#<user_id> | user_role<br>joined_at<br>user_id | GSI_USER_ID<br>user_id: <user_id> |
| WSP#<workspace_id> | CON#<connection_id> | name<br>connector_type<br>created_by<br>pg_host<br>pg_port<br>pg_db<br>pg_username<br>pg_password | |
| WSP#<workspace_id> | LAYER#<layer_name> | name<br>connection_id<br>uploaded_by<br>created_at | |
| WSP#<workspace_id> | PROJ#<project_id> | name<br>owner<br>created_at | |
| SESSION#<session_id> | SESSION#<session_id> | user_id<br>created_at | GSI_USER<br>user_id: <user_id> |

| Entity | PK | SK | user_id | wsp_id | con_id | Attributes |
|-------------------|---------------|---------------------------------|---------|--------|---------|----------------------------------------|
| User | USER#{id} | USER#{id} | | | | created_at, active |
| User Global Role | USER#{id} | ROLE#[SUPER/SUPPORT/READ] | | | | |
| Email | EMAIL#{email} | EMAIL#{email} | &check; | | | [primary, secondary] |
| Session | SESSION#{id} | SESSION#{id} | &check; | | | created_at, login_ip |
| | | | | | | |
| Connection | CON#{id/name} | CON#{id/name} | | | | name, connector_type, connector_config |
| Connection Access | WSP#{id} | CONACC#{id/name}#{wsp_id}:level | | | &check; | |
| | | | | | | |
| Workspace | WSP#{id} | WSP#{id} | | | | name, owner, created_at, active |
| Workspace Member | WSP#{id} | USER#{id} | &check; | | | role, joined_at |
| Layer | WSP#{id} | LAYER#{layer_name} | | | &check; | created_by, created_at |
| Project | WSP#{id} | PROJ#{id} | | | | name, owner, created_at |

## Notes
- The Connection entity may have an ID or a name. A Connection with a name is used for global connectors created by the system administrators. A Connection with an ID is used for user-created connectors.
78 changes: 60 additions & 18 deletions gridwalk-backend/src/core/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ use tokio_postgres::NoTls;

use crate::data::Database;

use super::Workspace;

// TODO: Switch connector_type/postgis_uri to enum to support other connectors
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Connection {
pub id: String,
pub workspace_id: String,
pub name: String,
pub created_by: String,
pub connector_type: String,
pub config: PostgresConnection,
}
Expand All @@ -26,27 +26,68 @@ impl Connection {
Ok(())
}

pub async fn from_id(
database: &Arc<dyn Database>,
workspace_id: &str,
connection_id: &str,
) -> Result<Self> {
let con = database
.get_workspace_connection(workspace_id, connection_id)
.await?;
pub async fn from_name(database: &Arc<dyn Database>, connection_name: &str) -> Result<Self> {
let con = database.get_connection(connection_name).await?;
Ok(con)
}

pub async fn get_all(
database: &Arc<dyn Database>,
workspace_id: &str,
) -> Result<Vec<Connection>> {
let connections = database.get_workspace_connections(workspace_id).await?;
Ok(connections)
//pub async fn delete(&self, database: &Arc<dyn Database>) -> Result<()> {
// database.delete_workspace_connection(self).await
//}
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ConnectionAccess {
pub connection_id: String,
pub workspace_id: String,
pub access_config: ConnectionAccessConfig,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum ConnectionAccessConfig {
Admin(String),
ReadWrite(String),
ReadOnly(String),
}

impl ConnectionAccessConfig {
pub fn from_str(variant: &str, path: String) -> Result<Self, String> {
match variant.to_lowercase().as_str() {
"admin" => Ok(ConnectionAccessConfig::Admin(path)),
"readwrite" | "read_write" => Ok(ConnectionAccessConfig::ReadWrite(path)),
"readonly" | "read_only" => Ok(ConnectionAccessConfig::ReadOnly(path)),
_ => Err(format!("Invalid variant name: {}", variant)),
}
}

pub fn variant_name(&self) -> &'static str {
match self {
ConnectionAccessConfig::Admin(_) => "Admin",
ConnectionAccessConfig::ReadWrite(_) => "ReadWrite",
ConnectionAccessConfig::ReadOnly(_) => "ReadOnly",
}
}

pub fn path(&self) -> &String {
match self {
ConnectionAccessConfig::Admin(v)
| ConnectionAccessConfig::ReadWrite(v)
| ConnectionAccessConfig::ReadOnly(v) => v,
}
}
}

pub async fn delete(&self, database: &Arc<dyn Database>) -> Result<()> {
database.delete_workspace_connection(self).await
impl ConnectionAccess {
pub async fn create_record(self, database: &Arc<dyn Database>) -> Result<()> {
database.create_connection_access(&self).await?;
Ok(())
}

pub async fn get_all(
database: &Arc<dyn Database>,
wsp: &Workspace,
) -> Result<Vec<ConnectionAccess>> {
database.get_accessible_connections(wsp).await
}
}

Expand Down Expand Up @@ -187,6 +228,7 @@ FROM mvt_data;
}
}

// The GeospatialConfig struct and its impl block are used to manage live connections
#[derive(Clone)]
pub struct GeospatialConfig {
sources: Arc<RwLock<HashMap<String, Arc<dyn GeoConnector>>>>,
Expand Down
20 changes: 20 additions & 0 deletions gridwalk-backend/src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ use crate::data::Database;
use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use strum_macros::{Display, EnumString};

#[derive(PartialEq, Debug, Display, EnumString, Clone, Deserialize, Serialize)]
#[strum(serialize_all = "snake_case")]
pub enum GlobalRole {
Super,
Support,
Read,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct User {
pub id: String,
pub email: String,
pub first_name: String,
pub last_name: String,
pub global_role: Option<GlobalRole>,
pub active: bool,
pub created_at: u64,
pub hash: String,
Expand All @@ -20,6 +30,7 @@ pub struct CreateUser {
pub email: String,
pub first_name: String,
pub last_name: String,
pub global_role: Option<GlobalRole>,
pub password: String,
}

Expand Down Expand Up @@ -78,12 +89,14 @@ impl User {
email: create_user.email.to_string(),
first_name: create_user.first_name.to_string(),
last_name: create_user.last_name.to_string(),
global_role: create_user.clone().global_role,
active,
created_at: now,
hash: password_hash,
}
}

<<<<<<< HEAD
pub async fn update_password(
&mut self,
database: &Arc<dyn Database>,
Expand All @@ -103,5 +116,12 @@ impl User {
user.update_password(database, new_password).await?;

Ok(user)
=======
pub async fn check_global_role(&self) -> Option<GlobalRole> {
match &self.global_role {
Some(support_level) => Some(support_level.clone()),
None => None,
}
>>>>>>> c688619 (chore: separate connection record)
}
}
10 changes: 10 additions & 0 deletions gridwalk-backend/src/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::fmt;
use std::str::FromStr;
use std::sync::Arc;

use super::{ConnectionAccess, ConnectionAccessConfig};

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Workspace {
pub id: String,
Expand Down Expand Up @@ -72,6 +74,14 @@ impl Workspace {
// Check for existing org with same name
let db_resp = database.create_workspace(wsp).await;

// Create ConnectionAccess to shared primary db
let connection_access = ConnectionAccess {
connection_id: "primary".to_string(),
workspace_id: wsp.id.clone(),
access_config: ConnectionAccessConfig::ReadWrite(wsp.id.clone()),
};
connection_access.create_record(database).await?;

match db_resp {
Ok(_) => Ok(()),
Err(_) => Err(anyhow!("failed to create workspace")),
Expand Down
13 changes: 5 additions & 8 deletions gridwalk-backend/src/data/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::{
Connection, Layer, Project, Session, User, Workspace, WorkspaceMember, WorkspaceRole,
Connection, ConnectionAccess, Layer, Project, Session, User, Workspace, WorkspaceMember,
WorkspaceRole,
};
use anyhow::Result;
use async_trait::async_trait;
Expand All @@ -25,13 +26,9 @@ pub trait UserStore: Send + Sync + 'static {
async fn get_workspace_members(&self, wsp: &Workspace) -> Result<Vec<WorkspaceMember>>;
async fn remove_workspace_member(&self, org: &Workspace, user: &User) -> Result<()>;
async fn create_connection(&self, connection: &Connection) -> Result<()>;
async fn get_workspace_connection(
&self,
workspace_id: &str,
connection_id: &str,
) -> Result<Connection>;
async fn get_workspace_connections(&self, workspace_id: &str) -> Result<Vec<Connection>>;
async fn delete_workspace_connection(&self, con: &Connection) -> Result<()>;
async fn get_connection(&self, connection_id: &str) -> Result<Connection>;
async fn create_connection_access(&self, ca: &ConnectionAccess) -> Result<()>;
async fn get_accessible_connections(&self, wsp: &Workspace) -> Result<Vec<ConnectionAccess>>;
async fn create_layer(&self, layer: &Layer) -> Result<()>;
async fn create_project(&self, project: &Project) -> Result<()>;
async fn get_workspaces(&self, user: &User) -> Result<Vec<String>>;
Expand Down
Loading

0 comments on commit 769c124

Please sign in to comment.