diff --git a/trifid-api/src/main.rs b/trifid-api/src/main.rs index 12365dd..e3f7c7f 100644 --- a/trifid-api/src/main.rs +++ b/trifid-api/src/main.rs @@ -96,6 +96,7 @@ async fn main() -> Result<(), Box> { .service(routes::v1::roles::update_role_request) .service(routes::v1::trifid::trifid_extensions) .service(routes::v1::hosts::get_hosts) + .service(routes::v1::hosts::create_hosts_request) }).bind(CONFIG.server.bind)?.run().await?; Ok(()) diff --git a/trifid-api/src/routes/v1/hosts.rs b/trifid-api/src/routes/v1/hosts.rs index 04a783d..c047638 100644 --- a/trifid-api/src/routes/v1/hosts.rs +++ b/trifid-api/src/routes/v1/hosts.rs @@ -18,19 +18,27 @@ // This endpoint has full parity with the original API. It has been recreated from the original API documentation. // This endpoint is considered done. No major features should be added or removed, unless it fixes bugs. // This endpoint requires the `definednetworking` extension to be enabled to be used. +// +//#POST /v1/hosts t+parity:full t+type:documented t+status:done t+feature:definednetworking +// This endpoint has full parity with the original API. It has been recreated from the original API documentation. +// This endpoint is considered done. No major features should be added or removed, unless it fixes bugs. +// This endpoint requires the `definednetworking` extension to be enabled to be used. -use std::net::SocketAddrV4; +use std::net::{Ipv4Addr, SocketAddrV4}; use std::str::FromStr; -use actix_web::{HttpRequest, HttpResponse, get}; -use actix_web::web::{Data, Query}; +use std::time::{SystemTime, UNIX_EPOCH}; +use actix_web::{HttpRequest, HttpResponse, get, post}; +use actix_web::web::{Data, Json, Query}; +use chrono::{TimeZone, Utc}; use log::error; -use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, QueryOrder, PaginatorTrait}; +use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, QueryOrder, PaginatorTrait, IntoActiveModel, ActiveModelTrait}; use serde::{Serialize, Deserialize}; use trifid_api_entities::entity::{host, host_static_address, network, organization}; use crate::AppState; use crate::auth_tokens::{enforce_2fa, enforce_api_token, TokenInfo}; use crate::cursor::Cursor; use crate::error::{APIError, APIErrorsResponse}; +use crate::tokens::random_id; #[derive(Serialize, Deserialize)] pub struct ListHostsRequestOpts { @@ -112,7 +120,7 @@ fn page_default() -> u64 { 25 } #[get("/v1/hosts")] pub async fn get_hosts(opts: Query, req_info: HttpRequest, db: Data) -> HttpResponse { - // For this endpoint, you either need to be a fully authenticated user OR a token with roles:list + // For this endpoint, you either need to be a fully authenticated user OR a token with hosts:list let session_info = enforce_2fa(&req_info, &db.conn).await.unwrap_or(TokenInfo::NotPresent); let api_token_info = enforce_api_token(&req_info, &["hosts:list"], &db.conn).await.unwrap_or(TokenInfo::NotPresent); @@ -231,7 +239,7 @@ pub async fn get_hosts(opts: Query, req_info: HttpRequest, } }; - let host_pages = host::Entity::find().filter(host::Column::Network.eq(net_id)).order_by_asc(host::Column::CreatedAt).paginate(&db.conn, opts.page_size); + let host_pages = host::Entity::find().filter(host::Column::Network.eq(&net_id)).order_by_asc(host::Column::CreatedAt).paginate(&db.conn, opts.page_size); let total = match host_pages.num_items().await { Ok(r) => r, @@ -308,17 +316,16 @@ pub async fn get_hosts(opts: Query, req_info: HttpRequest, name: u.name, ip_address: u.ip, static_addresses: ips.iter().map(|u| SocketAddrV4::from_str(&u.address).unwrap()).collect(), - listen_port: u.listen_port as u16, - is_lighthouse: false, - is_relay: false, - created_at: "".to_string(), - is_blocked: false, + is_lighthouse: u.is_lighthouse, + is_relay: u.is_relay, + created_at: Utc.timestamp_opt(u.created_at, 0).unwrap().format("%Y-%m-%dT%H-%M-%S%.3fZ").to_string(), + is_blocked: u.is_blocked, metadata: HostResponseMetadata { - last_seen_at: None, - version: "".to_string(), - platform: "".to_string(), - update_available: false, + last_seen_at: Some(Utc.timestamp_opt(u.last_seen_at, 0).unwrap().format("%Y-%m-%dT%H-%M-%S%.3fZ").to_string()), + version: u.last_version.to_string(), + platform: u.last_platform, + update_available: u.last_out_of_date, }, }) } @@ -355,4 +362,263 @@ pub async fn get_hosts(opts: Query, req_info: HttpRequest, } else { None }, }, }) +} + +#[derive(Serialize, Deserialize)] +pub struct CreateHostRequest { + pub name: String, + #[serde(rename = "networkID")] + pub network_id: String, + #[serde(rename = "roleID", default)] + pub role_id: Option, + #[serde(rename = "ipAddress")] + pub ip_address: Ipv4Addr, + #[serde(rename = "staticAddresses", default)] + pub static_addresses: Vec, + #[serde(rename = "listenPort")] + pub listen_port: u16, + #[serde(rename = "isLighthouse")] + pub is_lighthouse: bool, + #[serde(rename = "isRelay")] + pub is_relay: bool +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct CreateHostResponse { + pub data: HostResponse, + pub metadata: CreateHostResponseMetadata +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct CreateHostResponseMetadata {} + +#[post("/v1/hosts")] +pub async fn create_hosts_request(req: Json, req_info: HttpRequest, db: Data) -> HttpResponse { + // For this endpoint, you either need to be a fully authenticated user OR a token with hosts:create + let session_info = enforce_2fa(&req_info, &db.conn).await.unwrap_or(TokenInfo::NotPresent); + let api_token_info = enforce_api_token(&req_info, &["hosts:create"], &db.conn).await.unwrap_or(TokenInfo::NotPresent); + + // If neither are present, throw an error + if matches!(session_info, TokenInfo::NotPresent) && matches!(api_token_info, TokenInfo::NotPresent) { + return HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_UNAUTHORIZED".to_string(), + message: "This endpoint requires either a fully authenticated user or a token with the hosts:create scope".to_string(), + path: None, + } + ], + }) + } + + // If both are present, throw an error + if matches!(session_info, TokenInfo::AuthToken(_)) && matches!(api_token_info, TokenInfo::ApiToken(_)) { + return HttpResponse::BadRequest().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_AMBIGUOUS_AUTHENTICATION".to_string(), + message: "Both a user token and an API token with the proper scope was provided. Please only provide one.".to_string(), + path: None + } + ], + }) + } + + + let org_id = match api_token_info { + TokenInfo::ApiToken(tkn) => tkn.organization, + _ => { + // we have a session token, which means we have to do a db request to get the organization that this user owns + let user = match session_info { + TokenInfo::AuthToken(tkn) => tkn.session_info.user, + _ => unreachable!() + }; + + let org = match organization::Entity::find().filter(organization::Column::Owner.eq(user.id)).one(&db.conn).await { + Ok(r) => r, + Err(e) => { + error!("database error: {}", e); + return HttpResponse::InternalServerError().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_DB_ERROR".to_string(), + message: "There was an error performing the database request, please try again later.".to_string(), + path: None, + } + ], + }); + } + }; + + if let Some(org) = org { + org.id + } else { + return HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_NO_ORG".to_string(), + message: "This user does not own any organizations. Try using an API token instead.".to_string(), + path: None + } + ], + }) + } + } + }; + + let net_id; + + let net = match network::Entity::find().filter(network::Column::Organization.eq(&org_id)).one(&db.conn).await { + Ok(r) => r, + Err(e) => { + error!("database error: {}", e); + return HttpResponse::InternalServerError().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_DB_ERROR".to_string(), + message: "There was an error performing the database request, please try again later.".to_string(), + path: None, + } + ], + }); + } + }; + + if let Some(net) = net { + net_id = net.id; + } else { + return HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_NO_NET".to_string(), + message: "This user does not own any networks. Try using an API token instead.".to_string(), + path: None + } + ], + }) + } + + if net_id != req.network_id { + return HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_WRONG_NET".to_string(), + message: "The network on the request does not match the network associated with this token or user.".to_string(), + path: None + } + ], + }) + } + + if req.is_lighthouse && req.is_relay { + return HttpResponse::BadRequest().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_CANNOT_BE_RELAY_AND_LIGHTHOUSE".to_string(), + message: "A host cannot be a relay and a lighthouse at the same time.".to_string(), + path: None + } + ], + }) + } + + if req.is_lighthouse || req.is_relay && req.static_addresses.is_empty() { + return HttpResponse::BadRequest().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_NEEDS_STATIC_ADDR".to_string(), + message: "A relay or lighthouse requires at least one static address.".to_string(), + path: None + } + ], + }) + } + + let new_host_model = host::Model { + id: random_id("host"), + name: req.name.clone(), + network: net_id.clone(), + role: req.role_id.clone().unwrap_or("".to_string()), + ip: req.ip_address.to_string(), + listen_port: req.listen_port as i32, + is_lighthouse: req.is_lighthouse, + is_relay: req.is_relay, + counter: 0, + created_at: SystemTime::now().duration_since(UNIX_EPOCH).expect("time went backwards").as_secs() as i64, + is_blocked: false, + last_seen_at: 0, + last_version: 0, + last_platform: "".to_string(), + last_out_of_date: false, + }; + let static_addresses: Vec = req.static_addresses.iter().map(|u| { + host_static_address::Model { + id: random_id("hsaddress"), + host: new_host_model.id.clone(), + address: u.to_string(), + } + }).collect(); + + let new_host_model_clone = new_host_model.clone(); + let static_addresses_clone = static_addresses.clone(); + + let new_host_active_model = new_host_model.into_active_model(); + match new_host_active_model.insert(&db.conn).await { + Ok(_) => (), + Err(e) => { + error!("database error: {}", e); + return HttpResponse::InternalServerError().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_DB_ERROR".to_string(), + message: "There was an error creating the new host. Please try again later".to_string(), + path: None + } + ], + }) + } + } + + for rule in &static_addresses_clone { + let active_model = rule.clone().into_active_model(); + match active_model.insert(&db.conn).await { + Ok(_) => (), + Err(e) => { + error!("database error: {}", e); + return HttpResponse::InternalServerError().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_DB_ERROR".to_string(), + message: "There was an error creating the new host. Please try again later".to_string(), + path: None + } + ], + }) + } + } + } + + HttpResponse::Ok().json(CreateHostResponse { + data: HostResponse { + id: new_host_model_clone.id, + organization_id: org_id, + network_id: net_id, + role_id: new_host_model_clone.role, + name: new_host_model_clone.name, + ip_address: req.ip_address.to_string(), + static_addresses: req.static_addresses.clone(), + listen_port: req.listen_port, + is_lighthouse: req.is_lighthouse, + is_relay: req.is_relay, + created_at: "".to_string(), + is_blocked: false, + metadata: HostResponseMetadata { + last_seen_at: Some(Utc.timestamp_opt(new_host_model_clone.last_seen_at, 0).unwrap().format("%Y-%m-%dT%H-%M-%S%.3fZ").to_string()), + version: new_host_model_clone.last_version.to_string(), + platform: new_host_model_clone.last_platform, + update_available: new_host_model_clone.last_out_of_date, + }, + }, + metadata: CreateHostResponseMetadata {}, + }) } \ No newline at end of file diff --git a/trifid-api/trifid_api_entities/src/entity/host.rs b/trifid-api/trifid_api_entities/src/entity/host.rs index 6dc6594..73c4cf7 100644 --- a/trifid-api/trifid_api_entities/src/entity/host.rs +++ b/trifid-api/trifid_api_entities/src/entity/host.rs @@ -16,6 +16,11 @@ pub struct Model { pub is_relay: bool, pub counter: i32, pub created_at: i64, + pub is_blocked: bool, + pub last_seen_at: i64, + pub last_version: i32, + pub last_platform: String, + pub last_out_of_date: bool, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/trifid-api/trifid_api_migration/src/m20230427_170037_create_table_hosts.rs b/trifid-api/trifid_api_migration/src/m20230427_170037_create_table_hosts.rs index c867ef6..fc6bfe5 100644 --- a/trifid-api/trifid_api_migration/src/m20230427_170037_create_table_hosts.rs +++ b/trifid-api/trifid_api_migration/src/m20230427_170037_create_table_hosts.rs @@ -21,6 +21,11 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Host::IsRelay).boolean().not_null()) .col(ColumnDef::new(Host::Counter).unsigned().not_null()) .col(ColumnDef::new(Host::CreatedAt).big_integer().not_null()) + .col(ColumnDef::new(Host::IsBlocked).boolean().not_null()) + .col(ColumnDef::new(Host::LastSeenAt).big_integer().not_null()) + .col(ColumnDef::new(Host::LastVersion).integer().not_null()) + .col(ColumnDef::new(Host::LastPlatform).string().not_null()) + .col(ColumnDef::new(Host::LastOutOfDate).boolean().not_null()) .foreign_key( ForeignKey::create() .from(Host::Table, Host::Network) @@ -67,5 +72,10 @@ pub enum Host { IsLighthouse, IsRelay, Counter, - CreatedAt + CreatedAt, + IsBlocked, + LastSeenAt, + LastVersion, + LastPlatform, + LastOutOfDate } diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key.rs new file mode 100644 index 0000000..04aa795 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key.rs @@ -0,0 +1,41 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "api_key")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(unique)] + pub key: String, + pub organization: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::api_key_scope::Entity")] + ApiKeyScope, + #[sea_orm( + belongs_to = "super::organization::Entity", + from = "Column::Organization", + to = "super::organization::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Organization, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ApiKeyScope.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Organization.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key_scope.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key_scope.rs new file mode 100644 index 0000000..1deffbc --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/api_key_scope.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "api_key_scope")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub scope: String, + pub api_key: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::api_key::Entity", + from = "Column::ApiKey", + to = "super::api_key::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + ApiKey, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ApiKey.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/auth_token.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/auth_token.rs new file mode 100644 index 0000000..db14039 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/auth_token.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "auth_token")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub user: String, + pub expires_on: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::User", + to = "super::user::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/firewall_rule.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/firewall_rule.rs new file mode 100644 index 0000000..6a8c64f --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/firewall_rule.rs @@ -0,0 +1,38 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "firewall_rule")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub role: String, + pub protocol: String, + pub description: String, + pub allowed_role_id: Option, + pub port_range_from: i32, + pub port_range_to: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::role::Entity", + from = "Column::AllowedRoleId", + to = "super::role::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Role2, + #[sea_orm( + belongs_to = "super::role::Entity", + from = "Column::Role", + to = "super::role::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + Role1, +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/magic_link.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/magic_link.rs new file mode 100644 index 0000000..1707d7e --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/magic_link.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "magic_link")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub user: String, + pub expires_on: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::User", + to = "super::user::Column::Id", + on_update = "Cascade", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/mod.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/mod.rs new file mode 100644 index 0000000..41382c0 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/mod.rs @@ -0,0 +1,16 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +pub mod prelude ; + +pub mod api_key ; +pub mod api_key_scope ; +pub mod auth_token ; +pub mod firewall_rule ; +pub mod magic_link ; +pub mod network ; +pub mod organization ; +pub mod role ; +pub mod session_token ; +pub mod signing_ca ; +pub mod totp_authenticator ; +pub mod user ; \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/network.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/network.rs new file mode 100644 index 0000000..832f0e8 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/network.rs @@ -0,0 +1,15 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "network")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , pub cidr : String , # [sea_orm (unique)] pub organization : String , # [sea_orm (unique)] pub signing_ca : String , pub created_at : i64 , pub name : String , pub lighthouses_as_relays : bool , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (belongs_to = "super::organization::Entity" , from = "Column::Organization" , to = "super::organization::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] Organization , # [sea_orm (belongs_to = "super::signing_ca::Entity" , from = "Column::SigningCa" , to = "super::signing_ca::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] SigningCa , } + +impl Related < super :: organization :: Entity > for Entity { fn to () -> RelationDef { Relation :: Organization . def () } } + +impl Related < super :: signing_ca :: Entity > for Entity { fn to () -> RelationDef { Relation :: SigningCa . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/organization.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/organization.rs new file mode 100644 index 0000000..fdaf8e3 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/organization.rs @@ -0,0 +1,19 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "organization")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , pub name : String , # [sea_orm (unique)] pub owner : String , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (has_many = "super::api_key::Entity")] ApiKey , # [sea_orm (has_one = "super::network::Entity")] Network , # [sea_orm (has_many = "super::role::Entity")] Role , # [sea_orm (belongs_to = "super::user::Entity" , from = "Column::Owner" , to = "super::user::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] User , } + +impl Related < super :: api_key :: Entity > for Entity { fn to () -> RelationDef { Relation :: ApiKey . def () } } + +impl Related < super :: network :: Entity > for Entity { fn to () -> RelationDef { Relation :: Network . def () } } + +impl Related < super :: role :: Entity > for Entity { fn to () -> RelationDef { Relation :: Role . def () } } + +impl Related < super :: user :: Entity > for Entity { fn to () -> RelationDef { Relation :: User . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/prelude.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/prelude.rs new file mode 100644 index 0000000..2314fbc --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/prelude.rs @@ -0,0 +1,14 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + +pub use super :: api_key :: Entity as ApiKey ; +pub use super :: api_key_scope :: Entity as ApiKeyScope ; +pub use super :: auth_token :: Entity as AuthToken ; +pub use super :: firewall_rule :: Entity as FirewallRule ; +pub use super :: magic_link :: Entity as MagicLink ; +pub use super :: network :: Entity as Network ; +pub use super :: organization :: Entity as Organization ; +pub use super :: role :: Entity as Role ; +pub use super :: session_token :: Entity as SessionToken ; +pub use super :: signing_ca :: Entity as SigningCa ; +pub use super :: totp_authenticator :: Entity as TotpAuthenticator ; +pub use super :: user :: Entity as User ; \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/role.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/role.rs new file mode 100644 index 0000000..9ce3a13 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/role.rs @@ -0,0 +1,13 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "role")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , # [sea_orm (unique)] pub name : String , pub description : String , pub organization : String , pub created_at : i64 , pub modified_at : i64 , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (belongs_to = "super::organization::Entity" , from = "Column::Organization" , to = "super::organization::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] Organization , } + +impl Related < super :: organization :: Entity > for Entity { fn to () -> RelationDef { Relation :: Organization . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/session_token.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/session_token.rs new file mode 100644 index 0000000..23d37ba --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/session_token.rs @@ -0,0 +1,13 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "session_token")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , pub user : String , pub expires_on : i64 , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (belongs_to = "super::user::Entity" , from = "Column::User" , to = "super::user::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] User , } + +impl Related < super :: user :: Entity > for Entity { fn to () -> RelationDef { Relation :: User . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/signing_ca.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/signing_ca.rs new file mode 100644 index 0000000..72516a6 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/signing_ca.rs @@ -0,0 +1,13 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "signing_ca")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , pub organization : String , pub cert : String , # [sea_orm (unique)] pub key : String , pub expires : i64 , # [sea_orm (unique)] pub nonce : String , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (has_one = "super::network::Entity")] Network , } + +impl Related < super :: network :: Entity > for Entity { fn to () -> RelationDef { Relation :: Network . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/totp_authenticator.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/totp_authenticator.rs new file mode 100644 index 0000000..630c391 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/totp_authenticator.rs @@ -0,0 +1,13 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "totp_authenticator")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , # [sea_orm (unique)] pub secret : String , # [sea_orm (unique)] pub url : String , pub verified : bool , pub expires_on : i64 , # [sea_orm (unique)] pub user : String , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (belongs_to = "super::user::Entity" , from = "Column::User" , to = "super::user::Column::Id" , on_update = "Cascade" , on_delete = "Cascade" ,)] User , } + +impl Related < super :: user :: Entity > for Entity { fn to () -> RelationDef { Relation :: User . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file diff --git a/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/user.rs b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/user.rs new file mode 100644 index 0000000..23fc564 --- /dev/null +++ b/trifid-api/trifid_api_migration/trifid_api_entities/src/entity/user.rs @@ -0,0 +1,21 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 + + + +use sea_orm :: entity :: prelude :: * ; + +# [derive (Clone , Debug , PartialEq , DeriveEntityModel , Eq)] # [sea_orm (table_name = "user")] pub struct Model { # [sea_orm (primary_key , auto_increment = false)] pub id : String , # [sea_orm (unique)] pub email : String , } + +# [derive (Copy , Clone , Debug , EnumIter , DeriveRelation)] pub enum Relation { # [sea_orm (has_many = "super::auth_token::Entity")] AuthToken , # [sea_orm (has_many = "super::magic_link::Entity")] MagicLink , # [sea_orm (has_one = "super::organization::Entity")] Organization , # [sea_orm (has_many = "super::session_token::Entity")] SessionToken , # [sea_orm (has_one = "super::totp_authenticator::Entity")] TotpAuthenticator , } + +impl Related < super :: auth_token :: Entity > for Entity { fn to () -> RelationDef { Relation :: AuthToken . def () } } + +impl Related < super :: magic_link :: Entity > for Entity { fn to () -> RelationDef { Relation :: MagicLink . def () } } + +impl Related < super :: organization :: Entity > for Entity { fn to () -> RelationDef { Relation :: Organization . def () } } + +impl Related < super :: session_token :: Entity > for Entity { fn to () -> RelationDef { Relation :: SessionToken . def () } } + +impl Related < super :: totp_authenticator :: Entity > for Entity { fn to () -> RelationDef { Relation :: TotpAuthenticator . def () } } + +impl ActiveModelBehavior for ActiveModel { } \ No newline at end of file