start implementing course uploads

This commit is contained in:
red binder 2026-06-18 01:22:02 +02:00
commit fe67373fd0
16 changed files with 722 additions and 15 deletions

View file

@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT owner, under_review FROM datastore.objects WHERE data_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "owner",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "under_review",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
true,
false
]
},
"hash": "164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9"
}

View file

@ -0,0 +1,112 @@
{
"db_name": "PostgreSQL",
"query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "owner",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "size",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "name",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "data_type",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "meta_binary",
"type_info": "Bytea"
},
{
"ordinal": 6,
"name": "permission",
"type_info": "Int4"
},
{
"ordinal": 7,
"name": "permission_recipients",
"type_info": "Int4Array"
},
{
"ordinal": 8,
"name": "delete_permission",
"type_info": "Int4"
},
{
"ordinal": 9,
"name": "delete_permission_recipients",
"type_info": "Int4Array"
},
{
"ordinal": 10,
"name": "period",
"type_info": "Int4"
},
{
"ordinal": 11,
"name": "refer_data_id",
"type_info": "Int8"
},
{
"ordinal": 12,
"name": "flag",
"type_info": "Int4"
},
{
"ordinal": 13,
"name": "tags",
"type_info": "TextArray"
},
{
"ordinal": 14,
"name": "creation_date",
"type_info": "Timestamp"
},
{
"ordinal": 15,
"name": "update_date",
"type_info": "Timestamp"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true
]
},
"hash": "1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703"
}

View file

@ -0,0 +1,38 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int4",
"Int4",
"Text",
"Int4",
"Bytea",
"Int4",
"Int4Array",
"Int4",
"Int4Array",
"Int4",
"Int4",
"Int8",
"TextArray",
"Int4",
"TextArray",
"Timestamp",
"Timestamp"
]
},
"nullable": [
false
]
},
"hash": "219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c"
}

View file

@ -0,0 +1,16 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8",
"Int8",
"Int8"
]
},
"nullable": []
},
"hash": "29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4"
}

View file

@ -0,0 +1,38 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int4",
"Int4",
"Text",
"Int4",
"Bytea",
"Int4",
"Int4Array",
"Int4",
"Int4Array",
"Int4",
"Int4",
"Int8",
"TextArray",
"Int4",
"TextArray",
"Timestamp",
"Timestamp"
]
},
"nullable": [
false
]
},
"hash": "2d025ae36b11518c43a0531c58f58e6c97c3f4726bae21e0cfaa8cc0ff218692"
}

View file

@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
null
]
},
"hash": "2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb"
}

View file

@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT data_id\n FROM datastore.objects\n WHERE owner = $1 AND data_type > 2 AND data_type < 50\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false
]
},
"hash": "37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92"
}

View file

@ -0,0 +1,23 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "buffer",
"type_info": "Bytea"
}
],
"parameters": {
"Left": [
"Int8",
"Int4"
]
},
"nullable": [
false
]
},
"hash": "3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f"
}

View file

@ -0,0 +1,24 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO datastore.object_ratings (\n data_id,\n slot,\n flag,\n internal_flag,\n lock_type,\n initial_value,\n range_min,\n range_max,\n period_hour,\n period_duration,\n total_value\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8",
"Int2",
"Int2",
"Int2",
"Int2",
"Int8",
"Int4",
"Int4",
"Int2",
"Int4",
"Int8"
]
},
"nullable": []
},
"hash": "744047264f63b5eac396d8c0606824f43eb87c2739404d423b2d94bb727ed1c9"
}

View file

@ -0,0 +1,29 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "value",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8Array",
"Int8"
]
},
"nullable": [
false,
true
]
},
"hash": "8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79"
}

View file

@ -0,0 +1,40 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "slot",
"type_info": "Int2"
},
{
"ordinal": 1,
"name": "total_value",
"type_info": "Int8"
},
{
"ordinal": 2,
"name": "count",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "initial_value",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false,
true,
false,
true
]
},
"hash": "8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d"
}

View file

@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "under_review",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "access_password",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
false,
false
]
},
"hash": "93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb"
}

View file

@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": []
},
"hash": "e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9"
}

View file

