-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Initial implementation of products
- Loading branch information
Showing
18 changed files
with
708 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
```mermaid | ||
--- | ||
title: Product Structure | ||
--- | ||
erDiagram | ||
Organization { | ||
int32 id | ||
string name | ||
} | ||
Product { | ||
int32 id | ||
string name | ||
} | ||
ProductVersion { | ||
int32 id | ||
string version | ||
} | ||
Sbom { | ||
uuid id | ||
} | ||
Organization || -- o{ Product : produces | ||
Product || -- o{ ProductVersion : have | ||
ProductVersion || -- || Sbom : describes | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use sea_orm::entity::prelude::*; | ||
|
||
use crate::organization; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "product")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
pub name: String, | ||
pub vendor_id: Option<i32>, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation { | ||
#[sea_orm( | ||
belongs_to = "super::organization::Entity" | ||
from = "Column::VendorId" | ||
to = "super::organization::Column::Id")] | ||
Vendor, | ||
#[sea_orm(has_many = "super::product_version::Entity")] | ||
ProductVersion, | ||
} | ||
|
||
impl Related<organization::Entity> for Entity { | ||
fn to() -> RelationDef { | ||
Relation::Vendor.def() | ||
} | ||
} | ||
|
||
impl Related<super::product_version::Entity> for Entity { | ||
fn to() -> RelationDef { | ||
Relation::ProductVersion.def() | ||
} | ||
} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use sea_orm::entity::prelude::*; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "product_version")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
pub product_id: i32, | ||
pub sbom_id: Option<Uuid>, | ||
pub version: String, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation { | ||
#[sea_orm( | ||
belongs_to = "super::product::Entity", | ||
from = "super::product_version::Column::ProductId" | ||
to = "super::product::Column::Id")] | ||
Product, | ||
} | ||
|
||
impl Related<super::product::Entity> for Entity { | ||
fn to() -> RelationDef { | ||
Relation::Product.def() | ||
} | ||
} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
use sea_orm_migration::prelude::*; | ||
|
||
use crate::m0000022_create_organization::Organization; | ||
|
||
#[derive(DeriveMigrationName)] | ||
pub struct Migration; | ||
|
||
#[async_trait::async_trait] | ||
impl MigrationTrait for Migration { | ||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { | ||
// Replace the sample below with your own migration scripts | ||
manager | ||
.create_table( | ||
Table::create() | ||
.table(Product::Table) | ||
.col( | ||
ColumnDef::new(Product::Id) | ||
.integer() | ||
.not_null() | ||
.auto_increment() | ||
.primary_key(), | ||
) | ||
.col(ColumnDef::new(Product::Name).string().not_null()) | ||
.col(ColumnDef::new(Product::VendorId).integer() /* allowed to be null if not known */) | ||
.foreign_key( | ||
ForeignKey::create() | ||
.from_col(Product::VendorId) | ||
.to(Organization::Table, Organization::Id) | ||
) | ||
.to_owned(), | ||
) | ||
.await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { | ||
manager | ||
.drop_table(Table::drop().table(Product::Table).to_owned()) | ||
.await | ||
} | ||
} | ||
|
||
#[derive(DeriveIden)] | ||
pub enum Product { | ||
Table, | ||
Id, | ||
Name, | ||
VendorId, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use sea_orm_migration::prelude::*; | ||
|
||
use crate::{m0000030_create_sbom::Sbom, m0000290_create_product::Product, Now}; | ||
|
||
#[derive(DeriveMigrationName)] | ||
pub struct Migration; | ||
|
||
#[async_trait::async_trait] | ||
impl MigrationTrait for Migration { | ||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { | ||
// Replace the sample below with your own migration scripts | ||
manager | ||
.create_table( | ||
Table::create() | ||
.table(ProductVersion::Table) | ||
.if_not_exists() | ||
.col( | ||
ColumnDef::new(ProductVersion::Id) | ||
.integer() | ||
.not_null() | ||
.auto_increment() | ||
.primary_key(), | ||
) | ||
.col( | ||
ColumnDef::new(ProductVersion::Timestamp) | ||
.timestamp_with_time_zone() | ||
.default(Func::cust(Now)), | ||
) | ||
.col( | ||
ColumnDef::new(ProductVersion::ProductId) | ||
.integer() | ||
.not_null(), | ||
) | ||
.col(ColumnDef::new(ProductVersion::SbomId).uuid()) | ||
.col(ColumnDef::new(ProductVersion::Version).string().not_null()) | ||
.foreign_key( | ||
ForeignKey::create() | ||
.from_col(ProductVersion::ProductId) | ||
.to(Product::Table, Product::Id) | ||
.on_delete(ForeignKeyAction::Cascade), | ||
) | ||
.foreign_key( | ||
ForeignKey::create() | ||
.from_col(ProductVersion::SbomId) | ||
.to(Sbom::Table, Sbom::SbomId) | ||
.on_delete(ForeignKeyAction::SetNull), | ||
) | ||
.to_owned(), | ||
) | ||
.await?; | ||
|
||
manager | ||
.create_index( | ||
Index::create() | ||
.table(ProductVersion::Table) | ||
.name(INDEX_BY_PID_V) | ||
.if_not_exists() | ||
.unique() | ||
.col(ProductVersion::ProductId) | ||
.col(ProductVersion::Version) | ||
.to_owned(), | ||
) | ||
.await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { | ||
manager | ||
.drop_index( | ||
Index::drop() | ||
.table(ProductVersion::Table) | ||
.name(INDEX_BY_PID_V) | ||
.if_exists() | ||
.to_owned(), | ||
) | ||
.await?; | ||
manager | ||
.drop_table(Table::drop().table(ProductVersion::Table).to_owned()) | ||
.await?; | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
const INDEX_BY_PID_V: &str = "by_productid_v"; | ||
|
||
#[derive(DeriveIden)] | ||
pub enum ProductVersion { | ||
Table, | ||
Id, | ||
Timestamp, | ||
// -- | ||
ProductId, | ||
SbomId, | ||
Version, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod model; | ||
pub mod service; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use utoipa::ToSchema; | ||
|
||
mod summary; | ||
pub use summary::*; | ||
|
||
use crate::Error; | ||
use trustify_common::db::ConnectionOrTransaction; | ||
use trustify_entity::product; | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)] | ||
pub struct ProductHead { | ||
pub id: i32, | ||
pub name: String, | ||
} | ||
|
||
impl ProductHead { | ||
pub async fn from_entity( | ||
product: &product::Model, | ||
_tx: &ConnectionOrTransaction<'_>, | ||
) -> Result<Self, Error> { | ||
Ok(ProductHead { | ||
id: product.id, | ||
name: product.name.clone(), | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use crate::product::model::ProductHead; | ||
use crate::Error; | ||
use serde::{Deserialize, Serialize}; | ||
use trustify_common::db::ConnectionOrTransaction; | ||
use trustify_common::paginated; | ||
use trustify_entity::product; | ||
use utoipa::ToSchema; | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] | ||
pub struct ProductSummary { | ||
#[serde(flatten)] | ||
pub head: ProductHead, | ||
} | ||
|
||
paginated!(ProductSummary); | ||
|
||
impl ProductSummary { | ||
pub async fn from_entity( | ||
product: &product::Model, | ||
tx: &ConnectionOrTransaction<'_>, | ||
) -> Result<Self, Error> { | ||
Ok(ProductSummary { | ||
head: ProductHead::from_entity(product, tx).await?, | ||
}) | ||
} | ||
|
||
pub async fn from_entities( | ||
products: &[product::Model], | ||
tx: &ConnectionOrTransaction<'_>, | ||
) -> Result<Vec<Self>, Error> { | ||
let mut summaries = Vec::new(); | ||
|
||
for org in products { | ||
summaries.push(ProductSummary { | ||
head: ProductHead::from_entity(org, tx).await?, | ||
}); | ||
} | ||
|
||
Ok(summaries) | ||
} | ||
} |
Oops, something went wrong.