Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy 20240416 #238

Merged
merged 24 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3a86e51
feat: reqwestにタイムアウトを追加した
arata-nvm Apr 15, 2024
7c28980
Merge pull request #230 from sohosai/feature/reqwest-timeout
appare45 Apr 15, 2024
fc6a61e
feat: エクスポート時に日時をJSTで出力するように
arata-nvm Apr 15, 2024
4158f2e
feat: 文字数を書記素単位でカウントするように
arata-nvm Apr 15, 2024
8f81139
refactor: アーカイブのDTOでファイル名を返すように
arata-nvm Apr 15, 2024
416a1f4
feat: 申請に紐づくファイルをエクスポートできるように
arata-nvm Apr 15, 2024
5976e38
docs: スキーマを更新
arata-nvm Apr 15, 2024
d4d0da0
refactor: アーカイブ作成時に受け取る引数の型を変更した
arata-nvm Apr 15, 2024
da135b1
fix: 64KiBより大きいファイルでアーカイブの作成が終了しない問題を修正
arata-nvm Apr 15, 2024
c6557d7
refactor: axum-extraのかわりにtokio-utilをつかうように
arata-nvm Apr 15, 2024
dd40837
feat: ファイルエクスポート時にファイル名を変更するように
arata-nvm Apr 15, 2024
54154b2
fix: 申請一覧の型を修正
arata-nvm Apr 15, 2024
9fd3566
feat: 申請項目ごとにディレクトリを分けるように
arata-nvm Apr 15, 2024
3347df6
feat: ファイル名をサニタイズするように
arata-nvm Apr 15, 2024
f6d37be
fix: mongodbでの更新時に、型が異なる値を使用していたのを修正した
arata-nvm Apr 15, 2024
8a478fd
Merge pull request #235 from sohosai/feature/fix-mongo
arata-nvm Apr 15, 2024
54bc688
Merge pull request #231 from sohosai/feature/export-in-jst
arata-nvm Apr 16, 2024
becd790
Merge pull request #232 from sohosai/feature/count-chars
arata-nvm Apr 16, 2024
12ee933
docs: スキーマのファイル形式を修正
arata-nvm Apr 16, 2024
5f11243
feat: 企画を削除したときに、関連するリソースを削除するように
arata-nvm Apr 15, 2024
1bd465e
chore: cargo sqlx prepare --workflow
arata-nvm Apr 15, 2024
3accaf4
feat: bsonの型を使うように
arata-nvm Apr 16, 2024
55dd94a
Merge pull request #234 from sohosai/feature/rename-files
arata-nvm Apr 16, 2024
1cfcfd9
Merge pull request #223 from sohosai/feature/delete-project-and-form
arata-nvm Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 56 additions & 25 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ edition = "2021"
anyhow = "1.0.79"
async_zip = { version = "0.0.17", features = ["chrono", "deflate", "tokio"] }
axum = { version = "0.7.4", features = ["macros", "multipart", "query"] }
axum-extra = { version = "0.9.3", features = ["async-read-body"] }
aws-sdk-s3 = { version = "1.20.0", features = ["rt-tokio"] }
base64 = "0.22.0"
bitflags = "2.4.2"
chrono = { version = "0.4.32", features = ["serde"] }
chrono-tz = "0.9.0"
csv = "1.3.0"
dotenvy = "0.15.7"
emojis = "0.6.1"
Expand All @@ -43,7 +43,7 @@ sqlx = { version = "0.7.3", features = [
] }
thiserror = "1.0.56"
tokio = { version = "1.35.1", features = ["full"] }
tokio-util = { version = "0.7.10", features = ["compat"] }
tokio-util = { version = "0.7.10", features = ["compat", "io"] }
tower = { version = "0.4.13", features = ["util"] }
tower-http = { version = "0.5.1", features = ["cors", "trace"] }
tracing = "0.1.40"
Expand Down
57 changes: 56 additions & 1 deletion crates/sos24-domain/src/entity/file_data.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::ffi::OsStr;
use std::path::Path;

use getset::{Getters, Setters};
use thiserror::Error;

Expand Down Expand Up @@ -55,7 +58,37 @@ pub struct DestructedFileData {
}

impl_value_object!(FileId(uuid::Uuid));
impl_value_object!(FileName(String));

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileName(String);

impl FileName {
pub fn sanitized(name: String) -> Self {
// ref: https://github.com/rwf2/Rocket/blob/60f3cd57b06243beaee87fd5b7545e3bf0fa6f60/core/lib/src/fs/file_name.rs#L140-L146
static BAD_CHARS: &[char] = &[
// These have special meaning in a file name.
'.', '/', '\\', // These are treated specially by shells.
'<', '>', '|', ':', '(', ')', '&', ';', '#', '?', '*',
];

let file_name = Path::new(&name)
.file_name()
.and_then(OsStr::to_str)
.and_then(|n| n.split(BAD_CHARS).find(|s| !s.is_empty()))
.unwrap_or("");

let ext = Path::new(&name)
.extension()
.and_then(OsStr::to_str)
.unwrap_or("");

Self(format!("{}.{}", file_name, ext))
}

pub fn value(self) -> String {
self.0
}
}

#[derive(Debug, Error)]
pub enum FileIdError {
Expand All @@ -71,3 +104,25 @@ impl TryFrom<String> for FileId {
Ok(Self(uuid))
}
}

