feat(ws-org): add org_id scoping across ws entities
Add org_id fields and migrations for course, section, lianxi, piyue, and jihua/daka data paths, and enforce organization-scoped filtering in ws service queries. Made-with: Cursor
This commit is contained in:
+73
-17
@@ -14,6 +14,7 @@ use htycommons::common::{
|
||||
HtyErrCode, HtyResponse,
|
||||
};
|
||||
use htycommons::db::{exec_read_write_task, extract_conn, fetch_db_conn, DbState};
|
||||
use htycommons::jwt::jwt_decode_token;
|
||||
use htycommons::uuid;
|
||||
use htycommons::web::{
|
||||
wrap_json_anyhow_err, wrap_json_ok_resp, AuthorizationHeader, HtyHostHeader,
|
||||
@@ -30,6 +31,12 @@ use std::ops::DerefMut;
|
||||
use std::sync::Arc;
|
||||
use tracing::{debug, error};
|
||||
|
||||
fn required_current_org_id_from_sudoer_token_str(token_str: &String) -> anyhow::Result<String> {
|
||||
jwt_decode_token(token_str)?
|
||||
.current_org_id
|
||||
.ok_or_else(|| anyhow!("current_org_id is required"))
|
||||
}
|
||||
|
||||
pub async fn create_daka(
|
||||
root: HtySudoerTokenHeader,
|
||||
host: HtyHostHeader,
|
||||
@@ -54,6 +61,9 @@ pub async fn raw_create_daka(
|
||||
db_pool: Arc<DbState>,
|
||||
in_req_daka: &ReqDakaWithCourseSectionIds,
|
||||
) -> anyhow::Result<String> {
|
||||
let current_org_id = jwt_decode_token(&(*_token).clone())?
|
||||
.current_org_id
|
||||
.ok_or_else(|| anyhow!("current_org_id is required"))?;
|
||||
let req_daka = in_req_daka.clone();
|
||||
if req_daka.start_date.is_none()
|
||||
|| req_daka.duration_days.is_none()
|
||||
@@ -120,6 +130,7 @@ pub async fn raw_create_daka(
|
||||
students: req_daka.students.clone(),
|
||||
course_sections: req_daka.course_sections.clone(),
|
||||
is_yanqi: req_daka.is_yanqi.clone(),
|
||||
org_id: Some(current_org_id),
|
||||
};
|
||||
|
||||
let mut params = HashMap::new();
|
||||
@@ -168,6 +179,7 @@ pub fn raw_create_daka_tx(
|
||||
course_section_id: in_section_id,
|
||||
meta: Some(meta_data.clone()),
|
||||
is_delete: false,
|
||||
org_id: result_daka.org_id.clone(),
|
||||
};
|
||||
debug!("START CREATE DAKA QUMU SECTION -> {:?}", §ion);
|
||||
let created_section = DakaCourseSection::create(§ion, conn)?;
|
||||
@@ -220,8 +232,12 @@ pub async fn raw_find_daka_by_id2(
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<ReqDakaWithCourseSections2> {
|
||||
debug!("raw_find_daka_by_id2 -> {:?}", id);
|
||||
|
||||
let daka = Daka::find_by_id(&id, extract_conn(fetch_db_conn(&db_pool)?).deref_mut())?;
|
||||
let current_org_id = required_current_org_id_from_sudoer_token_str(&root.0)?;
|
||||
let daka = Daka::find_by_id_in_org(
|
||||
&id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
debug!("raw_find_daka_by_id2 -> daka: {:?}", id);
|
||||
|
||||
@@ -262,11 +278,17 @@ pub async fn raw_find_daka_by_id2(
|
||||
let any_relations: Vec<anyhow::Result<ReqDakaCourseSection>> = the_course_sections
|
||||
.iter()
|
||||
.map(|course_section| {
|
||||
let in_jihua_course_section = DakaCourseSection::find_by_daka_id_and_course_section_id(
|
||||
&daka.id,
|
||||
&course_section.id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
let daka_org_id = daka
|
||||
.org_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("daka.org_id is required"))?;
|
||||
let in_jihua_course_section =
|
||||
DakaCourseSection::find_by_daka_id_and_course_section_id_in_org(
|
||||
&daka.id,
|
||||
&course_section.id,
|
||||
daka_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
Ok(ReqDakaCourseSection {
|
||||
id: Some(in_jihua_course_section.id.clone()),
|
||||
daka_id: None,
|
||||
@@ -348,7 +370,12 @@ pub async fn raw_find_daka_by_id(
|
||||
id: &String,
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<ReqDakaWithCourseSections> {
|
||||
let daka = Daka::find_by_id(&id, extract_conn(fetch_db_conn(&db_pool)?).deref_mut())?;
|
||||
let current_org_id = required_current_org_id_from_sudoer_token_str(&root.0)?;
|
||||
let daka = Daka::find_by_id_in_org(
|
||||
&id,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
|
||||
let all_lianxis =
|
||||
daka.find_active_belonging_lianxis(extract_conn(fetch_db_conn(&db_pool)?).deref_mut())?;
|
||||
@@ -368,11 +395,17 @@ pub async fn raw_find_daka_by_id(
|
||||
let any_relations: Vec<anyhow::Result<ReqDakaCourseSection>> = the_course_sections
|
||||
.iter()
|
||||
.map(|course_section| {
|
||||
let in_jihua_course_section = DakaCourseSection::find_by_daka_id_and_course_section_id(
|
||||
&daka.id,
|
||||
&course_section.id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
let daka_org_id = daka
|
||||
.org_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("daka.org_id is required"))?;
|
||||
let in_jihua_course_section =
|
||||
DakaCourseSection::find_by_daka_id_and_course_section_id_in_org(
|
||||
&daka.id,
|
||||
&course_section.id,
|
||||
daka_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
Ok(ReqDakaCourseSection {
|
||||
id: Some(in_jihua_course_section.id.clone()),
|
||||
daka_id: None,
|
||||
@@ -471,6 +504,9 @@ pub async fn raw_update_daka(
|
||||
db_pool: Arc<DbState>,
|
||||
in_req_daka: &ReqDakaWithCourseSectionIds,
|
||||
) -> anyhow::Result<String> {
|
||||
let current_org_id = jwt_decode_token(&(*_token).clone())?
|
||||
.current_org_id
|
||||
.ok_or_else(|| anyhow!("current_org_id is required"))?;
|
||||
let the_req_daka = in_req_daka.clone();
|
||||
let id_daka = the_req_daka
|
||||
.clone()
|
||||
@@ -534,6 +570,7 @@ pub async fn raw_update_daka(
|
||||
db_daka.updated_at = c_req_daka.updated_at.clone();
|
||||
db_daka.course_sections = c_req_daka.course_sections.clone();
|
||||
db_daka.is_yanqi = c_req_daka.is_yanqi.clone();
|
||||
db_daka.org_id = Some(current_org_id.clone());
|
||||
|
||||
debug!("raw_update_daka -> update_daka -> {:?}", &db_daka);
|
||||
|
||||
@@ -596,9 +633,14 @@ pub fn raw_update_daka_course_section_relations(
|
||||
|
||||
// 首先做第一步
|
||||
// todo: 改为逻辑删除后,这里会重复查出来`已删除`关系,后续优化。
|
||||
let current_org_id = in_daka
|
||||
.org_id
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("daka.org_id is required"))?;
|
||||
let mut to_delete_relation_ids: Vec<String> = Vec::new();
|
||||
// 查找这个daka的所有course_section_ids,然后跟传入的做比对,把不存在于传入数据的ids放入`to_delete_relation_ids`,然后逻辑删除.
|
||||
let existing_daka_course_sections = DakaCourseSection::find_by_daka_id(daka_id, conn)?;
|
||||
let existing_daka_course_sections =
|
||||
DakaCourseSection::find_by_daka_id_in_org(daka_id, ¤t_org_id, conn)?;
|
||||
debug!(
|
||||
"raw_update_daka_course_section_relations -> existing_daka_course_sections -> {:?}",
|
||||
&existing_daka_course_sections
|
||||
@@ -627,9 +669,10 @@ pub fn raw_update_daka_course_section_relations(
|
||||
|
||||
// 然后做第二步
|
||||
for in_course_section_id in in_course_section_ids.clone() {
|
||||
match DakaCourseSection::find_by_daka_id_and_course_section_id(
|
||||
match DakaCourseSection::find_by_daka_id_and_course_section_id_in_org(
|
||||
&in_daka.id,
|
||||
&in_course_section_id,
|
||||
¤t_org_id,
|
||||
conn,
|
||||
) {
|
||||
Ok(rel) => {
|
||||
@@ -657,6 +700,7 @@ pub fn raw_update_daka_course_section_relations(
|
||||
course_section_id: in_course_section_id.clone(),
|
||||
meta: None,
|
||||
is_delete: false,
|
||||
org_id: in_daka.org_id.clone(),
|
||||
};
|
||||
debug!("raw_update_daka_course_section_relations -> ADDING THIS RELATION -> {:?}", & to_add_rel);
|
||||
let _ = DakaCourseSection::create(&to_add_rel, conn)?;
|
||||
@@ -674,12 +718,12 @@ pub fn raw_update_daka_course_section_relations(
|
||||
}
|
||||
|
||||
pub async fn delete_daka_by_id(
|
||||
_root: HtySudoerTokenHeader,
|
||||
root: HtySudoerTokenHeader,
|
||||
Path(id_delete): Path<String>,
|
||||
State(db_pool): State<Arc<DbState>>,
|
||||
) -> Json<HtyResponse<()>> {
|
||||
debug!("delete_daka_by_id -> start here");
|
||||
match raw_delete_daka_by_id(&id_delete, db_pool).await {
|
||||
match raw_delete_daka_by_id(&root, &id_delete, db_pool).await {
|
||||
Ok(ok) => wrap_json_ok_resp(ok),
|
||||
Err(e) => {
|
||||
error!("delete_daka_by_id -> failed to delete daka, e: {}", e);
|
||||
@@ -689,9 +733,16 @@ pub async fn delete_daka_by_id(
|
||||
}
|
||||
|
||||
pub async fn raw_delete_daka_by_id(
|
||||
root: &HtySudoerTokenHeader,
|
||||
id_delete: &String,
|
||||
db_pool: Arc<DbState>,
|
||||
) -> anyhow::Result<()> {
|
||||
let current_org_id = required_current_org_id_from_sudoer_token_str(&root.0)?;
|
||||
let _ = Daka::find_by_id_in_org(
|
||||
id_delete,
|
||||
¤t_org_id,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
)?;
|
||||
// 逻辑删除 daka
|
||||
let _ = Daka::logic_delete_by_id(
|
||||
id_delete,
|
||||
@@ -778,6 +829,7 @@ pub async fn raw_find_dakas_with_sections_by_user_id(
|
||||
) -> anyhow::Result<(Vec<ReqDakaWithCourseSections>, i64, i64)> {
|
||||
debug!("raw_find_dakas_with_sections_by_user_id -> START");
|
||||
debug!("raw_find_dakas_with_sections_by_user_id -> teacher_id: {:?} / student_id: {:?} / scope: {:?}", teacher_id, student_id, scope);
|
||||
let current_org_id = required_current_org_id_from_sudoer_token_str(&_root.0)?;
|
||||
|
||||
if (teacher_id.is_some() && student_id.is_some())
|
||||
|| (teacher_id.is_none() && student_id.is_none())
|
||||
@@ -799,6 +851,7 @@ pub async fn raw_find_dakas_with_sections_by_user_id(
|
||||
teacher_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("teacher_id is required"))?,
|
||||
¤t_org_id,
|
||||
page,
|
||||
page_size,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
@@ -809,6 +862,7 @@ pub async fn raw_find_dakas_with_sections_by_user_id(
|
||||
teacher_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("teacher_id is required"))?,
|
||||
¤t_org_id,
|
||||
page,
|
||||
page_size,
|
||||
start_from,
|
||||
@@ -821,6 +875,7 @@ pub async fn raw_find_dakas_with_sections_by_user_id(
|
||||
teacher_id
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow!("teacher_id is required"))?,
|
||||
¤t_org_id,
|
||||
page,
|
||||
page_size,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
@@ -850,6 +905,7 @@ pub async fn raw_find_dakas_with_sections_by_user_id(
|
||||
|
||||
dakas_with_pages = Daka::find_active_dakas_by_student_id_with_pagination(
|
||||
&id_student,
|
||||
¤t_org_id,
|
||||
page,
|
||||
page_size,
|
||||
extract_conn(fetch_db_conn(&db_pool)?).deref_mut(),
|
||||
|
||||
Reference in New Issue
Block a user