@ -0,0 +1,125 @@
{
"db_name": "PostgreSQL",
"query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "data_id",
"type_info": "Int8"
},
{
"ordinal": 1,
"name": "owner",
"type_info": "Int4"
},
{
"ordinal": 2,
"name": "size",
"type_info": "Int4"
},
{
"ordinal": 3,
"name": "name",
"type_info": "Text"
},
{
"ordinal": 4,
"name": "data_type",
"type_info": "Int4"
},
{
"ordinal": 5,
"name": "meta_binary",
"type_info": "Bytea"
},
{
"ordinal": 6,
"name": "permission",
"type_info": "Int4"
},
{
"ordinal": 7,
"name": "permission_recipients",
"type_info": "Int4Array"
},
{
"ordinal": 8,
"name": "delete_permission",
"type_info": "Int4"
},
{
"ordinal": 9,
"name": "delete_permission_recipients",
"type_info": "Int4Array"
},
{
"ordinal": 10,
"name": "period",
"type_info": "Int4"
},
{
"ordinal": 11,
"name": "refer_data_id",
"type_info": "Int8"
},
{
"ordinal": 12,
"name": "flag",
"type_info": "Int4"
},
{
"ordinal": 13,
"name": "tags",
"type_info": "TextArray"
},
{
"ordinal": 14,
"name": "creation_date",
"type_info": "Timestamp"
},
{
"ordinal": 15,
"name": "update_date",
"type_info": "Timestamp"
},
{
"ordinal": 16,
"name": "access_password",
"type_info": "Int8"
},
{
"ordinal": 17,
"name": "under_review",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Int4",
"Int4"
]
},
"nullable": [
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
false,
false
]
},
"hash": "efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c"
}

View file

