Skip to content

Commit a499cf3

Browse files
committed
Merge branch 'master' of github.com:mdcpp/mdoj into staging
2 parents b14cbd9 + 790d75c commit a499cf3

File tree

15 files changed

+155
-449
lines changed

15 files changed

+155
-449
lines changed

Cargo.lock

Lines changed: 63 additions & 402 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ version = "0.11.0"
3737
default-features = false
3838

3939
[workspace.dependencies.sea-orm]
40-
version = "0.12.11"
40+
version = "1.0.0"
4141
default-features = false
4242

4343
[workspace.dependencies.sea-orm-migration]
44-
version = "0.12.11"
44+
version = "1.0.0"
4545
default-features = false
4646

4747
[profile.wasm-release]

backend/Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ futures = "0.3.29"
1919
bincode = "1.3.3"
2020
base64 = "0.21.5"
2121
tonic-web = { workspace = true }
22-
quick_cache = "0.4.0"
22+
quick_cache = "0.6.2"
2323
hickory-resolver = "0.24.0"
2424
crossbeam-queue = "0.3.8"
2525
dashmap = "5.5.3"
@@ -36,7 +36,6 @@ opentelemetry-semantic-conventions = "0.16.0"
3636
tracing-opentelemetry = { version = "0.24.0", features = ["metrics"] }
3737
tracing-core = "0.1.32"
3838
migration = { path = "./migration", optional = true }
39-
sea-orm-cli = { version = "0.12.12", optional = true }
4039
governor = "0.6.0"
4140
http = "^0.2"
4241
lazy_static = "1.5.0"
@@ -69,7 +68,7 @@ version = "^0.4"
6968
features = ["cors", "trace"]
7069

7170
[dependencies.sea-query]
72-
version = "0.30.4"
71+
version = "0.31.0"
7372
features = ["thread-safe", "with-chrono", "backend-sqlite"]
7473

7574
[dependencies.chrono]
@@ -102,7 +101,8 @@ workspace = true
102101
features = ["macros", "rt-multi-thread", "full", "time"]
103102

