Skip to content

Commit

Permalink
Migrate file methods.
Browse files Browse the repository at this point in the history
Also add site_id column to file tables.
  • Loading branch information
emmiegit committed Oct 15, 2023
1 parent 7762f2f commit 438b056
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 88 deletions.
2 changes: 2 additions & 0 deletions deepwell/migrations/20220906103252_deepwell.sql
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ CREATE TABLE file (
from_wikidot BOOLEAN NOT NULL DEFAULT false,
name TEXT NOT NULL,
page_id BIGINT NOT NULL REFERENCES page(page_id),
site_id BIGINT NOT NULL REFERENCES site(site_id),

UNIQUE (page_id, name, deleted_at)
);
Expand All @@ -442,6 +443,7 @@ CREATE TABLE file_revision (
revision_number INTEGER NOT NULL,
file_id BIGINT NOT NULL REFERENCES file(file_id),
page_id BIGINT NOT NULL REFERENCES page(page_id),
site_id BIGINT NOT NULL REFERENCES site(site_id),
user_id BIGINT NOT NULL REFERENCES "user"(user_id),
name TEXT NOT NULL,
s3_hash BYTEA NOT NULL,
Expand Down
5 changes: 1 addition & 4 deletions deepwell/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ async fn build_module(app_state: ServerState) -> anyhow::Result<RpcModule<Server

// Files
register!("file_upload", file_upload);
register!("file_get", not_implemented);
register!("file_get", file_get);
register!("file_edit", file_edit);
register!("file_delete", file_delete);
register!("file_move", file_move);
Expand Down Expand Up @@ -320,9 +320,6 @@ pub fn tide_build_server(state: ServerState) -> tide::Server<ServerState> {
}

fn tide_build_routes(mut app: tide::Server<ServerState>) -> tide::Server<ServerState> {
// Files
app.at("/file/get").put(file_retrieve);

// File revisions
app.at("/file/revision").put(file_revision_put);
app.at("/file/revision/get").put(file_revision_retrieve);
Expand Down
73 changes: 31 additions & 42 deletions deepwell/src/endpoints/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,33 @@
use super::prelude::*;
use crate::models::file::Model as FileModel;
use crate::models::file_revision::Model as FileRevisionModel;
use crate::services::file::{GetFile, GetFileOutput};
use crate::services::file::{GetFileDetails, GetFileOutput};
use crate::services::Result;
use crate::web::FileDetailsQuery;
use crate::web::FileDetails;

pub async fn file_retrieve(mut req: ApiRequest) -> ApiResponse {
let txn = req.database().begin().await?;
let ctx = ServiceContext::from_req(&req, &txn);

let details: FileDetailsQuery = req.query()?;
let GetFile {
site_id,
page_id,
file: file_reference,
} = req.body_json().await?;
pub async fn file_get(
ctx: &ServiceContext<'_>,
params: Params<'static>,
) -> Result<Option<GetFileOutput>> {
let GetFileDetails { input, details } = params.parse()?;

tide::log::info!(
"Getting file {file_reference:?} from page ID {page_id} in site ID {site_id}",
"Getting file {:?} from page ID {} in site ID {}",
input.file,
input.page_id,
input.site_id,
);

// We cannot use get_id() because we need File for build_file_response().
// TODO use optional
let file = FileService::get(&ctx, page_id, file_reference).await?;

let revision = FileRevisionService::get_latest(&ctx, page_id, file.file_id).await?;

let response =
build_file_response(&ctx, &file, &revision, details, StatusCode::Ok).await?;

txn.commit().await?;
Ok(response)
match FileService::get_optional(&ctx, input).await? {
None => Ok(None),
Some(file) => {
let revision =
FileRevisionService::get_latest(&ctx, file.page_id, file.file_id).await?;
let output = build_file_response(&ctx, file, revision, details).await?;
Ok(Some(output))
}
}
}

pub async fn file_upload(
Expand Down Expand Up @@ -90,16 +87,12 @@ pub async fn file_restore(

async fn build_file_response(
ctx: &ServiceContext<'_>,
file: &FileModel,
revision: &FileRevisionModel,
details: FileDetailsQuery,
status: StatusCode,
) -> Result<Response> {
// Get blob data, if requested
file: FileModel,
revision: FileRevisionModel,
details: FileDetails,
) -> Result<GetFileOutput> {
let data = BlobService::get_maybe(ctx, details.data, &revision.s3_hash).await?;

// Build result struct
let output = GetFileOutput {
Ok(GetFileOutput {
file_id: file.file_id,
file_created_at: file.created_at,
file_updated_at: file.updated_at,
Expand All @@ -110,16 +103,12 @@ async fn build_file_response(
revision_created_at: revision.created_at,
revision_number: revision.revision_number,
revision_user_id: revision.user_id,
name: &file.name,
name: file.name,
data,
mime: &revision.mime_hint,
mime: revision.mime_hint,
size: revision.size_hint,
licensing: &revision.licensing,
revision_comments: &revision.comments,
hidden_fields: &revision.hidden,
};

let body = Body::from_json(&output)?;
let response = Response::builder(status).body(body).into();
Ok(response)
licensing: revision.licensing,
revision_comments: revision.comments,
hidden_fields: revision.hidden,
})
}
9 changes: 9 additions & 0 deletions deepwell/src/models/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Model {
#[sea_orm(column_type = "Text")]
pub name: String,
pub page_id: i64,
pub site_id: i64,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
Expand All @@ -29,6 +30,14 @@ pub enum Relation {
on_delete = "NoAction"
)]
Page,
#[sea_orm(
belongs_to = "super::site::Entity",
from = "Column::SiteId",
to = "super::site::Column::SiteId",
on_update = "NoAction",
on_delete = "NoAction"
)]
Site,
}

impl Related<super::file_revision::Entity> for Entity {
Expand Down
9 changes: 9 additions & 0 deletions deepwell/src/models/file_revision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub struct Model {
pub revision_number: i32,
pub file_id: i64,
pub page_id: i64,
pub site_id: i64,
pub user_id: i64,
#[sea_orm(column_type = "Text")]
pub name: String,
Expand Down Expand Up @@ -47,6 +48,14 @@ pub enum Relation {
on_delete = "NoAction"
)]
Page,
#[sea_orm(
belongs_to = "super::site::Entity",
from = "Column::SiteId",
to = "super::site::Column::SiteId",
on_update = "NoAction",
on_delete = "NoAction"
)]
Site,
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
Expand Down
27 changes: 18 additions & 9 deletions deepwell/src/services/file/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ impl FileService {
#[allow(dead_code)] // TEMP
pub async fn delete(
ctx: &ServiceContext<'_>,
site_id: i64,
page_id: i64,
reference: Reference<'_>,
input: DeleteFile,
Expand All @@ -281,7 +282,15 @@ impl FileService {
} = input;

// Ensure file exists
let FileModel { file_id, .. } = Self::get(ctx, page_id, reference).await?;
let FileModel { file_id, .. } = Self::get(
ctx,
GetFile {
site_id,
page_id,
file: reference,
},
)
.await?;

let last_revision =
FileRevisionService::get_latest(ctx, page_id, file_id).await?;
Expand Down Expand Up @@ -396,8 +405,11 @@ impl FileService {

pub async fn get_optional(
ctx: &ServiceContext<'_>,
page_id: i64,
reference: Reference<'_>,
GetFile {
site_id,
page_id,
file: reference,
}: GetFile<'_>,
) -> Result<Option<FileModel>> {
let txn = ctx.transaction();
let file = {
Expand All @@ -410,6 +422,7 @@ impl FileService {
.filter(
Condition::all()
.add(condition)
.add(file::Column::SiteId.eq(site_id))
.add(file::Column::PageId.eq(page_id))
.add(file::Column::DeletedAt.is_null()),
)
Expand All @@ -421,12 +434,8 @@ impl FileService {
}

#[inline]
pub async fn get(
ctx: &ServiceContext<'_>,
page_id: i64,
reference: Reference<'_>,
) -> Result<FileModel> {
find_or_error(Self::get_optional(ctx, page_id, reference)).await
pub async fn get(ctx: &ServiceContext<'_>, input: GetFile<'_>) -> Result<FileModel> {
find_or_error(Self::get_optional(ctx, input)).await
}

/// Gets the file ID from a reference, looking up if necessary.
Expand Down
71 changes: 40 additions & 31 deletions deepwell/src/services/file/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ use crate::models::sea_orm_active_enums::FileRevisionType;
use crate::services::file_revision::{
CreateFileRevisionOutput, CreateFirstFileRevisionOutput,
};
use crate::web::{ProvidedValue, Reference};
use crate::web::{FileDetails, ProvidedValue, Reference};
use serde_json::Value as JsonValue;
use time::OffsetDateTime;

#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct CreateFile {
pub revision_comments: String,
pub name: String,
Expand All @@ -39,14 +39,44 @@ pub struct CreateFile {

pub type CreateFileOutput = CreateFirstFileRevisionOutput;

#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct GetFile<'a> {
pub site_id: i64,
pub page_id: i64,
pub file: Reference<'a>,
}

#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct GetFileDetails<'a> {
#[serde(flatten)]
pub input: GetFile<'a>,

#[serde(default)]
pub details: FileDetails,
}

#[derive(Serialize, Debug, Clone)]
pub struct GetFileOutput {
pub file_id: i64,
pub file_created_at: OffsetDateTime,
pub file_updated_at: Option<OffsetDateTime>,
pub file_deleted_at: Option<OffsetDateTime>,
pub page_id: i64,
pub revision_id: i64,
pub revision_type: FileRevisionType,
pub revision_created_at: OffsetDateTime,
pub revision_number: i32,
pub revision_user_id: i64,
pub name: String,
pub data: Option<Vec<u8>>,
pub mime: String,
pub size: i64,
pub licensing: JsonValue,
pub revision_comments: String,
pub hidden_fields: Vec<String>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct UpdateFile {
pub revision_comments: String,
pub user_id: i64,
Expand All @@ -58,7 +88,7 @@ pub struct UpdateFile {
pub bypass_filter: bool,
}

#[derive(Deserialize, Debug, Default)]
#[derive(Deserialize, Debug, Default, Clone)]
#[serde(default)]
pub struct UpdateFileBody {
pub name: ProvidedValue<String>,
Expand All @@ -68,7 +98,7 @@ pub struct UpdateFileBody {

pub type UpdateFileOutput = CreateFileRevisionOutput;

#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct MoveFile {
pub revision_comments: String,
pub user_id: i64,
Expand All @@ -79,35 +109,14 @@ pub struct MoveFile {

pub type MoveFileOutput = CreateFileRevisionOutput;

#[derive(Serialize, Debug)]
pub struct GetFileOutput<'a> {
pub file_id: i64,
pub file_created_at: OffsetDateTime,
pub file_updated_at: Option<OffsetDateTime>,
pub file_deleted_at: Option<OffsetDateTime>,
pub page_id: i64,
pub revision_id: i64,
pub revision_type: FileRevisionType,
pub revision_created_at: OffsetDateTime,
pub revision_number: i32,
pub revision_user_id: i64,
pub name: &'a str,
pub data: Option<Vec<u8>>,
pub mime: &'a str,
pub size: i64,
pub licensing: &'a JsonValue,
pub revision_comments: &'a str,
pub hidden_fields: &'a [String],
}

#[derive(Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct DeleteFile {
pub revision_comments: String,
pub site_id: i64,
pub user_id: i64,
}

#[derive(Debug)]
#[derive(Deserialize, Debug, Clone)]
pub struct RestoreFile {
pub revision_comments: String,
pub new_page_id: Option<i64>,
Expand All @@ -116,14 +125,14 @@ pub struct RestoreFile {
pub user_id: i64,
}

#[derive(Serialize, Debug)]
#[derive(Serialize, Debug, Clone)]
pub struct DeleteFileOutput {
pub file_id: i64,
pub file_revision_id: i64,
pub file_revision_number: i32,
}

#[derive(Serialize, Debug)]
#[derive(Serialize, Debug, Clone)]
pub struct RestoreFileOutput {
pub page_id: i64,
pub file_id: i64,
Expand Down
2 changes: 1 addition & 1 deletion deepwell/src/web/file_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

#[derive(Serialize, Deserialize, Debug, Default, Copy, Clone, PartialEq, Eq)]
#[serde(default)]
pub struct FileDetailsQuery {
pub struct FileDetails {
/// Include the contents of the file.
pub data: bool,
}
2 changes: 1 addition & 1 deletion deepwell/src/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod unwrap;

pub use self::connection_type::ConnectionType;
pub use self::fetch_direction::FetchDirection;
pub use self::file_details::FileDetailsQuery;
pub use self::file_details::FileDetails;
pub use self::page_details::PageDetails;
pub use self::page_order::{PageOrder, PageOrderColumn};
pub use self::provided_value::ProvidedValue;
Expand Down

0 comments on commit 438b056

Please sign in to comment.