@ -5,17 +5,13 @@ use rnex_core::executables::common::{
};
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::nex::s3presigner::S3Presigner;
use rnex_core::rmc::protocols::datastore::{
BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult,
DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo,
DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget,
RateCustomRankingParam, RatingInfo, RatingInfoWithSlot,
};
use rnex_core::rmc::protocols::datastore::{BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo, DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, RateCustomRankingParam, RatingInfo, RatingInfoWithSlot, RatingInitParamWithSlot};
use rnex_core::rmc::protocols::datastore::{DataStore, PreparePostParam, ReqPostInfo};
use rnex_core::rmc::response::ErrorCode;
use rnex_core::rmc::structures::qbuffer::QBuffer;
use rnex_core::rmc::structures::qresult::QResult;
use sqlx::types::time;
use crate::rmc::protocols::datastore::AttachFileParam;
fn map_row_to_meta_info(
row_data_id: i64,
@ -359,6 +355,45 @@ fn filter_properties_by_result_option(meta_info: &mut GetMetaInfo, result_option
// No idea what the other things do. :shrug:
}
async fn init_object_rating_slot(data_id: u64, rating_param: RatingInitParamWithSlot) {
let row = sqlx::query!(
r#"
INSERT INTO datastore.object_ratings (
data_id,
slot,
flag,
internal_flag,
lock_type,
initial_value,
range_min,
range_max,
period_hour,
period_duration,
total_value
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11
)
"#,
data_id as i64,
rating_param.slot as i16,
rating_param.param.flag as i16,
rating_param.param.internal_flag as i16,
rating_param.param.lock_type as i16,
rating_param.param.initial_value,
rating_param.param.range_min,
rating_param.param.range_max,
rating_param.param.period_hour as i16,
rating_param.param.period_duration as i32,
rating_param.param.initial_value,
)
.fetch_one(get_db())
.await
.map_err(|e| {
log::error!("DB Error: {:?}", e);
ErrorCode::DataStore_SystemFileError
});
}
// Dawg...
async fn get_custom_rankings_by_data_ids(
application_id: u32,
@ -438,7 +473,7 @@ async fn get_user_course_object_ids(owner_pid: PID) -> Result<Vec<u64>, ErrorCod
}
fn get_blacklist_1() -> Vec<String> {
[
vec![
"けされ",
"消され",
"削除され",
@ -506,13 +541,13 @@ fn get_blacklist_1() -> Vec<String> {
"PLEASE star",
"Bitte Sterne",
]
.iter()
.into_iter()
.map(String::from)
.collect()
}
fn get_blacklist_2() -> Vec<String> {
[
vec![
"ゼロから",
"0から",
"0から",
@ -521,13 +556,13 @@ fn get_blacklist_2() -> Vec<String> {
"東日本",
"大震",
]
.iter()
.into_iter()
.map(String::from)
.collect()
}
fn get_blacklist_3() -> Vec<String> {
[
vec![
"いいね",
"下さい",
"ください",
@ -590,7 +625,7 @@ fn get_blacklist_3() -> Vec<String> {
"ま/んこ",
"まん/こ",
]
.iter()
.into_iter()
.map(String::from)
.collect()
}
@ -845,7 +880,6 @@ impl DataStore for User {
&self,
custom_ranking_param: DataStoreGetCustomRankingByDataIDParam,
) -> Result<(Vec<DataStoreCustomRankingResult>, Vec<QResult>), ErrorCode> {
// use log instead
println!("appid: {:?}", custom_ranking_param.application_id);
println!("dataid list: {:?}", custom_ranking_param.data_id_list);
println!("result option: {:?}", custom_ranking_param.result_option);
@ -1041,4 +1075,106 @@ impl DataStore for User {
Ok((metas, results))
}
async fn prepare_attach_file(&self, param: AttachFileParam) -> Result<ReqPostInfo, ErrorCode> {
let recipient_ids: Vec<i32> = param
.post_param
.permission
.recipient_ids
.iter()
.map(|&id| id as i32)
.collect();
let del_recipient_ids: Vec<i32> = param
.post_param
.del_permission
.recipient_ids
.iter()
.map(|&id| id as i32)
.collect();
let tags: Vec<String> = param
.post_param
.tags
.iter()
.map(|t| t.to_string())
.collect();
let extra_data: Vec<String> = param
.post_param
.extra_data
.iter()
.map(|e| e.to_string())
.collect();
let now = time::OffsetDateTime::now_utc();
let db_now = time::PrimitiveDateTime::new(now.date(), now.time());
let row = sqlx::query!(
r#"
INSERT INTO datastore.objects (
owner, size, name, data_type, meta_binary,
permission, permission_recipients,
delete_permission, delete_permission_recipients,
flag, period, refer_data_id, tags,
persistence_slot_id, extra_data, creation_date, update_date
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17
) RETURNING data_id
"#,
self.pid as i32,
param.post_param.size as i32,
param.post_param.name,
param.post_param.data_type as i32,
&param.post_param.meta_binary.0,
param.post_param.permission.permission as i32,
&recipient_ids,
param.post_param.del_permission.permission as i32,
&del_recipient_ids,
param.post_param.flag as i32,
param.post_param.period as i32,
param.refer_data_id as i64, // The course's data ID being attached to
&tags,
param.post_param.persistence_init_param.persistence_slot_id as i32,
&extra_data,
db_now,
db_now
)
.fetch_one(get_db())
.await
.map_err(|e| {
log::error!("DB Error: {:?}", e);
ErrorCode::DataStore_SystemFileError
})?;
let data_id = row.data_id as u64;
for rating_param in &param.post_param.rating_init_params {
init_object_rating_slot(data_id, rating_param.clone())
.await
}
let presigner = S3Presigner::new(
&format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT),
format!("{}", *RNEX_DATASTORE_S3_BUCKET),
)
.await;
let key = format!("data/{}.jpg", data_id);
let (upload_url, fields) = presigner.generate_presigned_post(&key).await;
let form_fields = fields
.into_iter()
.map(|(k, v)| KeyValue { key: k, value: v })
.collect();
Ok(ReqPostInfo {
dataid: data_id,
url: upload_url,
request_headers: vec![],
form_fields,
root_ca_cert: vec![],
})
}
}

View file

@ -1,4 +1,4 @@
use macros::{RmcSerialize, method_id, rmc_proto};
use macros::{RmcSerialize, method_id, rmc_proto, rmc_struct};
use rnex_core::PID;
use rnex_core::kerberos::KerberosDateTime;
use rnex_core::rmc::response::ErrorCode;
@ -74,7 +74,7 @@ pub struct RatingInitParam {
pub flag: u8,
pub internal_flag: u8,
pub lock_type: u8,
pub intial_valie: i64,
pub initial_value: i64,
pub range_min: i32,
pub range_max: i32,
pub period_hour: i8,
@ -213,6 +213,13 @@ pub struct DataStoreSearchParam {
pub use_cache: bool,
}
#[derive(RmcSerialize, Clone)]
#[rmc_struct(0)]
pub struct AttachFileParam {
pub post_param: PreparePostParam,
pub refer_data_id: u64,
pub content_type: String,
}
#[rmc_proto(115)]
pub trait DataStore {
#[method_id(8)]
@ -263,4 +270,9 @@ pub trait DataStore {
&self,
application_id: u32,
) -> Result<Vec<String>, ErrorCode>;
#[method_id(59)]
async fn prepare_attach_file(
&self,
attach_file_param: AttachFileParam,
) -> Result<ReqPostInfo, ErrorCode>;
}