104103
[dependencies.sea-orm]
105-
version = "0.12.11"
104+
workspace = true
105+
default-features = false
106106
features = [
107107
"runtime-tokio-rustls",
108108
"macros",
@@ -124,12 +124,12 @@ version = "0.9.8"
124124
features = ["mutex", "spin_mutex", "rwlock"]
125125

126126
[dependencies.sea-orm-migration]
127-
# workspace = true
128-
version = "0.12.11"
127+
workspace = true
129128
optional = true
129+
default-features = false
130130
features = ["runtime-tokio-rustls", "sqlx-sqlite", "with-chrono"]
131131

132132
[features]
133133
default = ["insecure-print"]
134-
standalone = ["dep:migration", "dep:sea-orm-migration", "dep:sea-orm-cli"]
134+
standalone = ["dep:migration", "dep:sea-orm-migration"]
135135
insecure-print = ["sea-orm/debug-print"]

backend/migration/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ version = "1"
2222
features = ["attributes", "tokio1"]
2323

2424
[dependencies.sea-orm]
25-
version = "0.12.11"
25+
workspace = true
2626
default-features = false
2727
features = [
2828
"runtime-async-std-rustls",
@@ -34,8 +34,7 @@ features = [
3434
]
3535

3636
[dependencies.sea-orm-migration]
37-
# workspace = true
38-
version = "0.12.11"
37+
workspace = true
3938
default-features = true
4039
features = [
4140
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.

backend/migration/src/m20231207_000001_create_table.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,17 +668,25 @@ impl MigrationTrait for Migration {
668668
index!(manager, Problem, AcceptCount);
669669
index!(manager, Problem, Difficulty);
670670
index!(manager, Problem, Order);
671+
index!(manager, Problem, Content);
672+
index!(manager, Problem, Title);
673+
671674
index!(manager, Submit, Committed);
672675
index!(manager, Submit, Time);
673676
index!(manager, Submit, Memory);
677+
index!(manager, Submit, UserId);
678+
674679
index!(manager, Contest, Hoster);
675680
index!(manager, Contest, Public);
676681
index!(manager, Contest, End);
677682
index!(manager, Contest, Begin);
683+
678684
index!(manager, User, Score);
679685
index!(manager, User, Username);
686+
680687
index!(manager, Token, Rand);
681688
index!(manager, Token, Expiry);
689+
682690
index!(manager, Chat, CreateAt);
683691

684692
manager

backend/src/entity/contest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct Model {
2121
pub title: String,
2222
pub content: String,
2323
pub tags: String,
24-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))", nullable)]
24+
#[sea_orm(column_type = "Blob", nullable)]
2525
pub password: Option<Vec<u8>>,
2626
#[sea_orm(column_type = "Time")]
2727
pub create_at: chrono::NaiveDateTime,

backend/src/entity/submit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct Model {
1717
pub accuracy: Option<i64>,
1818
pub committed: bool,
1919
pub lang: String,
20-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
20+
#[sea_orm(column_type = "Blob")]
2121
pub code: Vec<u8>,
2222
#[sea_orm(nullable)]
2323
pub memory: Option<i64>,

backend/src/entity/testcase.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ pub struct Model {
99
pub user_id: i32,
1010
#[sea_orm(nullable)]
1111
pub problem_id: Option<i32>,
12-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
12+
#[sea_orm(column_type = "Blob")]
1313
pub input: Vec<u8>,
14-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
14+
#[sea_orm(column_type = "Blob")]
1515
pub output: Vec<u8>,
1616
pub score: u32,
1717
pub order: f32,

backend/src/entity/token.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub struct Model {
1010
#[sea_orm(primary_key)]
1111
pub id: i32,
1212
pub user_id: i32,
13-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
13+
#[sea_orm(column_type = "Blob")]
1414
pub rand: Vec<u8>,
1515
pub permission: i32,
1616
#[sea_orm(column_type = "Time")]

backend/src/entity/user.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub struct Model {
1313
pub permission: i32,
1414
pub score: i64,
1515
pub username: String,
16-
#[sea_orm(column_type = "Binary(BlobSize::Blob(None))")]
16+
#[sea_orm(column_type = "Blob")]
1717
pub password: Vec<u8>,
1818
#[sea_orm(column_type = "Time")]
1919
pub create_at: chrono::NaiveDateTime,

backend/src/entity/util/helper.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
55
use std::ops::Deref;
66

7+
use sea_orm::sea_query::*;
78
use sea_orm::*;
8-
use sea_query::*;
99
use tracing::instrument;
1010

1111
use crate::util::error::Error;
@@ -190,3 +190,21 @@ impl<E: EntityTrait> MaxCount<E> {
190190
})
191191
}
192192
}
193+
194+
/// convert sized span to single-direction span
195+
///
196+
/// Return None if span cannot be converted(cross boundary).
197+
///
198+
/// It panics if overflow(u64 to i64).
199+
///
200+
/// See `dev.md` for sized span and single-direction span.
201+
pub(super) fn to_inner_size_offset(size: u64, offset: i64) -> Option<(i64, u64)> {
202+
// cross boundary
203+
if offset.is_negative() && size > offset.unsigned_abs() {
204+
return None;
205+
}
206+
match offset.is_negative() {
207+
true => Some((-(size as i64), offset.unsigned_abs() - size)),
208+
false => Some((size as i64, offset as u64)),
209+
}
210+
}

backend/src/entity/util/paginator.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::marker::PhantomData;
2020

2121
use crate::util::error::Error;
2222

23-
const PAGINATE_GUARANTEE: u64 = 96;
23+
const PAGINATE_GUARANTEE: u64 = 256;
2424

2525
#[async_trait]
2626
pub trait PaginateRaw
@@ -362,6 +362,14 @@ impl<S: SortSource<R>, R: Reflect<S::Entity>> PaginateRaw for ColumnPaginator<S,
362362
}
363363
}
364364

365+
/// A paginator that may be initialized
366+
///
367+
/// Key-set Paginator requires information from last fetched column
368+
/// (sometimes called trailing information) to be initialized.
369+
///
370+
/// **Can only be serialized or deserialized when initialized.**
371+
///
372+
/// **Calling fetch with size 0 doesn't initialize it!**
365373
#[derive(Serialize, Default)]
366374
pub enum UninitPaginator<P: PaginateRaw> {
367375
#[serde(skip)]
@@ -390,9 +398,15 @@ impl<'de, P: PaginateRaw> Deserialize<'de> for UninitPaginator<P> {
390398
}
391399

392400
impl<P: PaginateRaw> UninitPaginator<P> {
401+
/// construct a paginator with its initial query argument.
393402
pub fn new(data: <P::Source as PagerData>::Data, start_from_end: bool) -> Self {
394403
Self::Uninit(data, start_from_end)
395404
}
405+
/// fetch some entries
406+
///
407+
/// Return `Error::BadArgument` when
408+
/// 1. offset is when paginator has yet to be initialized and offset is negative
409+
/// 2. span crosses the boundary,
396410
pub async fn fetch(
397411
&mut self,
398412
size: u64,
@@ -401,32 +415,31 @@ impl<P: PaginateRaw> UninitPaginator<P> {
401415
db: &DatabaseConnection,
402416
) -> Result<Vec<P::Reflect>, Error> {
403417
if let UninitPaginator::Init(x) = self {
404-
let size = size.min((i64::MAX - 1) as u64) as i64;
405-
let offset = offset.max(i64::MIN + 1);
406-
let (size, offset) = match offset < 0 {
407-
true => (
408-
-size,
409-
(-offset)
410-
.checked_sub(size)
411-
.ok_or(Error::BadArgument("size"))? as u64,
412-
),
413-
false => (size, offset as u64),
414-
};
418+
let (size, offset) =
419+
to_inner_size_offset(size, offset).ok_or(Error::BadArgument("size"))?;
415420
x.fetch(auth, size, offset, db).await.map(|mut x| {
416421
if size.is_negative() {
417422
x.reverse();
418423
}
419424
x
420425
})
421426
} else if let UninitPaginator::Uninit(x, start_from_end) = std::mem::take(self) {
427+
if offset.is_negative() {
428+
return Err(Error::BadArgument("offset"));
429+
}
422430
let (paginator, list) =
423-
P::new_fetch(x, auth, size, offset.max(0) as u64, start_from_end, db).await?;
431+
P::new_fetch(x, auth, size, offset as u64, start_from_end, db).await?;
424432
*self = UninitPaginator::Init(paginator);
425433
Ok(list)
426434
} else {
427435
unreachable!("Cannot in middle state")
428436
}
429437
}
438+
/// get how many column are remaining the **absolute forward** direction of paginator
439+
///
440+
/// If more than [`PAGINATE_GUARANTEE`], it returns [`PAGINATE_GUARANTEE`].
441+
///
442+
/// It passes [`sea_orm::DbErr`] to the callee.
430443
pub async fn remain(&self, auth: &Auth, db: &DatabaseConnection) -> Result<u64, Error>
431444
where
432445
P: Remain,

backend/src/server/db.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,9 @@ pub async fn init(
4848
#[cfg(feature = "standalone")]
4949
/// Run migration
5050
async fn migrate(db: &DatabaseConnection) -> super::Result<()> {
51-
sea_orm_migration::cli::run_migrate(
52-
::migration::Migrator,
53-
db,
54-
Some(sea_orm_cli::cli::MigrateSubcommands::Up { num: None }),
55-
false,
56-
)
57-
.await
58-
.map_err(InitError::AutoMigrate)?;
59-
Ok(())
51+
<::migration::Migrator as migration::MigratorTrait>::up(db, None)
52+
.await
53+
.map_err(InitError::AutoMigrate)
6054
}
6155

6256
#[instrument(skip_all, name = "construct_admin")]

backend/src/server/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub enum InitError {
88
OptimizeDB(sea_orm::DbErr),
99
#[cfg(feature = "standalone")]
1010
#[error("Fail to run auto migration: `{0}`")]
11-
AutoMigrate(Box<dyn std::error::Error>),
11+
AutoMigrate(sea_orm::DbErr),
1212
#[error("Fail to create initial user: `{0}`")]
1313
UserCreation(sea_orm::DbErr),
1414
#[error("Fail to parse config: `{0}`")]

backend/src/util/bound.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ macro_rules! list_paginator_request {
5353
paste::paste! {
5454
impl BoundCheck for [<List $n Request>] {
5555
fn check(&self) -> bool {
56-
if self.size==0{
56+
if self.size == 0 || self.size >= i32::MAX as u64 || self.offset.unsigned_abs() >= i32::MAX as u64{
5757
true
5858
}else if let Some(x) = &self.request {
5959
(match x {
@@ -82,7 +82,12 @@ list_paginator_request!(User);
8282

8383
impl BoundCheck for ListTokenRequest {
8484
fn check(&self) -> bool {
85-
if let Some(list_token_request::Request::Paginator(x)) = &self.request {
85+
if self.size == 0
86+
|| self.size >= i32::MAX as u64
87+
|| self.offset.unsigned_abs() >= i32::MAX as u64
88+
{
89+
true
90+
} else if let Some(list_token_request::Request::Paginator(x)) = &self.request {
8691
x.len() > 512
8792
} else {
8893
false
@@ -92,12 +97,15 @@ impl BoundCheck for ListTokenRequest {
9297

9398
impl BoundCheck for ListChatRequest {
9499
fn check(&self) -> bool {
95-
self.offset == 0 || self.offset > 4096 || self.size > 128
100+
self.offset == 0 || self.offset.unsigned_abs() > 4096 || self.size > 128
96101
}
97102
}
98103
impl BoundCheck for ListSubmitRequest {
99104
fn check(&self) -> bool {
100-
if self.offset == 0 {
105+
if self.size == 0
106+
|| self.size >= i32::MAX as u64
107+
|| self.offset.unsigned_abs() >= i32::MAX as u64
108+
{
101109
true
102110
} else if let Some(list_submit_request::Request::Paginator(x)) = &self.request {
103111
x.len() > 512
@@ -108,7 +116,12 @@ impl BoundCheck for ListSubmitRequest {
108116
}
109117
impl BoundCheck for ListTestcaseRequest {
110118
fn check(&self) -> bool {
111-
if let Some(list_testcase_request::Request::Paginator(x)) = &self.request {
119+
if self.size == 0
120+
|| self.size >= i32::MAX as u64
121+
|| self.offset.unsigned_abs() >= i32::MAX as u64
122+
{
123+
true
124+
} else if let Some(list_testcase_request::Request::Paginator(x)) = &self.request {
112125
x.len() > 512
113126
} else {
114127
false

0 commit comments

Comments
 (0)