#[cfg(test)]
mod tests {
use crate::entity::file_data::FileName;

#[test]
fn filename_sanitized() {
const TEST_CASES: [(&str, &str); 6] = [
("foo.txt", "foo.txt"),
("foo.exe.txt", "foo.txt"),
("../../foo.txt", "foo.txt"),
("./foo.txt", "foo.txt"),
("/bar/foo.txt", "foo.txt"),
("/bar/.foo.txt", "foo.txt"),
];

for (input, expected) in TEST_CASES {
let actual = FileName::sanitized(String::from(input));
assert_eq!(actual.value().as_str(), expected);
}
}
}
35 changes: 35 additions & 0 deletions crates/sos24-domain/src/entity/file_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,41 @@ impl FileObjectKey {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArchiveEntry {
key: FileObjectKey,
filename: FileName,
updated_at: chrono::DateTime<chrono::Utc>,
}

impl ArchiveEntry {
pub fn new(
key: FileObjectKey,
filename: FileName,
updated_at: chrono::DateTime<chrono::Utc>,
) -> Self {
Self {
key,
filename,
updated_at,
}
}

pub fn destruct(self) -> DestructedArchiveEntry {
DestructedArchiveEntry {
key: self.key,
filename: self.filename,
updated_at: self.updated_at,
}
}
}

pub struct DestructedArchiveEntry {
pub key: FileObjectKey,
pub filename: FileName,
pub updated_at: chrono::DateTime<chrono::Utc>,
}

#[cfg(test)]
mod test {
use crate::entity::file_object::generate_content_disposition;
Expand Down
4 changes: 4 additions & 0 deletions crates/sos24-domain/src/entity/form.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ impl Form {
self.categories.matches(*project.category())
&& self.attributes.matches(*project.attributes())
}

pub fn find_item(&self, item_id: &FormItemId) -> Option<&FormItem> {
self.items.iter().find(|item| item.id() == item_id)
}
}

impl_value_object!(FormId(uuid::Uuid));
Expand Down
12 changes: 12 additions & 0 deletions crates/sos24-domain/src/entity/form_answer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ impl FormAnswer {
self.items = items;
Ok(())
}

pub fn list_file_items(&self) -> Vec<(FormItemId, Vec<FileId>)> {
self.items
.iter()
.filter_map(|item| match &item.kind {
FormAnswerItemKind::File(file) => {
Some((item.item_id().clone(), file.clone().value()))
}
_ => None,
})
.collect()
}
}

impl_value_object!(FormAnswerId(uuid::Uuid));
Expand Down
4 changes: 4 additions & 0 deletions crates/sos24-domain/src/repository/file_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ pub trait FileDataRepository: Send + Sync + 'static {
owner_project: ProjectId,
) -> Result<Vec<WithDate<FileData>>, FileDataRepositoryError>;
async fn delete_by_id(&self, id: FileId) -> Result<(), FileDataRepositoryError>;
async fn delete_by_owner_project(
&self,
owner_project: ProjectId,
) -> Result<(), FileDataRepositoryError>;
}
13 changes: 7 additions & 6 deletions crates/sos24-domain/src/repository/file_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use mockall::automock;
use thiserror::Error;
use tokio::io::DuplexStream;

use crate::entity::common::date::WithDate;
use crate::entity::file_data::FileData;
use crate::entity::file_object::{ContentDisposition, FileObject, FileObjectKey, FileSignedUrl};
use crate::entity::file_object::{
ArchiveEntry, ContentDisposition, FileObject, FileObjectKey, FileSignedUrl,
};

#[derive(Debug, Error)]
pub enum FileObjectRepositoryError {
Expand All @@ -27,9 +27,10 @@ pub trait FileObjectRepository: Send + Sync + 'static {
content_disposition: Option<ContentDisposition>,
) -> Result<FileSignedUrl, FileObjectRepositoryError>;
// TODO: 返り値をラッピングしておくと内部仕様が露出しなくてよい
async fn create_archive(
fn create_archive(
&self,
bucket: String,
files: Vec<WithDate<FileData>>,
) -> Result<DuplexStream, FileObjectRepositoryError>;
entry_list: Vec<ArchiveEntry>,
writer: DuplexStream,
) -> impl std::future::Future<Output = Result<(), FileObjectRepositoryError>> + Send;
}
1 change: 1 addition & 0 deletions crates/sos24-domain/src/repository/form_answer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ pub trait FormAnswerRepository: Send + Sync + 'static {
form_id: FormId,
) -> Result<Option<WithDate<FormAnswer>>, FormAnswerRepositoryError>;
async fn update(&self, form_answer: FormAnswer) -> Result<(), FormAnswerRepositoryError>;
async fn delete_by_project_id(&self, id: ProjectId) -> Result<(), FormAnswerRepositoryError>;
}
2 changes: 2 additions & 0 deletions crates/sos24-domain/src/repository/invitation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use mockall::automock;
use thiserror::Error;

use crate::entity::project::ProjectId;
use crate::entity::user::UserId;
use crate::entity::{
common::date::WithDate,
Expand Down Expand Up @@ -30,4 +31,5 @@ pub trait InvitationRepository: Send + Sync + 'static {

async fn update(&self, invitation: Invitation) -> Result<(), InvitationRepositoryError>;
async fn delete_by_id(&self, id: InvitationId) -> Result<(), InvitationRepositoryError>;
async fn delete_by_project_id(&self, id: ProjectId) -> Result<(), InvitationRepositoryError>;
}
Loading